
    i                       d Z ddlmZ ddlZddlZddlmZ  ej        e          Z	dZ
ddZdddddddddZdddddZdddddZdd iZd!Ze d"e d#e d$e d%e d&e d'e d(e d)e d*e d+e d,e d-e d.d/Zd0ZdZdZ ej                    Zdad1Zdd3ZdZdZdZd4Zdd6Zdd9Zdd<Z dd>Z!dd@Z"ddAZ#ddCZ$ddGZ%dddMZ&dddNZ'dddPZ(ddRZ)	 	 ddd[Z*dd\Z+dd^Z,dd_Z-	 ddd`Z.ddeZ/ddfZ0ddhZ1ddiZ2ddkZ3ddlZ4ddnZ5ddoZ6ddpZ7ddrZ8	 	 	 	 	 dddzZ9	 	 	 	 	 	 ddd}Z:	 	 	 	 	 ddd~Z;	 	 	 	 	 	 dddZ<	 	 	 	 dddZ=ddZ>ddZ?efddZ@edfddZAddZBddZC	 	 dddZDddZEdS )us  
yuanbao_proto.py - Yuanbao WebSocket 协议编解码（纯 Python 实现）

协议层级：
  WebSocket frame
    └── ConnMsg (protobuf: trpc.yuanbao.conn_common.ConnMsg)
          ├── head: Head  (cmd_type, cmd, seq_no, msg_id, module, ...)
          └── data: bytes  (业务 payload，标准 protobuf)
                └── InboundMessagePush / SendC2CMessageReq / SendGroupMessageReq / ...
                      (trpc.yuanbao.yuanbao_conn.yuanbao_openclaw_proxy.*)

注意：conn 层（ConnMsg）本身是标准 protobuf，不是自定义二进制格式。
     conn.proto 注释里的自定义格式（magic+head_len+body_len）仅用于 quic/tcp，
     WebSocket 直接传 ConnMsg protobuf bytes（无粘包问题，每个 ws frame = 一条消息）。

实现方式：手写 varint / protobuf wire-format 编解码，不依赖第三方 protobuf 库。
    )annotationsN)OptionalFlabelstrdatabytesreturnNonec                    t           rmd                    d |d d         D                       }t          |          dk    rdnd}t                              d| t          |          ||z              d S d S )N c              3     K   | ]}|d V  	dS )02xN .0bs     D/home/ubuntu/.hermes/hermes-agent/gateway/platforms/yuanbao_proto.py	<genexpr>z_dbg.<locals>.<genexpr>$   s&      99!a::999999    @   z... z[yuanbao_proto] %s (%dB): %s)
