Skip to content

Commit 5d049bb

Browse files
ernadoclaude
andcommitted
feat(updates): map dispatched tg updates to Bot API objects
messageFromTg converts a dispatched message (reusing convertMessage), callbackQueryFromTg and inlineQueryFromTg build their Bot API objects from the update plus the harvested Entities (sender resolved without an extra RPC). These feed the handler routing added next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2efe399 commit 5d049bb

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

updates_map.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+
"strconv"
6+
7+
"github.com/gotd/td/tg"
8+
)
9+
10+
// messageFromTg converts a dispatched message into a Bot API Message. Service
11+
// and empty messages yield (nil, nil) so callers can skip them.
12+
func (b *Bot) messageFromTg(ctx context.Context, msg tg.MessageClass) (*Message, error) {
13+
m, ok := msg.(*tg.Message)
14+
if !ok {
15+
return nil, nil
16+
}
17+
return b.convertMessage(ctx, m)
18+
}
19+
20+
// callbackQueryFromTg builds a CallbackQuery from a bot callback update. The
21+
// sender is taken from the update entities (already harvested by the peer hook),
22+
// so no extra RPC is needed.
23+
func callbackQueryFromTg(e tg.Entities, u *tg.UpdateBotCallbackQuery) *CallbackQuery {
24+
cq := &CallbackQuery{
25+
ID: strconv.FormatInt(u.QueryID, 10),
26+
ChatInstance: strconv.FormatInt(u.ChatInstance, 10),
27+
Data: string(u.Data),
28+
GameShortName: u.GameShortName,
29+
}
30+
if user, ok := e.Users[u.UserID]; ok {
31+
cq.From = userFromTgUser(user)
32+
} else {
33+
cq.From = User{ID: u.UserID}
34+
}
35+
return cq
36+
}
37+
38+
// inlineQueryFromTg builds an InlineQuery from a bot inline-query update.
39+
func inlineQueryFromTg(e tg.Entities, u *tg.UpdateBotInlineQuery) *InlineQuery {
40+
iq := &InlineQuery{
41+
ID: strconv.FormatInt(u.QueryID, 10),
42+
Query: u.Query,
43+
Offset: u.Offset,
44+
}
45+
if user, ok := e.Users[u.UserID]; ok {
46+
iq.From = userFromTgUser(user)
47+
} else {
48+
iq.From = User{ID: u.UserID}
49+
}
50+
return iq
51+
}

updates_map_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package botapi
2+
3+
import (
4+
"testing"
5+
6+
"github.com/gotd/td/tg"
7+
)
8+
9+
func TestCallbackQueryFromTg(t *testing.T) {
10+
e := tg.Entities{Users: map[int64]*tg.User{5: {ID: 5, FirstName: "Ada", Username: "ada"}}}
11+
u := &tg.UpdateBotCallbackQuery{QueryID: 100, UserID: 5, ChatInstance: 77, Data: []byte("vote:1")}
12+
13+
cq := callbackQueryFromTg(e, u)
14+
if cq.ID != "100" || cq.ChatInstance != "77" || cq.Data != "vote:1" {
15+
t.Fatalf("scalar fields: %+v", cq)
16+
}
17+
if cq.From.ID != 5 || cq.From.Username != "ada" {
18+
t.Fatalf("from from entities: %+v", cq.From)
19+
}
20+
}
21+
22+
func TestCallbackQueryFromTgUnknownUser(t *testing.T) {
23+
cq := callbackQueryFromTg(tg.Entities{}, &tg.UpdateBotCallbackQuery{QueryID: 1, UserID: 9})
24+
if cq.From.ID != 9 {
25+
t.Fatalf("fallback from id: %+v", cq.From)
26+
}
27+
}
28+
29+
func TestInlineQueryFromTg(t *testing.T) {
30+
e := tg.Entities{Users: map[int64]*tg.User{3: {ID: 3, FirstName: "Bob"}}}
31+
u := &tg.UpdateBotInlineQuery{QueryID: 42, UserID: 3, Query: "cats", Offset: "10"}
32+
33+
iq := inlineQueryFromTg(e, u)
34+
if iq.ID != "42" || iq.Query != "cats" || iq.Offset != "10" || iq.From.ID != 3 {
35+
t.Fatalf("inline query: %+v", iq)
36+
}
37+
}

0 commit comments

Comments
 (0)