Skip to content

Commit 6f2c6ed

Browse files
ernadoclaude
andcommitted
fix: unpack business-account send responses
A send on behalf of a business account returns the sent message wrapped in updateBotNewBusinessMessage (or updateBotEditBusinessMessage), which unpack.MessageClass rejects as a "bad updates result". Extract the message from those update types in the single-send fallback and the album unpacker, so SendMessage/SendPhoto/SendMediaGroup as the account return the sent message instead of erroring. Tests now use the real business response shape. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 29ee9a9 commit 6f2c6ed

4 files changed

Lines changed: 43 additions & 8 deletions

File tree

business_media_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func businessAlbumHandler(t *testing.T, connSeen *string) func(*bin.Buffer) (bin
4242

4343
return m, nil
4444
case tg.MessagesSendMultiMediaRequestTypeID:
45-
return multiMessageUpdates(11, 12), nil
45+
return multiBusinessMessageUpdates(11, 12), nil
4646
default:
4747
return nil, fmt.Errorf("unexpected inner request %#x", inner)
4848
}
@@ -51,7 +51,7 @@ func businessAlbumHandler(t *testing.T, connSeen *string) func(*bin.Buffer) (bin
5151

5252
func TestSendPhotoWithBusinessConnection(t *testing.T) {
5353
inv := newMockInvoker()
54-
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, sendMediaOK())
54+
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, businessSendReply())
5555

5656
b := newMockBot(inv)
5757

@@ -85,7 +85,7 @@ func TestSendPhotoWithBusinessConnection(t *testing.T) {
8585

8686
func TestSendDocumentWithBusinessConnection(t *testing.T) {
8787
inv := newMockInvoker()
88-
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, sendMediaOK())
88+
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, businessSendReply())
8989

9090
b := newMockBot(inv)
9191

@@ -116,7 +116,7 @@ func TestSendPhotoByFileIDWithBusinessConnection(t *testing.T) {
116116
fid := documentFileID(t, 0x91)
117117

118118
inv := newMockInvoker()
119-
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, sendMediaOK())
119+
inv.reply(tg.InvokeWithBusinessConnectionRequestTypeID, businessSendReply())
120120

121121
b := newMockBot(inv)
122122

business_send_test.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,34 @@ import (
77
"github.com/gotd/td/tg"
88
)
99

10+
// multiBusinessMessageUpdates is the response an album sent on behalf of a
11+
// business account returns: each message wrapped in updateBotNewBusinessMessage.
12+
func multiBusinessMessageUpdates(ids ...int) *tg.Updates {
13+
upds := make([]tg.UpdateClass, 0, len(ids))
14+
15+
for _, id := range ids {
16+
upds = append(upds, &tg.UpdateBotNewBusinessMessage{
17+
ConnectionID: "bc1",
18+
Message: &tg.Message{ID: id, Out: true, PeerID: &tg.PeerUser{UserID: 10}},
19+
})
20+
}
21+
22+
return &tg.Updates{Updates: upds, Users: []tg.UserClass{&tg.User{ID: 10, AccessHash: 1}}}
23+
}
24+
25+
// businessSendReply is the response a send on behalf of a business account
26+
// returns: the sent message wrapped in updateBotNewBusinessMessage (not the
27+
// updateNewMessage a normal send returns).
1028
func businessSendReply() *tg.Updates {
11-
return messageUpdates(&tg.Message{ID: 1, Message: "hi", PeerID: &tg.PeerUser{UserID: 10}})
29+
return &tg.Updates{
30+
Updates: []tg.UpdateClass{
31+
&tg.UpdateBotNewBusinessMessage{
32+
ConnectionID: "bc1",
33+
Message: &tg.Message{ID: 1, Out: true, Message: "hi", PeerID: &tg.PeerUser{UserID: 10}},
34+
},
35+
},
36+
Users: []tg.UserClass{&tg.User{ID: 10, AccessHash: 1}},
37+
}
1238
}
1339

1440
func TestSendMessageWithBusinessConnection(t *testing.T) {

edit.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ func (b *Bot) EditMessageReplyMarkup(ctx context.Context, chat ChatID, messageID
7878
return b.sentMessage(ctx, peer, resp, err)
7979
}
8080

81-
// editedMessageFromResp extracts the edited message from an edit response.
82-
// Edits return UpdateEditMessage/UpdateEditChannelMessage, which the generic
83-
// send unpacker does not handle.
81+
// editedMessageFromResp extracts the resulting message from a response the
82+
// generic send unpacker (unpack.MessageClass) does not handle: edits
83+
// (UpdateEditMessage/UpdateEditChannelMessage) and sends on behalf of a business
84+
// account (UpdateBotNew/EditBusinessMessage).
8485
func editedMessageFromResp(resp tg.UpdatesClass) (tg.MessageClass, bool) {
8586
var updates []tg.UpdateClass
8687

@@ -101,6 +102,10 @@ func editedMessageFromResp(resp tg.UpdatesClass) (tg.MessageClass, bool) {
101102
return upd.Message, true
102103
case *tg.UpdateEditChannelMessage:
103104
return upd.Message, true
105+
case *tg.UpdateBotNewBusinessMessage:
106+
return upd.Message, true
107+
case *tg.UpdateBotEditBusinessMessage:
108+
return upd.Message, true
104109
}
105110
}
106111

media_group.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ func (b *Bot) sentMessages(ctx context.Context, resp tg.UpdatesClass, sendErr er
132132
msg = u.Message
133133
case *tg.UpdateNewChannelMessage:
134134
msg = u.Message
135+
case *tg.UpdateBotNewBusinessMessage:
136+
// A media group sent on behalf of a business account returns its
137+
// messages as business message updates.
138+
msg = u.Message
135139
default:
136140
continue
137141
}

0 commit comments

Comments
 (0)