DEBUG_MODEjoinlenloggerdebug)r   r   hex_strellipsiss       r   _dbgr   "   s     [((99tCRCy99999IINN553UCIIwQYGYZZZZZ[ [r   z trpc.yuanbao.conn_common.ConnMsgz$trpc.yuanbao.conn_common.AuthBindReqz$trpc.yuanbao.conn_common.AuthBindRspz trpc.yuanbao.conn_common.PingReqz trpc.yuanbao.conn_common.PingRspz#trpc.yuanbao.conn_common.KickoutMsgz%trpc.yuanbao.conn_common.DirectedPushz trpc.yuanbao.conn_common.PushMsg)ConnMsgAuthBindReqAuthBindRspPingReqPingRsp
KickoutMsgDirectedPushPushMsg         )RequestResponsePushPushAckz	auth-bindpingkickoutzupdate-meta)AuthBindPingKickout
UpdateMeta
ConnAccessconn_accessyuanbao_openclaw_proxyz.InboundMessagePushz.SendC2CMessageReqz.SendC2CMessageRspz.SendGroupMessageReqz.SendGroupMessageRspz.QueryGroupInfoReqz.QueryGroupInfoRspz.GetGroupMemberListReqz.GetGroupMemberListRspz.SendPrivateHeartbeatReqz.SendPrivateHeartbeatRspz.SendGroupHeartbeatReqz.SendGroupHeartbeatRsp)InboundMessagePushSendC2CMessageReqSendC2CMessageRspSendGroupMessageReqSendGroupMessageRspQueryGroupInfoReqQueryGroupInfoRspGetGroupMemberListReqGetGroupMemberListRspSendPrivateHeartbeatReqSendPrivateHeartbeatRspSendGroupHeartbeatReqSendGroupHeartbeatRsp   l    intc                 v    t           5  t          } t          dz   t          z  addd           n# 1 swxY w Y   | S )u9   生成递增序列号（线程安全，溢出时归零）r(   N)	_seq_lock_seq_counter_SEQ_MAX)vals    r   next_seq_norL   q   sz     
 5 5$q(H45 5 5 5 5 5 5 5 5 5 5 5 5 5 5 Js   .22   valuec                    | dk     r| dz  } g }	 | dz  }| dz  } | r|                     |dz             n|                     |           n<t          |          S )u(   将非负整数编码为 protobuf varintr       T         )appendr   )rN   outbitss      r   _encode_varintrW      s{    qyy**
Ct|! 	JJtd{####JJt ::r   postuple[int, int]c                    d}d}|t          |           k     rK| |         }|dz  }||dz  |z  z  }|dz  }|dz  sn(|dk    rt          d          |t          |           k     K||fS )u6   从 data[pos:] 解码 varint，返回 (value, new_pos)r   r(   rQ   rR   rS   r   zvarint too long)r   
ValueError)r   rX   resultshiftr   s        r   _decode_varintr^      s    FE
D		//Iq1t8%%
D 	B;;./// D		// 3;r   field_number	wire_typec                6    | dz  |z  }t          |          |z   S )u,   编码一个 protobuf field（tag + value）r*   )rW   )r_   r`   rN   tags       r   _encode_fieldrc      s$    1	
)C#&&r   sc                j    |                      d          }t          t          |                    |z   S )uH   编码 protobuf string 字段的 value 部分（length-prefixed UTF-8）utf-8)encoderW   r   )rd   encodeds     r   _encode_stringri      s,    hhwG#g,,'''11r   r   c                @    t          t          |                     | z   S )uA   编码 protobuf bytes 字段的 value 部分（length-prefixed）rW   r   r   s    r   _encode_bytesrm          #a&&!!A%%r   c                @    t          t          |                     | z   S )u)   编码嵌套 message（length-prefixed）rk   rl   s    r   _encode_messagerp      rn   r   "list[tuple[int, int, bytes | int]]c                   g }d}t          |           }||k     r(t          | |          \  }}|dz	  }|dz  }|t          k    r,t          | |          \  }}|                    |||f           n|t          k    r>t          | |          \  }}| |||z            }||z  }|                    |||f           n|t
          k    r+| ||dz            }|dz  }|                    |||f           nN|t          k    r+| ||dz            }|dz  }|                    |||f           nt          d| d|dz
             ||k     (|S )	u   
    解析 protobuf message 的所有字段，返回 [(field_number, wire_type, raw_value), ...]
    raw_value:
      - WT_VARINT: int
      - WT_LEN: bytes
      - WT_64BIT: bytes (8 bytes)
      - WT_32BIT: bytes (4 bytes)
    r   r*   rR         zunknown wire type z at pos r(   )r   r^   	WT_VARINTrT   WT_LENWT_64BITWT_32BITr[   )	r   fieldsrX   nrb   r_   r`   rK   lengths	            r   _parse_fieldsr|      s    F
CD		A
''!$,,Sax$J		!!%dC00HCMM<C89999&  (s33KFCsC&L()C6MCMM<C89999(""sC!G|$C1HCMM<C89999(""sC!G|$C1HCMM<C89999N)NNS1WNNOOO+ '', Mr   ry   listdict[int, list]c                r    i }| D ]1\  }}}|                     |g                               ||f           2|S )u\   将 fields 列表转为 {field_number: [value, ...]} 字典（repeated 字段会有多个）)
setdefaultrT   )ry   dfnwtrK   s        r   _fields_to_dictr      sJ    A / /B	R##RI....Hr   r   fdictdictr   defaultc                    |                      |          }|s|S |d         \  }}|t          k    r3t          |t          t          f          r|                    dd          S |S )u*   从 fields dict 取第一个 string 字段r   rf   replace)errors)getrv   
isinstancer   	bytearraydecoder   r   r   entriesr   rK   s         r   _get_stringr      sb    iimmG ajGB	V||
3	(:;;|zz')z444Nr   c                    |                      |          }|s|S |d         \  }}|t          k    rt          |t                    r|S |S )u*   从 fields dict 取第一个 varint 字段r   )r   ru   r   rF   r   s         r   _get_varintr      sL    iimmG ajGB	Y:c3//
Nr   r   c                    |                      |          }|s|S |d         \  }}|t          k    r+t          |t          t          f          rt          |          S |S )u1   从 fields dict 取第一个 bytes/message 字段r   )r   rv   r   r   r   r   s         r   
_get_bytesr      sX    iimmG ajGB	V||
3	(:;;|SzzNr   list[bytes]c                F    |                      |g           }d |D             S )u'   取所有 repeated bytes/message 字段c                H    g | ]\  }}|t           k    t          |           S r   )rv   r   )r   r   rK   s      r   
<listcomp>z'_get_repeated_bytes.<locals>.<listcomp>  s'    >>>72svE#JJr   )r   )r   r   r   s      r   _get_repeated_bytesr   
  s)    iiBG>>g>>>>r   cmd_typecmdseq_nomsg_idmoduleneed_ackboolstatusc           	     X   d}| dk    r&|t          dt          t          |                     z  }|r&|t          dt          t	          |                    z  }|dk    r&|t          dt          t          |                    z  }|r&|t          dt          t	          |                    z  }|r&|t          dt          t	          |                    z  }|r&|t          dt          t          d                    z  }|dk    r)|t          d	t          t          |d
z                      z  }|S )u   编码 ConnMsg.Headr   r   r(   r)   r*   rt   rM      
   rP   )rc   ru   rW   rv   ri   )r   r   r   r   r   r   r   bufs           r   _encode_headr   %  s#    C1}}}Q	>(+C+CDDD
 =}Qs(;(;<<<{{}Q	>&+A+ABBB @}Qv(>(>??? @}Qv(>(>??? >}Q	>!+<+<==={{}RN6DV;V,W,WXXXJr   c                :   t          t          |                     }t          |dd          t          |dd          t          |dd          t          |dd          t          |dd          t	          t          |dd                    t          |d	d          d
S )u!   解码 ConnMsg.Head，返回 dictr(   r   r)   r   r*   rt   rM   r   r   r   r   r   r   r   r   r   )r   r|   r   r   r   r   r   s     r   _decode_headr   A  s    M$//00Eq!,,5!R((eQ**eQ++eQ++UAq1122eR++  r   msg_typec                    t          | d|dd          }t          dt          t          |                    }|r&|t          dt          t	          |                    z  }t          d|           |S )u  
    编码 ConnMsg（简化接口，对应任务要求的签名）。

    Args:
        msg_type: cmd_type（CMD_TYPE 枚举值）
        seq_no:   序列号
        data:     内层 payload bytes（业务 protobuf）

    Returns:
        ConnMsg 编码后的 bytes
    r   )r   r   r   r   r   r(   r)   encode_conn_msgr   rc   rv   rp   rm   r   )r   r   r   
head_bytesr   s        r   r   r   O  s~       J 6?:#>#>
?
?C =}Qd(;(;<<<	C   Jr   c                    t          d|            t          t          |                     }t          |d          }t          |d          }|rt	          |          n	dddddddd}|d         |d	         ||d
S )u  
    解码 ConnMsg，返回 {msg_type, seq_no, data, head}。

    Returns:
        {
          "msg_type": int,      # cmd_type
          "seq_no":   int,
          "data":     bytes,    # 内层 payload
          "head":     dict,     # 完整 head 字段
        }
    decode_conn_msgr(   r)   r   r   Fr   r   r   )r   r   r   head)r   r   r|   r   r   )r   r   r   payloadr   s        r   r   r   i  s     		D!!!M$//00EE1%%J""G'1 <
###bArQ8 8D
 $x.	  r   c                    t          | |||||          }t          dt          t          |                    }|r&|t          dt          t	          |                    z  }t          d|           |S )u   
    编码完整的 ConnMsg（含 cmd/msg_id/module 等 head 字段）。
    比 encode_conn_msg 提供更多 head 控制。
    )r   r   r   r   r   r   r(   r)   encode_conn_msg_fullr   )	r   r   r   r   r   r   r   r   r   s	            r   r   r     s       J 6?:#>#>
?
?C =}Qd(;(;<<<	%%%Jr   servicemethodreq_idbodyc                Z    t          t          d         |t                      || |          S )us  
    将业务 payload 包装为 ConnMsg bytes。

    Args:
        service: 模块名（head.module），如 "yuanbao_openclaw_proxy"
        method:  命令字（head.cmd），如 "send_c2c_message"
        req_id:  消息 ID（head.msg_id）
        body:    已编码的业务 protobuf bytes

    Returns:
        ConnMsg bytes（可直接发送到 WebSocket）
    r+   r   r   r   r   r   r   )r   CMD_TYPErL   r   r   r   r   s       r   encode_biz_msgr     s6      )$}}   r   c                    t          |           }|d         }|d         |d         |d         |d         |d         t          d         k    |dS )	u  
    解码 ConnMsg bytes，返回业务层信息。

    Returns:
        {
          "service":     str,    # head.module
          "method":      str,    # head.cmd
          "req_id":      str,    # head.msg_id
          "body":        bytes,  # 内层 biz payload
          "is_response": bool,   # cmd_type == 1 (Response)
          "head":        dict,   # 完整 head
        }
    r   r   r   r   r   r   r,   )r   r   r   r   is_responser   )r   r   )r   r\   r   s      r   decode_biz_msgr     sZ     T""F&>D>u+x.vJ'8J+??  r   contentc                   d}dD ]P\  }}|                      |d          }|r3|t          |t          t          t	          |                              z  }QdD ]P\  }}|                      |d          }|r3|t          |t
          t          t          |                              z  }Q|                      d          pg D ]}d}dD ]P\  }}|                     |d          }	|	r3|t          |t
          t          t          |	                              z  }Q|                     dd          }
|
r&|t          d	t          t          |
                    z  }|t          d
t          t          |                    z  }|S )Nr   )r(   text)r)   uuid)rt   r   )rM   desc)r   ext)rR   sound)r   url)   	file_namer   )r*   image_format)	   index)   	file_sizer   image_info_array)r(   type)r)   size)r*   width)rt   heightr   rM   rs   )	r   rc   rv   ri   r   ru   rW   rF   rp   )r   r   r   keyvimgimg_bufifnikeyivr   s              r   _encode_msg_contentr     s   
C E EC KKR   	E=V^CFF-C-CDDDCI H HCKKQ 	H=Ys1vv0F0FGGGC{{-..4" 	B 	BP 	R 	RICq!!B R=iB9P9PQQQggeR   	E}Qs0C0CDDDG}Q(@(@AAAJr   c                   t          t          |                     }i }dD ]\  }}t          ||          }|r|||<   dD ]\  }}t          ||          }|r|||<   g }t	          |d          D ]m}t          t          |                    }i }	dD ]\  }
}t          ||
          }|r||	|<   t          |d          }|r||	d<   |	r|                    |	           n|r||d<   |S )Nr   r   rs   r   rM   r   r   )r   r|   r   r   r   rT   )r   r   r   r   r   r   imgs	img_bytesifdictr   r   r   r   r   s                 r   _decode_msg_contentr     sG   M$//00EG  C r"" 	GCLI  Cr"" 	GCLD(22  	 y!9!9::P 	 	ICVS))B D	&!$$ 	CJ 	KK +&*"#Nr   elementc                    d}|                      dd          }|r&|t          dt          t          |                    z  }|                      di           }|r5t	          |          }|t          dt          t          |                    z  }|S )Nr   r   r   r(   msg_contentr)   )r   rc   rv   ri   r   rp   )r   r   r   r   content_bytess        r   _encode_msg_body_elementr   1  s    
C{{:r**H B}Qx(@(@AAAkk-,,G H+G44}Q(F(FGGGJr   c                    t          t          |                     }t          |dd          }t          |d          }|rt	          |          ni }||dS )Nr(   r   r)   )r   r   )r   r|   r   r   r   )r   r   r   r   r   s        r   _decode_msg_body_elementr   =  s]    M$//00E5!R((Hua((M4AI!-000rG 999r   trace_idc                P    | sdS t          dt          t          |                     S )Nr   r(   )rc   rv   ri   )r   s    r   _encode_log_extr   I  s)     sFN8$<$<===r   c                |    t          t          |                     }t          |d          t          |d          dS )zDecode a single ImMsgSeq sub-message (field 17 of InboundMessagePush).

    ImMsgSeq proto fields:
      1: msg_seq (uint64)
      2: msg_id  (string)
    r(   r)   )msg_seqr   )r   r|   r   r   r   s     r   _decode_im_msg_seqr   O  sB     M$//00Eua((eQ''  r   c                ^    t          t          |                     }dt          |d          iS )Nr   r(   )r   r|   r   r   s     r   _decode_log_extr   ]  s,    M$//00EE1--..r   Optional[dict]c                v   	 t          d|            t          t          |                     }g }t          |d          D ]$}|                    t          |                     %t          |d          }|r#t          |                              dd          nd}t          |d          }d |D             pd}i d	t          |d
          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d          dt          |d           d!|d"t          |d#          d$t          |d%          d&t          |d'          d(|t          |d)          t          |d*          |d+}d, |                                D             S # t          $ r-}	t          rt                              d-|	           Y d}	~	dS d}	~	ww xY w).u  
    解析入站消息推送的 biz payload（InboundMessagePush proto bytes）。

    Args:
        data: ConnMsg.data 字段的 bytes（即 biz payload）

    Returns:
        {
          "from_account":  str,
          "to_account":    str (可选),
          "group_code":    str (可选，群消息才有),
          "group_id":      str (可选),
          "group_name":    str (可选),
          "msg_key":       str,
          "msg_id":        str,
          "msg_seq":       int,
          "msg_random":    int,
          "msg_time":      int,
          "sender_nickname": str,
          "msg_body":      [{"msg_type": str, "msg_content": dict}, ...],
          "callback_command": str,
          "cloud_custom_data": str,
          "bot_owner_id":  str,
          "claw_msg_type": int,
          "private_from_group_code": str,
          "trace_id":      str,
          "recall_msg_seq_list": [{"msg_seq": int, "msg_id": str}, ...] 或 None,
        }
        或 None（解析失败）
    zdecode_inbound_push input      r   r   rE   c                ,    g | ]}t          |          S r   )r   r   s     r   r   z'decode_inbound_push.<locals>.<listcomp>  s!    MMM1!44MMMr   Ncallback_commandr(   from_accountr)   
to_accountr*   sender_nicknamert   group_idrM   
group_coder   
group_namerR   r   rs   
msg_randomr   msg_timer   msg_keyr   r   r   msg_bodycloud_custom_data   
event_time   bot_owner_id   recall_msg_seq_list      )claw_msg_typeprivate_from_group_coder   c                &    i | ]\  }}|s|d v ||S ))r  r   r   r   kr   s      r   
<dictcomp>z'decode_inbound_push.<locals>.<dictcomp>  s.    UUUA1U=T8T8T18T8T8Tr   z.[yuanbao_proto] decode_inbound_push failed: %s)r   r   r|   r   rT   r   r   r   r   r   r   items	Exceptionr   r   r   )
r   r   r  el_byteslog_ext_bytesr   recall_seq_rawr  r\   es
             r   decode_inbound_pushr  }  s   >)($///d 3 344+E266 	@ 	@HOO4X>>????"5"--IV^?=1155j"EEE\^,UB77MMnMMMUQU
E1 5 5
Kq11
 +eQ//
 {5!44	

 E1--
 +eQ//
 +eQ//
 {5!,,
 +eQ//
 E2..
 {5"--
 k%,,
 
  UB!7!7
 +eR00
  Kr22!
" "#6#
$ )33'25"'='= )
 
 
. VUUUUU    	NLLI1MMMttttts   G>H 
H8"H33H8r   r   r  r  r   Optional[int]r   c           	        d}|r&|t          dt          t          |                    z  }|t          dt          t          |                     z  }|r&|t          dt          t          |                    z  }|r&|t          dt          t	          |                    z  }|D ]7}	t          |	          }
|t          dt          t          |
                    z  }8|r&|t          dt          t          |                    z  }|&|t          d	t          t	          |                    z  }|r5t          |          }|t          d
t          t          |                    z  }|S )uC  
    编码 SendC2CMessageReq biz payload。

    SendC2CMessageReq fields:
      1: msg_id (string)
      2: to_account (string)
      3: from_account (string)
      4: msg_random (uint32)
      5: msg_body (repeated MsgBodyElement)
      6: group_code (string)
      7: msg_seq (uint64)
      8: log_ext (LogInfoExt)
    r   r(   r)   r*   rt   rM   r   NrR   rs   )rc   rv   ri   ru   rW   r   rp   r   )r   r   r  r   r  r   r   r   r   elr  	log_bytess               r   _encode_send_c2c_reqr     s^   . C @}Qv(>(>???=FN:$>$>???C F}Q|(D(DEEE G}Q	>*+E+EFFF C C+B//}Q(A(ABBB D}Qz(B(BCCC}Q	>'+B+BCCC D#H--	}Q	(B(BCCCJr   random
ref_msg_idc	           	        d}	|r&|	t          dt          t          |                    z  }	|	t          dt          t          |                     z  }	|r&|	t          dt          t          |                    z  }	|r&|	t          dt          t          |                    z  }	|r&|	t          dt          t          |                    z  }	|D ]7}
t          |
          }|	t          dt          t	          |                    z  }	8|r&|	t          dt          t          |                    z  }	|&|	t          d
t
          t          |                    z  }	|r5t          |          }|	t          dt          t	          |                    z  }	|	S )u`  
    编码 SendGroupMessageReq biz payload。

    SendGroupMessageReq fields:
      1: msg_id (string)
      2: group_code (string)
      3: from_account (string)
      4: to_account (string)
      5: random (string)
      6: msg_body (repeated MsgBodyElement)
      7: ref_msg_id (string)
      8: msg_seq (uint64)
      9: log_ext (LogInfoExt)
    r   r(   r)   r*   rt   rM   r   rR   Nrs   r   )rc   rv   ri   r   rp   ru   rW   r   )r   r   r  r   r   r!  r   r"  r   r   r  r  r  s                r   _encode_send_group_reqr$    s   2 C @}Qv(>(>???=FN:$>$>???C F}Q|(D(DEEE D}Qz(B(BCCC @}Qv(>(>??? C C+B//}Q(A(ABBB D}Qz(B(BCCC}Q	>'+B+BCCC D#H--	}Q	(B(BCCCJr   c           
         t          | |||||||          }t          d|           |pdt                       }	t          t          d         dt                      |	t
          |          S )u  
    编码 C2C 发消息请求，返回完整 ConnMsg bytes（可直接发送到 WebSocket）。

    Args:
        to_account:   收件人账号
        msg_body:     消息体列表，每个元素: {"msg_type": str, "msg_content": dict}
                      例如: [{"msg_type": "TIMTextElem", "msg_content": {"text": "hello"}}]
        from_account: 发件人账号（机器人账号）
        msg_id:       消息唯一 ID（空时使用 req_id）
        msg_random:   随机数（防重）
        msg_seq:      消息序列号（可选）
        group_code:   来自群聊的私聊场景时填写
        trace_id:     链路追踪 ID

    Returns:
        ConnMsg bytes
    )r   r   r  r   r  r   r   r   zencode_send_c2c biz payloadc2c_r+   send_c2c_messager   )r   r   rL   r   r   _BIZ_PKG)
