feat: sync monoforum and collectible emoji status
Sync telesrv bd15657 (feat(account): implement collectible emoji status). Skipped telesrv docs changes per public sync rules.
This commit is contained in:
parent
edb7057757
commit
0c99ae0a9d
91 changed files with 4061 additions and 693 deletions
134
internal/rpc/account_collectible_emoji_status_test.go
Normal file
134
internal/rpc/account_collectible_emoji_status_test.go
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/iamxvbaba/td/clock"
|
||||
"github.com/iamxvbaba/td/tg"
|
||||
"github.com/iamxvbaba/td/tgerr"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
appusers "telesrv/internal/app/users"
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store/memory"
|
||||
)
|
||||
|
||||
type collectibleEmojiGiftService struct {
|
||||
GiftsService
|
||||
gifts map[int64]domain.UniqueStarGift
|
||||
}
|
||||
|
||||
func (s *collectibleEmojiGiftService) UniqueByID(_ context.Context, id int64) (domain.UniqueStarGift, bool, error) {
|
||||
gift, ok := s.gifts[id]
|
||||
return gift, ok, nil
|
||||
}
|
||||
|
||||
func (s *collectibleEmojiGiftService) ListUniqueByOwner(_ context.Context, owner domain.Peer, limit int) ([]domain.UniqueStarGift, error) {
|
||||
out := make([]domain.UniqueStarGift, 0, len(s.gifts))
|
||||
for _, gift := range s.gifts {
|
||||
if gift.Owner == owner && !gift.Burned && gift.OwnerAddress == "" {
|
||||
out = append(out, gift)
|
||||
}
|
||||
}
|
||||
if len(out) > limit {
|
||||
out = out[:limit]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func collectibleEmojiTestGift(ownerID int64) domain.UniqueStarGift {
|
||||
return domain.UniqueStarGift{
|
||||
ID: 9001, Title: "Plush Pepe", Slug: "PlushPepe-1",
|
||||
Owner: domain.Peer{Type: domain.PeerTypeUser, ID: ownerID},
|
||||
Model: domain.StarGiftCollectibleAttribute{Document: &domain.Document{ID: 7101}},
|
||||
Pattern: domain.StarGiftCollectibleAttribute{Document: &domain.Document{ID: 7201}},
|
||||
Backdrop: domain.StarGiftCollectibleAttribute{
|
||||
CenterColor: 0x102030, EdgeColor: 0x405060,
|
||||
PatternColor: 0x708090, TextColor: 0xa0b0c0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccountCollectibleEmojiStatusListSetAndRejectNonOwner(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
userStore := memory.NewUserStore()
|
||||
owner, err := userStore.Create(ctx, domain.User{AccessHash: 1, Phone: "15550009101", FirstName: "Owner"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
other, err := userStore.Create(ctx, domain.User{AccessHash: 2, Phone: "15550009102", FirstName: "Other"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
users := appusers.NewService(userStore)
|
||||
if _, err := users.GrantPremium(ctx, owner.ID, 1); err != nil {
|
||||
t.Fatalf("grant premium: %v", err)
|
||||
}
|
||||
gift := collectibleEmojiTestGift(owner.ID)
|
||||
gifts := &collectibleEmojiGiftService{gifts: map[int64]domain.UniqueStarGift{gift.ID: gift}}
|
||||
r := New(Config{}, Deps{Users: users, Gifts: gifts}, zaptest.NewLogger(t), clock.System)
|
||||
ownerCtx := WithUserID(ctx, owner.ID)
|
||||
|
||||
listed, err := r.onAccountGetCollectibleEmojiStatuses(ownerCtx, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("get collectible statuses: %v", err)
|
||||
}
|
||||
statuses, ok := listed.(*tg.AccountEmojiStatuses)
|
||||
if !ok || len(statuses.Statuses) != 1 || statuses.Hash == 0 {
|
||||
t.Fatalf("collectible list = %T %#v", listed, listed)
|
||||
}
|
||||
collectible, ok := statuses.Statuses[0].(*tg.EmojiStatusCollectible)
|
||||
if !ok || collectible.CollectibleID != gift.ID || collectible.DocumentID != gift.Model.Document.ID ||
|
||||
collectible.PatternDocumentID != gift.Pattern.Document.ID || collectible.PatternColor != gift.Backdrop.PatternColor {
|
||||
t.Fatalf("collectible status = %T %#v", statuses.Statuses[0], statuses.Statuses[0])
|
||||
}
|
||||
if cached, err := r.onAccountGetCollectibleEmojiStatuses(ownerCtx, statuses.Hash); err != nil {
|
||||
t.Fatalf("get cached collectible statuses: %v", err)
|
||||
} else if _, ok := cached.(*tg.AccountEmojiStatusesNotModified); !ok {
|
||||
t.Fatalf("cached collectible statuses = %T, want notModified", cached)
|
||||
}
|
||||
|
||||
input := &tg.InputEmojiStatusCollectible{CollectibleID: gift.ID}
|
||||
input.SetUntil(2_000_000_000)
|
||||
if ok, err := r.onAccountUpdateEmojiStatus(ownerCtx, input); err != nil || !ok {
|
||||
t.Fatalf("set collectible status: ok=%v err=%v", ok, err)
|
||||
}
|
||||
self, err := users.Self(ctx, owner.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !self.EmojiStatusCollectible.Valid() || self.EmojiStatusCollectible.CollectibleID != gift.ID ||
|
||||
self.EmojiStatusUntil != 2_000_000_000 {
|
||||
t.Fatalf("persisted collectible status = %+v", self.EmojiStatus())
|
||||
}
|
||||
wire, ok := tgUserEmojiStatus(self, time.Now().Unix()).(*tg.EmojiStatusCollectible)
|
||||
if !ok || wire.Slug != gift.Slug || wire.TextColor != gift.Backdrop.TextColor {
|
||||
t.Fatalf("wire collectible = %T %#v", tgUserEmojiStatus(self, time.Now().Unix()), wire)
|
||||
}
|
||||
|
||||
stolen := gift
|
||||
stolen.Owner = domain.Peer{Type: domain.PeerTypeUser, ID: other.ID}
|
||||
gifts.gifts[gift.ID] = stolen
|
||||
if ok, err := r.onAccountUpdateEmojiStatus(ownerCtx, &tg.InputEmojiStatusCollectible{CollectibleID: gift.ID}); ok || !tgerr.Is(err, "COLLECTIBLE_INVALID") {
|
||||
t.Fatalf("set non-owned collectible: ok=%v err=%v", ok, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollectibleEmojiStatusDurableUpdateProjection(t *testing.T) {
|
||||
collectible, ok := domain.CollectibleEmojiStatus(collectibleEmojiTestGift(1))
|
||||
if !ok {
|
||||
t.Fatal("test gift should project")
|
||||
}
|
||||
value := domain.UserEmojiStatus{DocumentID: collectible.DocumentID, Collectible: collectible}
|
||||
update, ok := tgOtherUpdateFromEvent(domain.UpdateEvent{
|
||||
UserID: 1, Type: domain.UpdateEventUserEmojiStatus, EmojiStatus: value,
|
||||
}).(*tg.UpdateUserEmojiStatus)
|
||||
if !ok {
|
||||
t.Fatal("durable event did not produce updateUserEmojiStatus")
|
||||
}
|
||||
if status, ok := update.EmojiStatus.(*tg.EmojiStatusCollectible); !ok || status.PatternDocumentID != collectible.PatternDocumentID {
|
||||
t.Fatalf("durable wire status = %T %#v", update.EmojiStatus, update.EmojiStatus)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue