Skip to content

Commit 29ee9a9

Browse files
ernadoclaude
andcommitted
docs(example): note required "Reply to messages" business permission
BUSINESS_PEER_INVALID was the bot lacking message permissions, not a code issue: enable "Reply to messages" (and others) under Settings → Business → Chatbots → Chat Automation. Document it in the business example and remove the temporary peer/connection diagnostics now that the cause is known. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 75a4736 commit 29ee9a9

2 files changed

Lines changed: 5 additions & 58 deletions

File tree

business_updates.go

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ 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)
6665
}
6766

6867
u := &Update{}
@@ -75,46 +74,6 @@ func (b *Bot) dispatchBusinessMessage(ctx context.Context, e tg.Entities, connec
7574
b.route(ctx, u)
7675
}
7776

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().Debug(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-
11877
// inputPeerFromEntities builds the input peer for a message's chat from the
11978
// access hashes delivered with the update, so a business send addresses the chat
12079
// with the account's own access hash. Returns nil when the peer is absent.

examples/business/main.go

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
// this bot. That delivers the account's 1-to-1 chats to the bot over a
1212
// business connection.
1313
//
14+
// IMPORTANT: under "Chat Automation", enable "Reply to messages" (and the
15+
// other permissions you want the bot to use — manage profile, gifts, …).
16+
// Without the reply permission, sending on behalf of the account fails with
17+
// 400 BUSINESS_PEER_INVALID even though everything else is correct.
18+
//
1419
// 3. From another account, write to the business account. Plain text is echoed
1520
// back (as the account). Messages starting with "!" are commands:
1621
//
@@ -137,23 +142,6 @@ func handleBusiness(log *zap.Logger) botapi.Handler {
137142
return nil
138143
}
139144

140-
// Diagnostic: fetch the connection (a read, never a business send) to see
141-
// the owner id and granted rights, and whether we are about to reply to
142-
// the owner themselves (an invalid business peer).
143-
if conn, err := bc.Connection(c); err == nil {
144-
canReply := conn.Rights != nil && conn.Rights.CanReply
145-
log.Info("Business connection state",
146-
zap.String("connection", conn.ID),
147-
zap.Int64("owner_id", conn.User.ID),
148-
zap.Bool("enabled", conn.IsEnabled),
149-
zap.Bool("can_reply", canReply),
150-
zap.Int64("reply_peer", bm.Chat.ID),
151-
zap.Bool("reply_peer_is_owner", conn.User.ID == bm.Chat.ID),
152-
)
153-
} else {
154-
log.Warn("Get business connection", zap.Error(err))
155-
}
156-
157145
log.Info("Business message",
158146
zap.String("connection", bc.ConnectionID()),
159147
zap.Int64("chat", bm.Chat.ID),

0 commit comments

Comments
 (0)