Skip to content

Commit 3a33ae0

Browse files
ernadoclaude
andcommitted
feat: add AnswerWebAppQuery
Sets the result of a Web App interaction via messages.sendWebViewResultMessage, reusing the InlineQueryResult -> tg InputBotInlineResult conversion. The returned SentWebAppMessage carries the inline_message_id, encoded with the new inline_message_id codec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 379a1b8 commit 3a33ae0

2 files changed

Lines changed: 113 additions & 0 deletions

File tree

answer_webapp.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
6+
"github.com/gotd/td/tg"
7+
)
8+
9+
// SentWebAppMessage describes an inline message sent by a Web App on behalf of a
10+
// user.
11+
type SentWebAppMessage struct {
12+
// InlineMessageID is the identifier of the sent inline message, present only
13+
// if the message has a reply markup with at least one callback or inline
14+
// query button.
15+
InlineMessageID string `json:"inline_message_id,omitempty"`
16+
}
17+
18+
// AnswerWebAppQuery sets the result of an interaction with a Web App and sends a
19+
// corresponding message on behalf of the user to the chat from which the query
20+
// originated. webAppQueryID is the query id from the Web App.
21+
func (b *Bot) AnswerWebAppQuery(ctx context.Context, webAppQueryID string, result InlineQueryResult) (*SentWebAppMessage, error) {
22+
if result == nil {
23+
return nil, &Error{Code: 400, Description: "Bad Request: inline query result is nil"}
24+
}
25+
26+
converted, err := result.toTg(ctx, b)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
res, err := b.raw.MessagesSendWebViewResultMessage(ctx, &tg.MessagesSendWebViewResultMessageRequest{
32+
BotQueryID: webAppQueryID,
33+
Result: converted,
34+
})
35+
if err != nil {
36+
return nil, asAPIError(err)
37+
}
38+
39+
out := &SentWebAppMessage{}
40+
41+
if id, ok := res.GetMsgID(); ok {
42+
enc, err := encodeInlineMessageID(id)
43+
if err != nil {
44+
return nil, err
45+
}
46+
47+
out.InlineMessageID = enc
48+
}
49+
50+
return out, nil
51+
}

answer_webapp_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/gotd/td/tg"
8+
)
9+
10+
func TestAnswerWebAppQuery(t *testing.T) {
11+
mid := &tg.InputBotInlineMessageID64{DCID: 2, OwnerID: 1, ID: 9, AccessHash: 42}
12+
13+
sent := &tg.WebViewMessageSent{}
14+
sent.SetMsgID(mid)
15+
16+
inv := newMockInvoker()
17+
inv.reply(tg.MessagesSendWebViewResultMessageRequestTypeID, sent)
18+
19+
result := &InlineQueryResultArticle{
20+
ID: "r1",
21+
Title: "Title",
22+
InputMessageContent: &InputTextMessageContent{MessageText: "hi"},
23+
}
24+
25+
got, err := newMockBot(inv).AnswerWebAppQuery(context.Background(), "wq1", result)
26+
if err != nil {
27+
t.Fatalf("AnswerWebAppQuery: %v", err)
28+
}
29+
30+
decoded, err := decodeInlineMessageID(got.InlineMessageID)
31+
if err != nil {
32+
t.Fatalf("decode inline message id %q: %v", got.InlineMessageID, err)
33+
}
34+
35+
if decoded.String() != mid.String() {
36+
t.Fatalf("inline message id = %#v, want %#v", decoded, mid)
37+
}
38+
39+
var req tg.MessagesSendWebViewResultMessageRequest
40+
41+
inv.decode(t, tg.MessagesSendWebViewResultMessageRequestTypeID, &req)
42+
43+
if req.BotQueryID != "wq1" {
44+
t.Fatalf("bot query id = %q", req.BotQueryID)
45+
}
46+
47+
if _, ok := req.Result.(*tg.InputBotInlineResult); !ok {
48+
t.Fatalf("result = %#v, want inline result", req.Result)
49+
}
50+
}
51+
52+
func TestAnswerWebAppQueryNilResult(t *testing.T) {
53+
inv := newMockInvoker()
54+
55+
if _, err := newMockBot(inv).AnswerWebAppQuery(context.Background(), "wq1", nil); err == nil {
56+
t.Fatal("expected error for nil result")
57+
}
58+
59+
if inv.count() != 0 {
60+
t.Fatalf("made %d RPC calls, want 0", inv.count())
61+
}
62+
}

0 commit comments

Comments
 (0)