feat: sync collectible star gifts

This commit is contained in:
A 2026-07-16 12:38:53 +08:00
parent 47fcf0ea41
commit 5ecf4e912d
64 changed files with 7559 additions and 403 deletions

View file

@ -9,40 +9,28 @@ import (
"telesrv/internal/store/memory"
)
type fakeCatalog struct {
gifts []domain.StarGift
calls int
}
func (f *fakeCatalog) BuildStarGiftCatalog(_ context.Context) ([]domain.StarGift, error) {
f.calls++
return f.gifts, nil
}
func newTestService(gifts []domain.StarGift) (*Service, *fakeCatalog) {
cat := &fakeCatalog{gifts: gifts}
return NewService(memory.NewStarGiftStore(), cat), cat
func newTestService(gifts []domain.StarGift) (*Service, *memory.StarGiftStore) {
st := memory.NewStarGiftStore()
st.SeedCatalog(gifts)
return NewService(st, nil, 2), st
}
func TestCatalogCachedAndHash(t *testing.T) {
gifts := []domain.StarGift{
{ID: 1, Stars: 15, ConvertStars: 15, Title: "Heart"},
{ID: 2, Stars: 50, ConvertStars: 50, Title: "Cake"},
{ID: 1, RevisionID: 11, Stars: 15, ConvertStars: 15, Title: "Heart"},
{ID: 2, RevisionID: 12, Stars: 50, ConvertStars: 50, Title: "Cake"},
}
svc, cat := newTestService(gifts)
svc, _ := newTestService(gifts)
ctx := context.Background()
got, err := svc.Catalog(ctx)
if err != nil || len(got) != 2 {
t.Fatalf("catalog = %d err %v, want 2", len(got), err)
}
// 再取一次不重新构建(缓存)。
// 再取一次命中进程内目录缓存。
if _, err := svc.Catalog(ctx); err != nil {
t.Fatalf("catalog#2: %v", err)
}
if cat.calls != 1 {
t.Fatalf("BuildStarGiftCatalog called %d times, want 1 (cached)", cat.calls)
}
hash, err := svc.CatalogHash(ctx)
if err != nil || hash != domain.StarGiftCatalogHash(gifts) {
t.Fatalf("hash = %d err %v, want %d", hash, err, domain.StarGiftCatalogHash(gifts))
@ -61,11 +49,15 @@ func TestSavedGiftLifecycle(t *testing.T) {
owner := domain.Peer{Type: domain.PeerTypeUser, ID: 1001}
id, err := svc.RecordSavedGift(ctx, domain.SavedStarGift{
Owner: owner, FromUserID: 2002, GiftID: 1, MsgID: 50, Date: 1700000000, ConvertStars: 15,
Owner: owner, FromUserID: 2002, GiftID: 1, RevisionID: 11, MsgID: 50, Date: 1700000000, ConvertStars: 15,
})
if err != nil || id == 0 {
t.Fatalf("RecordSavedGift = %d err %v", id, err)
}
collection, err := svc.CreateCollection(ctx, owner, "Inbox", []int64{id})
if err != nil || len(collection.GiftIDs) != 1 {
t.Fatalf("CreateCollection = %+v err %v", collection, err)
}
page, err := svc.ListSaved(ctx, owner, false, "", 100)
if err != nil || len(page.Gifts) != 1 || page.Count != 1 {
@ -99,6 +91,11 @@ func TestSavedGiftLifecycle(t *testing.T) {
if len(after.Gifts) != 0 {
t.Fatalf("list after convert = %d, want 0", len(after.Gifts))
}
collections, err := svc.ListCollections(ctx, owner)
if err != nil || len(collections) != 1 || len(collections[0].GiftIDs) != 0 ||
collections[0].Hash != domain.StarGiftCollectionHash("Inbox", nil) {
t.Fatalf("collection after convert = %+v err %v, want empty membership and refreshed hash", collections, err)
}
// 重复转换被拒。
if _, err := svc.Convert(ctx, ref); !errors.Is(err, domain.ErrStarGiftAlreadyConverted) {
t.Fatalf("double convert err = %v, want ErrStarGiftAlreadyConverted", err)
@ -111,7 +108,7 @@ func TestChannelSavedGiftAllocatesSavedIDWithoutMessage(t *testing.T) {
owner := domain.Peer{Type: domain.PeerTypeChannel, ID: 2001}
savedID, err := svc.RecordSavedGift(ctx, domain.SavedStarGift{
Owner: owner, FromUserID: 1001, GiftID: 1, MsgID: 0, SavedID: 0,
Owner: owner, FromUserID: 1001, GiftID: 1, RevisionID: 11, MsgID: 0, SavedID: 0,
Date: 1700000000, ConvertStars: 15,
})
if err != nil || savedID == 0 {
@ -133,7 +130,7 @@ func TestSavedGiftPagination(t *testing.T) {
owner := domain.Peer{Type: domain.PeerTypeUser, ID: 1001}
for i := 0; i < 5; i++ {
if _, err := svc.RecordSavedGift(ctx, domain.SavedStarGift{
Owner: owner, FromUserID: 2002, GiftID: 1, MsgID: 100 + i, Date: 1700000000 + i, ConvertStars: 15,
Owner: owner, FromUserID: 2002, GiftID: 1, RevisionID: 11, MsgID: 100 + i, Date: 1700000000 + i, ConvertStars: 15,
}); err != nil {
t.Fatalf("record#%d: %v", i, err)
}