r   r  r   r   r  r   r   r   	biz_bytesr   s
             r   encode_send_c2c_messager*  (  s    6 %!	 	 	I 		&	222--kmm--F)$}}   r   c	                    t          | ||||||||	  	        }	t          d|	           |pdt                       }
t          t          d         dt                      |
t
          |	          S )u  
    编码群消息发送请求，返回完整 ConnMsg bytes（可直接发送到 WebSocket）。

    Args:
        group_code:   群号
        msg_body:     消息体列表
        from_account: 发件人账号（机器人账号）
        msg_id:       消息唯一 ID
        to_account:   指定接收者（一般为空）
        random:       去重随机字符串
        msg_seq:      消息序列号
        ref_msg_id:   引用消息 ID
        trace_id:     链路追踪 ID

    Returns:
        ConnMsg bytes
    )	r   r   r  r   r   r!  r   r"  r   zencode_send_group biz payloadgrp_r+   send_group_messager   )r$  r   rL   r   r   r(  )r   r  r   r   r   r!  r   r"  r   r)  r   s              r   encode_send_group_messager.  Y  s    8 '!
 
 
I 		()444--kmm--F)$ }}   r   biz_iduidsourcetokenapp_versionoperation_systembot_version	route_envc	           
        t          dt          t          |                    t          dt          t          |                    z   t          dt          t          |                    z   }	d}
