feat: sync GIFv and saved GIF support

This commit is contained in:
A 2026-07-11 21:43:13 +08:00
parent c0088f1160
commit 5f7c0b9804
21 changed files with 641 additions and 50 deletions

View file

@ -14,20 +14,28 @@ import (
"telesrv/internal/store/memory"
)
func stickerCollectionRouter(t *testing.T) *Router {
func stickerCollectionRouter(t *testing.T) (*Router, *captureSessions) {
t.Helper()
files := &fakeFiles{docs: map[int64]domain.Document{
101: {ID: 101, AccessHash: 11, Attributes: []domain.DocumentAttribute{{Kind: domain.DocAttrSticker}}},
102: {ID: 102, AccessHash: 12, Attributes: []domain.DocumentAttribute{{Kind: domain.DocAttrSticker}}},
201: {ID: 201, AccessHash: 21, Attributes: []domain.DocumentAttribute{{Kind: domain.DocAttrAnimated}}},
201: {ID: 201, AccessHash: 21, MimeType: "video/mp4", Attributes: []domain.DocumentAttribute{
{Kind: domain.DocAttrAnimated},
{Kind: domain.DocAttrVideo, W: 320, H: 240, Duration: 1},
}},
202: {ID: 202, AccessHash: 22, MimeType: "video/mp4", Attributes: []domain.DocumentAttribute{
{Kind: domain.DocAttrAnimated},
{Kind: domain.DocAttrVideo, W: 640, H: 360, Duration: 2},
}},
301: {ID: 301, AccessHash: 31, Attributes: []domain.DocumentAttribute{{Kind: domain.DocAttrAudio}}},
}}
passwordStore := memory.NewPasswordStore()
sessions := &captureSessions{}
return New(Config{}, Deps{
Account: appaccount.NewService(passwordStore, appaccount.WithStickerCollections(passwordStore)),
Files: files,
Sessions: &captureSessions{},
}, zaptest.NewLogger(t), clock.System)
Sessions: sessions,
}, zaptest.NewLogger(t), clock.System), sessions
}
func inputDoc(id, accessHash int64) *tg.InputDocument {
@ -36,7 +44,7 @@ func inputDoc(id, accessHash int64) *tg.InputDocument {
// TestFavedStickersRoundTrip 回归:faveSticker/getFavedStickers 此前未注册/返空。
func TestFavedStickersRoundTrip(t *testing.T) {
r := stickerCollectionRouter(t)
r, _ := stickerCollectionRouter(t)
ctx := WithUserID(context.Background(), 1000000001)
// 非贴纸文档拒绝。
@ -80,7 +88,7 @@ func TestFavedStickersRoundTrip(t *testing.T) {
// TestRecentStickersRoundTrip 验证 saveRecentSticker/getRecentStickers + dates + clear。
func TestRecentStickersRoundTrip(t *testing.T) {
r := stickerCollectionRouter(t)
r, _ := stickerCollectionRouter(t)
ctx := WithUserID(context.Background(), 1000000001)
if ok, err := r.onMessagesSaveRecentSticker(ctx, &tg.MessagesSaveRecentStickerRequest{ID: inputDoc(101, 11)}); err != nil || !ok {
@ -110,22 +118,48 @@ func TestRecentStickersRoundTrip(t *testing.T) {
// TestSavedGifsRoundTrip 验证 saveGif/getSavedGifs + 非 GIF 拒绝。
func TestSavedGifsRoundTrip(t *testing.T) {
r := stickerCollectionRouter(t)
r, sessions := stickerCollectionRouter(t)
ctx := WithUserID(context.Background(), 1000000001)
// 非 GIF(贴纸)拒绝。
if ok, err := r.onMessagesSaveGif(ctx, &tg.MessagesSaveGifRequest{ID: inputDoc(101, 11)}); ok || !tgerr.Is(err, "STICKER_DOCUMENT_INVALID") {
t.Fatalf("save non-gif = ok %v err %v, want STICKER_DOCUMENT_INVALID", ok, err)
if ok, err := r.onMessagesSaveGif(ctx, &tg.MessagesSaveGifRequest{ID: inputDoc(101, 11)}); ok || !tgerr.Is(err, "GIF_ID_INVALID") {
t.Fatalf("save non-gif = ok %v err %v, want GIF_ID_INVALID", ok, err)
}
if ok, err := r.onMessagesSaveGif(ctx, &tg.MessagesSaveGifRequest{ID: inputDoc(201, 21)}); err != nil || !ok {
t.Fatalf("save gif = ok %v err %v", ok, err)
}
if pushed, ok := sessions.lastUserPush().(*tg.Updates); !ok || len(pushed.Updates) != 1 {
t.Fatalf("save gif push = %T %+v, want updateSavedGifs", sessions.lastUserPush(), pushed)
} else if _, ok := pushed.Updates[0].(*tg.UpdateSavedGifs); !ok {
t.Fatalf("save gif update = %T, want *tg.UpdateSavedGifs", pushed.Updates[0])
}
if ok, err := r.onMessagesSaveGif(ctx, &tg.MessagesSaveGifRequest{ID: inputDoc(202, 22)}); err != nil || !ok {
t.Fatalf("save second gif = ok %v err %v", ok, err)
}
out, err := r.onMessagesGetSavedGifs(ctx, 0)
if err != nil {
t.Fatalf("get saved gifs: %v", err)
}
if got := out.(*tg.MessagesSavedGifs); len(got.Gifs) != 1 {
t.Fatalf("saved gifs = %d, want 1", len(got.Gifs))
full := out.(*tg.MessagesSavedGifs)
if len(full.Gifs) != 2 || full.Gifs[0].(*tg.Document).ID != 202 {
t.Fatalf("saved gifs = %+v, want newest 202 first", full.Gifs)
}
again, err := r.onMessagesGetSavedGifs(ctx, full.Hash)
if err != nil {
t.Fatalf("get saved gifs by hash: %v", err)
}
if _, ok := again.(*tg.MessagesSavedGifsNotModified); !ok {
t.Fatalf("get saved gifs by hash = %T, want NotModified", again)
}
if ok, err := r.onMessagesSaveGif(ctx, &tg.MessagesSaveGifRequest{ID: inputDoc(201, 21), Unsave: true}); err != nil || !ok {
t.Fatalf("unsave gif = ok %v err %v", ok, err)
}
out, err = r.onMessagesGetSavedGifs(ctx, 0)
if err != nil {
t.Fatalf("get after unsave: %v", err)
}
if got := out.(*tg.MessagesSavedGifs); len(got.Gifs) != 1 || got.Gifs[0].(*tg.Document).ID != 202 {
t.Fatalf("saved gifs after unsave = %+v, want [202]", got.Gifs)
}
}