chore: refresh gramsrv public release

This commit is contained in:
A 2026-06-30 14:37:43 +08:00
parent 75cebe8dbf
commit 70b6820474
1274 changed files with 378751 additions and 59919 deletions

View file

@ -2,6 +2,7 @@ package rpc
import (
"context"
"strings"
"testing"
"github.com/gotd/td/clock"
@ -31,9 +32,14 @@ func TestUploadProfilePhotoPushesUpdateToOtherDevices(t *testing.T) {
req := &tg.PhotosUploadProfilePhotoRequest{}
req.SetFile(&tg.InputFile{ID: 42, Parts: 1, Name: "a.jpg"}) // File 是 flags 可选字段,须 SetFile 置位
if _, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), req); err != nil {
got, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), req)
if err != nil {
t.Fatalf("uploadProfilePhoto: %v", err)
}
returnedPhoto, ok := firstPhotosUser(t, got).Photo.(*tg.UserProfilePhoto)
if !ok || returnedPhoto.PhotoID != 778 || returnedPhoto.DCID != 2 {
t.Fatalf("returned self photo = %+v, want photo_id=778 dc_id=2", firstPhotosUser(t, got).Photo)
}
snap := sessions.snapshot()
if snap.userID != owner.ID {
@ -55,4 +61,156 @@ func TestUploadProfilePhotoPushesUpdateToOtherDevices(t *testing.T) {
if len(updates.Users) == 0 {
t.Fatal("pushed updates missing self user — other devices cannot refresh avatar")
}
pushedUser, ok := updates.Users[0].(*tg.User)
if !ok {
t.Fatalf("pushed user = %T, want *tg.User", updates.Users[0])
}
pushedPhoto, ok := pushedUser.Photo.(*tg.UserProfilePhoto)
if !ok || pushedPhoto.PhotoID != 778 || pushedPhoto.DCID != 2 {
t.Fatalf("pushed self photo = %+v, want photo_id=778 dc_id=2", pushedUser.Photo)
}
}
func TestUploadProfilePhotoSupportsAnimatedVideoAndEmojiMarkup(t *testing.T) {
ctx := context.Background()
userStore := memory.NewUserStore()
owner, _ := userStore.Create(ctx, domain.User{AccessHash: 11, Phone: "15550001002", FirstName: "Owner"})
sessions := &captureSessions{}
files := &fakeFiles{}
r := New(Config{DC: 2, IP: "127.0.0.1", Port: 2398}, Deps{
Users: appusers.NewService(userStore, appusers.WithPhotoProvider(files)),
Files: files,
Sessions: sessions,
}, zaptest.NewLogger(t), clock.System)
videoReq := &tg.PhotosUploadProfilePhotoRequest{}
videoReq.SetVideo(&tg.InputFile{ID: 43, Parts: 1, Name: "avatar.mp4"})
videoReq.SetVideoStartTs(0.25)
videoGot, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), videoReq)
if err != nil {
t.Fatalf("upload animated profile video: %v", err)
}
videoPhoto, ok := videoGot.Photo.(*tg.Photo)
if !ok || videoPhoto.ID != 779 || len(videoPhoto.VideoSizes) != 1 {
t.Fatalf("video profile photo = %+v, want photo 779 with video_sizes", videoGot.Photo)
}
videoSize, ok := videoPhoto.VideoSizes[0].(*tg.VideoSize)
if !ok || videoSize.Type != "u" || videoSize.VideoStartTs != 0.25 {
t.Fatalf("video size = %+v, want videoSize u start 0.25", videoPhoto.VideoSizes[0])
}
selfPhoto := firstPhotosUser(t, videoGot).Photo
userPhoto, ok := selfPhoto.(*tg.UserProfilePhoto)
if !ok || userPhoto.PhotoID != 779 || userPhoto.DCID != 2 || !userPhoto.HasVideo {
t.Fatalf("returned self photo = %+v, want photo 779 dc 2 has_video", selfPhoto)
}
if cur, ok, err := files.CurrentProfilePhotoKind(ctx, domain.PeerTypeUser, owner.ID, domain.ProfilePhotoKindProfile); err != nil || !ok || cur.ID != 779 {
t.Fatalf("current profile photo = %+v ok=%v err=%v, want 779", cur, ok, err)
}
markupReq := &tg.PhotosUploadProfilePhotoRequest{}
markupReq.SetVideoEmojiMarkup(&tg.VideoSizeEmojiMarkup{EmojiID: 99, BackgroundColors: []int{0xffffff}})
markupGot, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), markupReq)
if err != nil {
t.Fatalf("upload emoji profile photo: %v", err)
}
markupPhoto, ok := markupGot.Photo.(*tg.Photo)
if !ok || markupPhoto.ID != 780 || len(markupPhoto.VideoSizes) != 1 {
t.Fatalf("emoji profile photo = %+v, want photo 780 with video_sizes", markupGot.Photo)
}
if _, ok := markupPhoto.VideoSizes[0].(*tg.VideoSizeEmojiMarkup); !ok {
t.Fatalf("emoji video size = %T, want *tg.VideoSizeEmojiMarkup", markupPhoto.VideoSizes[0])
}
selfPhoto = firstPhotosUser(t, markupGot).Photo
userPhoto, ok = selfPhoto.(*tg.UserProfilePhoto)
if !ok || userPhoto.PhotoID != 780 || userPhoto.DCID != 2 || !userPhoto.HasVideo {
t.Fatalf("returned self photo after emoji = %+v, want photo 780 dc 2 has_video", selfPhoto)
}
stickerReq := &tg.PhotosUploadProfilePhotoRequest{}
stickerReq.SetVideoEmojiMarkup(&tg.VideoSizeStickerMarkup{
Stickerset: &tg.InputStickerSetAnimatedEmoji{},
StickerID: 123,
BackgroundColors: []int{0x112233, 0x445566},
})
stickerGot, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), stickerReq)
if err != nil {
t.Fatalf("upload animated emoji sticker profile photo: %v", err)
}
stickerPhoto, ok := stickerGot.Photo.(*tg.Photo)
if !ok || len(stickerPhoto.VideoSizes) != 1 {
t.Fatalf("sticker profile photo = %+v, want photo with video_sizes", stickerGot.Photo)
}
stickerSize, ok := stickerPhoto.VideoSizes[0].(*tg.VideoSizeStickerMarkup)
if !ok {
t.Fatalf("sticker video size = %T, want *tg.VideoSizeStickerMarkup", stickerPhoto.VideoSizes[0])
}
if _, ok := stickerSize.Stickerset.(*tg.InputStickerSetAnimatedEmoji); !ok {
t.Fatalf("sticker markup set = %T, want inputStickerSetAnimatedEmoji", stickerSize.Stickerset)
}
comboReq := &tg.PhotosUploadProfilePhotoRequest{}
comboReq.SetVideo(&tg.InputFile{ID: 45, Parts: 9, Name: "avatar.mp4"})
comboReq.SetVideoStartTs(0)
comboReq.SetVideoEmojiMarkup(&tg.VideoSizeEmojiMarkup{
EmojiID: 1258816259753929,
BackgroundColors: []int{0x536dfe, 0x29b6f6, 0x26a69a, 0x66bb6a},
})
comboGot, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), comboReq)
if err != nil {
t.Fatalf("upload Android video+emoji profile photo: %v", err)
}
comboPhoto, ok := comboGot.Photo.(*tg.Photo)
if !ok || len(comboPhoto.VideoSizes) != 2 {
t.Fatalf("combo profile photo = %+v, want two video_sizes", comboGot.Photo)
}
if _, ok := comboPhoto.VideoSizes[0].(*tg.VideoSize); !ok {
t.Fatalf("combo first video size = %T, want *tg.VideoSize", comboPhoto.VideoSizes[0])
}
if _, ok := comboPhoto.VideoSizes[1].(*tg.VideoSizeEmojiMarkup); !ok {
t.Fatalf("combo second video size = %T, want *tg.VideoSizeEmojiMarkup", comboPhoto.VideoSizes[1])
}
}
func TestUploadProfilePhotoFallbackEmojiAndInvalidFlags(t *testing.T) {
ctx := context.Background()
userStore := memory.NewUserStore()
owner, _ := userStore.Create(ctx, domain.User{AccessHash: 11, Phone: "15550001003", FirstName: "Owner"})
files := &fakeFiles{}
r := New(Config{DC: 2, IP: "127.0.0.1", Port: 2398}, Deps{
Users: appusers.NewService(userStore, appusers.WithPhotoProvider(files)),
Files: files,
}, zaptest.NewLogger(t), clock.System)
profileReq := &tg.PhotosUploadProfilePhotoRequest{}
profileReq.SetFile(&tg.InputFile{ID: 42, Parts: 1, Name: "avatar.jpg"})
if _, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), profileReq); err != nil {
t.Fatalf("seed profile photo: %v", err)
}
fallbackReq := &tg.PhotosUploadProfilePhotoRequest{}
fallbackReq.SetFallback(true)
fallbackReq.SetVideoEmojiMarkup(&tg.VideoSizeEmojiMarkup{EmojiID: 100, BackgroundColors: []int{0x112233}})
fallbackGot, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), fallbackReq)
if err != nil {
t.Fatalf("upload fallback emoji profile photo: %v", err)
}
if photo, ok := fallbackGot.Photo.(*tg.Photo); !ok || photo.ID != 780 {
t.Fatalf("fallback photo = %+v, want photo 780", fallbackGot.Photo)
}
if cur, ok, err := files.CurrentProfilePhotoKind(ctx, domain.PeerTypeUser, owner.ID, domain.ProfilePhotoKindFallback); err != nil || !ok || cur.ID != 780 {
t.Fatalf("current fallback photo = %+v ok=%v err=%v, want 780", cur, ok, err)
}
if cur, ok, err := files.CurrentProfilePhotoKind(ctx, domain.PeerTypeUser, owner.ID, domain.ProfilePhotoKindProfile); err != nil || !ok || cur.ID != 778 {
t.Fatalf("current profile photo after fallback = %+v ok=%v err=%v, want preserved 778", cur, ok, err)
}
invalidReq := &tg.PhotosUploadProfilePhotoRequest{}
invalidReq.SetFile(&tg.InputFile{ID: 44, Parts: 1, Name: "avatar.jpg"})
invalidReq.SetVideoEmojiMarkup(&tg.VideoSizeEmojiMarkup{EmojiID: 101, BackgroundColors: []int{0x445566}})
if _, err := r.onPhotosUploadProfilePhoto(WithUserID(ctx, owner.ID), invalidReq); err == nil || !strings.Contains(err.Error(), "PHOTO_INVALID") {
t.Fatalf("invalid mixed profile photo error = %v, want PHOTO_INVALID", err)
}
if cur, ok, err := files.CurrentProfilePhotoKind(ctx, domain.PeerTypeUser, owner.ID, domain.ProfilePhotoKindProfile); err != nil || !ok || cur.ID != 778 {
t.Fatalf("current profile photo after invalid = %+v ok=%v err=%v, want preserved 778", cur, ok, err)
}
}