|r&|
t          dt          t          |                    z  }
|r&|
t          dt          t          |                    z  }
|
t          dt          t          t          t                                        z  }
|r&|
t          dt          t          |                    z  }
t          dt          t          |                     t          dt          t          |	                    z   t          dt          t          |
                    z   }|r&|t          dt          t          |                    z  }t          t          d         t          d	         t                      |t          d
         |          S )u0  
    构造 auth-bind 请求 ConnMsg bytes。

    AuthBindReq fields:
      1: biz_id (string)
      2: auth_info (message AuthInfo: uid=1, source=2, token=3)
      3: device_info (message DeviceInfo: app_version=1, app_operation_system=2, instance_id=10, bot_version=24)
      5: env_name (string)
    r(   r)   r*   r   r      rM   r+   r1   r5   r   )rc   rv   ri   r   HERMES_INSTANCE_IDrp   r   r   CMDrL   MODULE)r/  r0  r1  r2  r   r3  r4  r5  r6  auth_bufdev_bufreq_bufs               r   encode_auth_bindr?    s   , 	a!4!455
6>&#9#9
:
:	;
6>%#8#8
9
9	:  G I=FN;,G,GHHH N=FN;K,L,LMMM}R<N8O8O)P)PQQQG J=V^K-H-HIII 	a!7!788
6?8#<#<
=
=	>
6?7#;#;
<
<	= 
  G=FN9,E,EFFF)$
