Skip to content

Commit 69f96a1

Browse files
ernadoclaude
andcommitted
feat(send): resolve ChatID to MTProto peers
resolvePeer maps the sealed ChatID union to a gotd peers.Peer: numeric ids via the TDLib id convention (ResolveTDLibID), @usernames via ResolveDomain, pulling access hashes from storage. resolveInputPeer returns the tg.InputPeerClass the sender needs. Resolution failures flow through asAPIError. The union switch is exhaustive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 9de654f commit 69f96a1

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

resolve.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
"github.com/gotd/td/constant"
8+
"github.com/gotd/td/telegram/peers"
9+
"github.com/gotd/td/tg"
10+
)
11+
12+
// resolvePeer resolves a Bot API ChatID to a gotd peer, pulling the access hash
13+
// from storage. Numeric ids go through the TDLib id convention; @usernames are
14+
// resolved by domain.
15+
//
16+
// The switch over the sealed ChatID union is exhaustive (gochecksumtype).
17+
func (b *Bot) resolvePeer(ctx context.Context, chat ChatID) (peers.Peer, error) {
18+
switch c := chat.(type) {
19+
case ChatIDInt:
20+
p, err := b.peers.ResolveTDLibID(ctx, constant.TDLibPeerID(int64(c)))
21+
if err != nil {
22+
return nil, asAPIError(err)
23+
}
24+
return p, nil
25+
case ChatIDUsername:
26+
name := strings.TrimPrefix(string(c), "@")
27+
if name == "" {
28+
return nil, &Error{Code: 400, Description: "Bad Request: chat_id is empty"}
29+
}
30+
p, err := b.peers.ResolveDomain(ctx, name)
31+
if err != nil {
32+
return nil, asAPIError(err)
33+
}
34+
return p, nil
35+
default:
36+
return nil, &Error{Code: 400, Description: "Bad Request: invalid chat_id"}
37+
}
38+
}
39+
40+
// resolveInputPeer resolves a ChatID to the tg.InputPeerClass the sender needs.
41+
func (b *Bot) resolveInputPeer(ctx context.Context, chat ChatID) (tg.InputPeerClass, error) {
42+
p, err := b.resolvePeer(ctx, chat)
43+
if err != nil {
44+
return nil, err
45+
}
46+
return p.InputPeer(), nil
47+
}

resolve_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
)
8+
9+
func TestResolvePeerEmptyUsername(t *testing.T) {
10+
b, err := New("123:abc", Options{AppID: 1, AppHash: "hash"})
11+
if err != nil {
12+
t.Fatal(err)
13+
}
14+
15+
_, err = b.resolvePeer(context.Background(), Username("@"))
16+
var apiErr *Error
17+
if !errors.As(err, &apiErr) || apiErr.Code != 400 {
18+
t.Fatalf("empty username should be a 400, got %v", err)
19+
}
20+
}

0 commit comments

Comments
 (0)