Skip to content

Commit e39a5cb

Browse files
committed
feat: GetUserProfileAudios
users.getSavedMusic returns the audios a user has added to their profile, each converted via the shared document classifier. New UserProfileAudios result type with offset/limit options. Mapping confirmed against telegram-bot-api 10.1. Hermetic test; lint clean.
1 parent 490b5b1 commit e39a5cb

2 files changed

Lines changed: 132 additions & 0 deletions

File tree

user_profile_audios.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
6+
"github.com/gotd/td/fileid"
7+
"github.com/gotd/td/tg"
8+
)
9+
10+
// UserProfileAudios is the result of GetUserProfileAudios: the audios a user has
11+
// added to their profile.
12+
type UserProfileAudios struct {
13+
// TotalCount is the total number of profile audios the user has.
14+
TotalCount int `json:"total_count"`
15+
// Audios are the requested profile audios.
16+
Audios []Audio `json:"audios"`
17+
}
18+
19+
// GetUserProfileAudiosOption configures GetUserProfileAudios.
20+
type GetUserProfileAudiosOption func(*profileAudiosConfig)
21+
22+
type profileAudiosConfig struct {
23+
offset int
24+
limit int
25+
}
26+
27+
// WithProfileAudiosOffset sets the number of audios to skip.
28+
func WithProfileAudiosOffset(offset int) GetUserProfileAudiosOption {
29+
return func(c *profileAudiosConfig) { c.offset = offset }
30+
}
31+
32+
// WithProfileAudiosLimit caps the number of audios returned (1-100).
33+
func WithProfileAudiosLimit(limit int) GetUserProfileAudiosOption {
34+
return func(c *profileAudiosConfig) { c.limit = limit }
35+
}
36+
37+
// audioFromDocument builds a Bot API Audio from an MTProto audio document,
38+
// reusing the shared document classifier.
39+
func audioFromDocument(d *tg.Document) Audio {
40+
var m Message
41+
42+
setDocumentMedia(d, &m)
43+
44+
if m.Audio != nil {
45+
return *m.Audio
46+
}
47+
48+
fileID, uniqueID := encodeFileID(fileid.FromDocument(d))
49+
50+
return Audio{FileID: fileID, FileUniqueID: uniqueID, MIMEType: d.MimeType, FileSize: d.Size}
51+
}
52+
53+
// GetUserProfileAudios returns the audios a user has added to their profile.
54+
func (b *Bot) GetUserProfileAudios(ctx context.Context, userID int64, opts ...GetUserProfileAudiosOption) (*UserProfileAudios, error) {
55+
cfg := profileAudiosConfig{limit: 100}
56+
for _, o := range opts {
57+
o(&cfg)
58+
}
59+
60+
user, err := b.resolveInputUser(ctx, userID)
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
res, err := b.raw.UsersGetSavedMusic(ctx, &tg.UsersGetSavedMusicRequest{
66+
ID: user,
67+
Offset: cfg.offset,
68+
Limit: cfg.limit,
69+
})
70+
if err != nil {
71+
return nil, asAPIError(err)
72+
}
73+
74+
music, ok := res.(*tg.UsersSavedMusic)
75+
if !ok {
76+
return &UserProfileAudios{}, nil
77+
}
78+
79+
out := &UserProfileAudios{TotalCount: music.Count, Audios: make([]Audio, 0, len(music.Documents))}
80+
81+
for _, doc := range music.Documents {
82+
if d, ok := doc.(*tg.Document); ok {
83+
out.Audios = append(out.Audios, audioFromDocument(d))
84+
}
85+
}
86+
87+
return out, nil
88+
}

user_profile_audios_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package botapi
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/gotd/td/tg"
8+
)
9+
10+
func TestGetUserProfileAudios(t *testing.T) {
11+
inv := newMockInvoker()
12+
inv.reply(tg.UsersGetSavedMusicRequestTypeID, &tg.UsersSavedMusic{
13+
Count: 3,
14+
Documents: []tg.DocumentClass{
15+
&tg.Document{
16+
ID: 1, AccessHash: 2, FileReference: []byte{0}, MimeType: "audio/mpeg", Size: 1000, DCID: 2,
17+
Attributes: []tg.DocumentAttributeClass{
18+
&tg.DocumentAttributeAudio{Duration: 180, Title: "Song", Performer: "Artist"},
19+
},
20+
},
21+
},
22+
})
23+
24+
got, err := newMockBot(inv).GetUserProfileAudios(context.Background(), 99, WithProfileAudiosLimit(50), WithProfileAudiosOffset(5))
25+
if err != nil {
26+
t.Fatalf("GetUserProfileAudios: %v", err)
27+
}
28+
29+
if got.TotalCount != 3 || len(got.Audios) != 1 {
30+
t.Fatalf("got = %#v", got)
31+
}
32+
33+
if got.Audios[0].Duration != 180 || got.Audios[0].Title != "Song" || got.Audios[0].Performer != "Artist" {
34+
t.Fatalf("audio = %#v", got.Audios[0])
35+
}
36+
37+
var req tg.UsersGetSavedMusicRequest
38+
39+
inv.decode(t, tg.UsersGetSavedMusicRequestTypeID, &req)
40+
41+
if req.Limit != 50 || req.Offset != 5 {
42+
t.Fatalf("req = %#v", req)
43+
}
44+
}

0 commit comments

Comments
 (0)