O}}l#   r   c                    t          t          d         t          d         t                      | t          d         d          S )u:   构造 ping 请求 ConnMsg bytes（PingReq 为空消息）r+   r2   r5   r   r   )r   r   r:  rL   r;  )r   s    r   encode_pingrA    s=    )$K}}l#   r   original_headc           
         t          t          d         |                     dd          t                      |                     dd          |                     dd          d          S )u   构造 push ACK 回包r.   r   r   r   r   r   r   )r   r   r   rL   )rB  s    r   encode_push_ackrD    sd    )$eR((}}  2..  2..   r   	heartbeatc                *   t          dt          t          |                     t          dt          t          |                    z   t          dt          t	          |                    z   }dt                       }t          t          d||          S )u   
    编码 SendPrivateHeartbeatReq，返回完整 ConnMsg bytes。

    SendPrivateHeartbeatReq fields:
      1: from_account (string)
      2: to_account   (string)
      3: heartbeat    (varint: RUNNING=1, FINISH=2)
    r(   r)   r*   hb_priv_send_private_heartbeatr   rc   rv   ri   ru   rW   rL   r   r(  )r   r   rE  r   r   s        r   encode_send_private_heartbeatrJ    s     	a!=!=>>
6>*#=#=
>
>	?
9nY&?&?
@
@	A 
 (''F'	   r   	send_timec                   ddl }|p#t          |                                 dz            }t          dt          t	          |                     t          dt          t	          d                    z   t          dt          t	          |                    z   t          dt
          t          |                    z   t          d	t
          t          |                    z   }d
