Skip to content

Commit fda2a70

Browse files
ernadoclaude
andcommitted
chore: log business message peer diagnostic
Temporary: log how a business message's send peer resolves (present in the update entities? access hash / min flag?) to pin down why a reply gets BUSINESS_PEER_INVALID. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c4a583f commit fda2a70

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

business_updates.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ func (b *Bot) dispatchBusinessMessage(ctx context.Context, e tg.Entities, connec
6262
m.BusinessConnectionID = connectionID
6363
if m.raw != nil {
6464
m.businessPeer = inputPeerFromEntities(m.raw.PeerID, e)
65+
b.logBusinessPeerDiag(ctx, m.raw.PeerID, e, m.businessPeer)
6566
}
6667

6768
u := &Update{}
@@ -74,6 +75,46 @@ func (b *Bot) dispatchBusinessMessage(ctx context.Context, e tg.Entities, connec
7475
b.route(ctx, u)
7576
}
7677

78+
// logBusinessPeerDiag logs how a business message's send peer was (or was not)
79+
// resolved, to diagnose BUSINESS_PEER_INVALID: whether the peer was present in
80+
// the update's entities, and the access hash / min flag carried there.
81+
func (b *Bot) logBusinessPeerDiag(ctx context.Context, peer tg.PeerClass, e tg.Entities, resolved tg.InputPeerClass) {
82+
fields := []log.Attr{
83+
log.String("raw_peer", peerKindString(peer)),
84+
log.Bool("resolved_from_entities", resolved != nil),
85+
log.Int("entity_users", len(e.Users)),
86+
log.Int("entity_chats", len(e.Chats)),
87+
log.Int("entity_channels", len(e.Channels)),
88+
}
89+
90+
if pu, ok := peer.(*tg.PeerUser); ok {
91+
if u, ok := e.Users[pu.UserID]; ok {
92+
fields = append(fields,
93+
log.Int64("entity_access_hash", u.AccessHash),
94+
log.Bool("entity_min", u.Min),
95+
)
96+
} else {
97+
fields = append(fields, log.Bool("user_in_entities", false))
98+
}
99+
}
100+
101+
b.logger().Info(ctx, "Business peer diagnostic", fields...)
102+
}
103+
104+
// peerKindString describes a peer for diagnostics.
105+
func peerKindString(peer tg.PeerClass) string {
106+
switch peer.(type) {
107+
case *tg.PeerUser:
108+
return peerKindUser
109+
case *tg.PeerChat:
110+
return peerKindChat
111+
case *tg.PeerChannel:
112+
return peerKindChannel
113+
default:
114+
return "none"
115+
}
116+
}
117+
77118
// inputPeerFromEntities builds the input peer for a message's chat from the
78119
// access hashes delivered with the update, so a business send addresses the chat
79120
// with the account's own access hash. Returns nil when the peer is absent.

0 commit comments

Comments
 (0)