@@ -179,7 +179,13 @@ func (m *weixinGatewayManager) onIncomingMessage(msg weixin.IncomingMessage) {
179179 return
180180 }
181181
182- if cfg .IsWeixinLocalMode () {
182+ isLocal := cfg .IsWeixinLocalMode ()
183+ hubClient := m .app .hubClient ()
184+ hubNil := hubClient == nil
185+ hubConn := ! hubNil && hubClient .IsConnected ()
186+ log .Printf ("[weixin-mgr] onIncomingMessage: user=%s local_mode=%v hub_nil=%v hub_connected=%v" , msg .FromUserID , isLocal , hubNil , hubConn )
187+
188+ if isLocal {
183189 m .handleLocalMessage (msg )
184190 return
185191 }
@@ -191,19 +197,7 @@ func (m *weixinGatewayManager) onIncomingMessage(msg weixin.IncomingMessage) {
191197func (m * weixinGatewayManager ) forwardToHub (msg weixin.IncomingMessage ) {
192198 hubClient := m .app .hubClient ()
193199 if hubClient == nil || ! hubClient .IsConnected () {
194- log .Printf ("[weixin-mgr] hub not connected, cannot forward WX message from user=%s" , msg .FromUserID )
195- m .mu .Lock ()
196- gw := m .gateway
197- m .mu .Unlock ()
198- if gw != nil {
199- if err := gw .SendText (context .Background (), weixin.OutgoingText {
200- ToUserID : msg .FromUserID ,
201- Text : "⚠️ Hub 未连接,无法处理消息。" ,
202- ContextToken : msg .ContextToken ,
203- }); err != nil {
204- log .Printf ("[weixin-mgr] failed to send hub-disconnected notice to user=%s: %v" , msg .FromUserID , err )
205- }
206- }
200+ log .Printf ("[weixin-mgr] forwardToHub FAILED: hub_nil=%v user=%s" , hubClient == nil , msg .FromUserID )
207201 return
208202 }
209203
@@ -227,7 +221,11 @@ func (m *weixinGatewayManager) forwardToHub(msg weixin.IncomingMessage) {
227221 payload ["context_token" ] = msg .ContextToken
228222 }
229223
230- hubClient .SendIMGatewayMessage ("weixin" , payload )
224+ if err := hubClient .SendIMGatewayMessage ("weixin" , payload ); err != nil {
225+ log .Printf ("[weixin-mgr] forwardToHub SendIMGatewayMessage error: %v" , err )
226+ } else {
227+ log .Printf ("[weixin-mgr] forwardToHub OK: user=%s text=%q" , msg .FromUserID , truncateForLog (msg .Text , 30 ))
228+ }
231229}
232230
233231// ---------------------------------------------------------------------------
@@ -600,7 +598,51 @@ func (m *weixinGatewayManager) saveMediaToTemp(msg weixin.IncomingMessage) (stri
600598 return p , nil
601599}
602600
603- // mediaLabel returns a Chinese label for the media type.
601+ // sendDiag sends a diagnostic message to the WeChat user for remote debugging.
602+ func (m * weixinGatewayManager ) sendDiag (toUserID , contextToken , text string ) {
603+ m .mu .Lock ()
604+ gw := m .gateway
605+ m .mu .Unlock ()
606+ if gw == nil {
607+ return
608+ }
609+ _ = gw .SendText (context .Background (), weixin.OutgoingText {
610+ ToUserID : toUserID ,
611+ Text : text ,
612+ ContextToken : contextToken ,
613+ })
614+ }
615+
616+ // BroadcastDiag sends a diagnostic message to the last known WeChat user.
617+ // Used when we don't have a specific user ID (e.g. claim result callback).
618+ func (m * weixinGatewayManager ) BroadcastDiag (text string ) {
619+ m .mu .Lock ()
620+ gw := m .gateway
621+ m .mu .Unlock ()
622+ if gw == nil {
623+ return
624+ }
625+ // Use gateway's last known user for broadcast
626+ lastUID := gw .LastActiveUserID ()
627+ if lastUID == "" {
628+ log .Printf ("[weixin-mgr] BroadcastDiag: no last active user, dropping: %s" , text )
629+ return
630+ }
631+ _ = gw .SendText (context .Background (), weixin.OutgoingText {
632+ ToUserID : lastUID ,
633+ Text : text ,
634+ })
635+ }
636+
637+ // truncateForLog truncates a string for log output.
638+ func truncateForLog (s string , maxRunes int ) string {
639+ runes := []rune (s )
640+ if len (runes ) <= maxRunes {
641+ return s
642+ }
643+ return string (runes [:maxRunes ]) + "..."
644+ }
645+
604646func mediaLabel (mediaType string ) string {
605647 switch mediaType {
606648 case "image" :
@@ -618,10 +660,12 @@ func mediaLabel(mediaType string) string {
618660
619661// HandleGatewayReply dispatches a reply from Hub to the WeChat API.
620662func (m * weixinGatewayManager ) HandleGatewayReply (reply GatewayReplyPayload ) {
663+ log .Printf ("[weixin-mgr] HandleGatewayReply: type=%s uid=%s text_len=%d" , reply .ReplyType , reply .PlatformUID , len (reply .Text ))
621664 m .mu .Lock ()
622665 gw := m .gateway
623666 m .mu .Unlock ()
624667 if gw == nil {
668+ log .Printf ("[weixin-mgr] HandleGatewayReply: gateway is nil, dropping reply" )
625669 return
626670 }
627671
@@ -743,6 +787,8 @@ func (a *App) SetWeixinLocalMode(enabled bool) error {
743787 if err := a .SaveConfig (cfg ); err != nil {
744788 return err
745789 }
790+ log .Printf ("[weixin-mgr] SetWeixinLocalMode: enabled=%v (local_mode after save: %v)" , enabled , cfg .IsWeixinLocalMode ())
791+
746792 // Invalidate cached local handler so it's recreated on next message.
747793 if a .weixinGateway != nil {
748794 a .weixinGateway .resetLocalHandler ()
@@ -753,9 +799,14 @@ func (a *App) SetWeixinLocalMode(enabled bool) error {
753799 // send the gateway claim so Hub registers this machine as the owner.
754800 if ! enabled {
755801 hubClient := a .hubClient ()
802+ hubNil := hubClient == nil
803+ hubConnected := ! hubNil && hubClient .IsConnected ()
804+ log .Printf ("[weixin-mgr] switching to hub mode: hub_nil=%v hub_connected=%v" , hubNil , hubConnected )
756805 if hubClient != nil && hubClient .IsConnected () {
757806 hubClient .SendIMGatewayClaim ("weixin" )
758807 log .Printf ("[weixin-mgr] sent gateway claim after switching to hub mode" )
808+ } else {
809+ log .Printf ("[weixin-mgr] WARNING: cannot send gateway claim, hub not available" )
759810 }
760811 }
761812 return nil
0 commit comments