t                       }t          t          d||          S )u;  
    编码 SendGroupHeartbeatReq，返回完整 ConnMsg bytes。

    SendGroupHeartbeatReq fields:
      1: from_account (string)
      2: to_account   (string)  — 群场景留空
      3: group_code   (string)
      4: send_time    (int64, ms timestamp)
      5: heartbeat    (varint: RUNNING=1, FINISH=2)
    r   Ni  r(   r)   r   r*   rt   rM   hb_grp_send_group_heartbeatr   )
timerF   rc   rv   ri   ru   rW   rL   r   r(  )r   r   rE  rK  _timetsr   r   s           r   encode_send_group_heartbeatrR    s      		.c%**,,-..Ba!=!=>>
6>"#5#5
6
6	7
6>*#=#=
>
>	? 9nR&8&8
9
9	: 9nY&?&?
@
@		A  '{}}&&F%	   r   c                    t          dt          t          |                     }dt                       }t	          t
          d||          S )u~   
    编码 QueryGroupInfoReq，返回完整 ConnMsg bytes。

    QueryGroupInfoReq fields:
      1: group_code (string)
    r(   qgi_query_group_infor   )rc   rv   ri   rL   r   r(  )r   r   r   s      r   encode_query_group_inforV  #  sQ     6>*#=#=
>
>C#KMM##F!	   r   c                N   	 t          t          |                     }t          |dd          }t          |d          }d|i}|r||d<   |                    dg           }|r|d         d         nd}|rt          |t          t          f          rpt          t          |                    }t          |d          pd|d	<   t          |d          pd|d
<   t          |d          pd|d<   t          |dd          |d<   nd|d	<   d|d
<   d|d<   d|d<   |S # t          $ r Y dS w xY w)u)  
    解码 QueryGroupInfoRsp biz payload。

    Proto 结构（对齐 TS biz-codec / member.ts queryGroupInfo）：

      message QueryGroupInfoRsp {
        int32  code       = 1;
        string message    = 2;
        GroupInfo group_info = 3;   // 嵌套 message
      }

      message GroupInfo {
        string group_name            = 1;
        string group_owner_user_id   = 2;
        string group_owner_nickname  = 3;
        uint32 group_size            = 4;
      }

    Returns:
        解码后的 dict，或 None（解析失败）
    r(   r   r)   codemessager*   r   r   r  owner_idowner_nicknamert   member_countN)	r   r|   r   r   r   r   r   r   r  )r   r   rX  msgr\   
gi_entriesgi_bytesgis           r   decode_query_group_info_rspra  4  sl   ,d 3 3445!Q''%##~ 	$ #F9 YYq"%%
'1::a=##s 
	'
8eY-?@@ 
	' x!8!899B#.r1#5#5#;F< !,R!3!3!9rF:'22q'9'9'?RF#$%0Q%:%:F>""#%F< !#F:')F#$%&F>"   tts   DD 
D$#D$   offsetlimitc                6   t          dt          t          |                     }|r&|t          dt          t	          |                    z  }|t          dt          t	          |                    z  }dt                       }t          t          d||          S )u   
    编码 GetGroupMemberListReq，返回完整 ConnMsg bytes。

    GetGroupMemberListReq fields:
      1: group_code (string)
      2: offset     (uint32)
      3: limit      (uint32)
    r(   r)   r*   gml_get_group_member_listr   rI  )r   rc  rd  r   r   s        r   encode_get_group_member_listrh  k  s     6>*#=#=
>
>C C}Q	>&+A+ABBB=I~e'<'<===C#KMM##F&	   r   c           
     ^   	 t          t          |                     }t          |dd          }g }t          |d          D ]}t          t          |                    }t	          |d          t	          |d          t          |d          t          |d          t	          |d          d}|                    d |                                D                        |t	          |d          |t          |d          t          t          |d                    d	S # t          $ r Y d
S w xY w)u  
    解码 GetGroupMemberListRsp biz payload。

    GetGroupMemberListRsp fields:
      1: code         (int32)
      2: message      (string)
      3: members      (repeated message MemberInfo)
      4: next_offset  (uint32)
      5: is_complete  (bool/varint)

    MemberInfo fields:
      1: user_id      (string)
      2: nickname     (string)
      3: role         (uint32)  — 0=member, 1=admin, 2=owner
      4: join_time    (uint32)
      5: name_card    (string)  — 群昵称

    Returns:
        {
          "code": int,
          "message": str,
          "members": [{"user_id": str, "nickname": str, "role": int, ...}, ...],
          "next_offset": int,
          "is_complete": bool,
        }
        或 None（解析失败）
    r(   r   r*   r)   rt   rM   )user_idnicknamerole	join_time	name_cardc                *    i | ]\  }}|s|d k    ||S )rl  r   r  s      r   r  z4decode_get_group_member_list_rsp.<locals>.<dictcomp>  s(    PPPTQqPAKKAqKKKr   )rX  rY  membersnext_offsetis_completeN)	r   r|   r   r   r   rT   r  r   r  )r   r   rX  rp  member_bytesmdictmembers          r    decode_get_group_member_list_rsprv    sG   8d 3 3445!Q''/q99 		R 		RL#M,$?$?@@E&ua00'q11#E1--(22(22 F NNPPV\\^^PPPQQQQ "5!,,&ua00E1 5 566
 
 	
    tts   DD 
D,+D,)r   r   r   r   r	   r
   )r	   rF   )rN   rF   r	   r   )r   r   rX   rF   r	   rY   )r_   rF   r`   rF   rN   r   r	   r   )rd   r   r	   r   )r   r   r	   r   )r   r   r	   rq   )ry   r}   r	   r~   )r   )r   r   r   rF   r   r   r	   r   )r   )r   r   r   rF   r   rF   r	   rF   )r   )r   r   r   rF   r   r   r	   r   )r   r   r   rF   r	   r   )Fr   )r   rF   r   r   r   rF   r   r   r   r   r   r   r   rF   r	   r   )r   r   r	   r   )r   rF   r   rF   r   r   r	   r   )F)r   rF   r   r   r   rF   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   Nr   r   )r   r   r   r   r  r}   r   r   r  rF   r   r  r   r   r   r   r	   r   )r   r   r   Nr   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  rF   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   r0  r   r1  r   r2  r   r   r   r3  r   r4  r   r5  r   r6  r   r	   r   )r   r   r	   r   )rB  r   r	   r   )r   r   r   r   rE  rF   r	   r   )
r   r   r   r   rE  rF   rK  rF   r	   r   )r   r   r	   r   )r   rb  )r   r   rc  rF   rd  rF   r	   r   )F__doc__
__future__r   logging	threadingtypingr   	getLogger__name__r   r   r   PB_MSG_TYPESr   r:  r;  r(  BIZ_SERVICESr9  WS_HEARTBEAT_RUNNINGWS_HEARTBEAT_FINISHLockrH   rI   rJ   rL   ru   rw   rv   rx   rW   r^   rc   ri   rm   rp   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?  rA  rD  rJ  rR  rV  ra  rh  rv  r   r   r   <module>r     s   $ # " " " " "           		8	$	$ 
[ [ [ [ 299117;1	 	 	  	  -
 $%:::$888$888&<<<&<<<$888$888 (@@@ (@@@"*DDD"*DDD (@@@ (@@@ "      IN	    		
   "    ' ' ' '2 2 2 2& & & &
& & & &
" " " "J               ? ? ? ?B     8      4   F     P   .   Z   6   J	 	 	 	: : : :> > > >   / / / /@H H H Hf !) ) ) ) )` !- - - - -h !. . . . .j !0 0 0 0 0z 3 3 3 3 3l	 	 	 		 	 	 	& *    < *	    L   "0 0 0 0r     44 4 4 4 4 4r   