97 lines
3.1 KiB
Go
97 lines
3.1 KiB
Go
package files
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
// Star gift 目录:从已 seed 的 animated_emoji 集按 emoticon 精选贴纸文档合成(复用文档行与
|
||
// blob,不复制字节),镜像 EnsureDefaultEmojiStatusSet。目录是静态的,不入库。
|
||
// 礼物 ID 取明显隔离的常量段避免撞键。
|
||
|
||
const starGiftIDBase int64 = 8_888_000_000_000_000
|
||
|
||
type starGiftSeed struct {
|
||
id int64
|
||
emoticon string
|
||
stars int64
|
||
title string
|
||
}
|
||
|
||
// starGiftSeeds 是固定礼物目录(emoticon 需在 animated_emoji 集里,否则该礼物被跳过)。
|
||
// convert_stars = stars(v1 全额转换,视作用新购 Stars 买入)。
|
||
var starGiftSeeds = []starGiftSeed{
|
||
{starGiftIDBase + 1, "❤", 15, "Heart"},
|
||
{starGiftIDBase + 2, "\U0001f382", 50, "Cake"}, // 🎂
|
||
{starGiftIDBase + 3, "\U0001f389", 100, "Party"}, // 🎉
|
||
{starGiftIDBase + 4, "\U0001f525", 250, "Fire"}, // 🔥
|
||
{starGiftIDBase + 5, "\U0001f3c6", 500, "Trophy"}, // 🏆
|
||
{starGiftIDBase + 6, "\U0001f48e", 1000, "Diamond"}, // 💎
|
||
{starGiftIDBase + 7, "\U0001f680", 2500, "Rocket"}, // 🚀
|
||
}
|
||
|
||
// BuildStarGiftCatalog 合成可购买礼物目录:解析每个 seed emoticon 的贴纸文档,跳过未 seed 的。
|
||
// animated_emoji 未 seed 时返回空目录(客户端显示空礼物面板,购买流仍可对已知 gift_id 工作)。
|
||
func (s *Service) BuildStarGiftCatalog(ctx context.Context) ([]domain.StarGift, error) {
|
||
source, found, err := s.media.GetStickerSetBySystemKey(ctx, "animated_emoji")
|
||
if err != nil {
|
||
return nil, fmt.Errorf("lookup animated_emoji set for star gifts: %w", err)
|
||
}
|
||
if !found || len(source.Packs) == 0 {
|
||
return nil, nil
|
||
}
|
||
byEmoticon := make(map[string]int64, len(source.Packs))
|
||
for _, pack := range source.Packs {
|
||
key := normalizeStatusEmoticon(pack.Emoticon)
|
||
if key == "" || len(pack.DocumentIDs) == 0 {
|
||
continue
|
||
}
|
||
if _, ok := byEmoticon[key]; !ok {
|
||
byEmoticon[key] = pack.DocumentIDs[0]
|
||
}
|
||
}
|
||
// 收集要加载的文档 id(去重)。
|
||
docIDs := make([]int64, 0, len(starGiftSeeds))
|
||
chosen := make([]starGiftSeed, 0, len(starGiftSeeds))
|
||
seen := make(map[int64]struct{})
|
||
for _, seed := range starGiftSeeds {
|
||
id, ok := byEmoticon[normalizeStatusEmoticon(seed.emoticon)]
|
||
if !ok || id == 0 {
|
||
continue
|
||
}
|
||
chosen = append(chosen, seed)
|
||
if _, dup := seen[id]; !dup {
|
||
seen[id] = struct{}{}
|
||
docIDs = append(docIDs, id)
|
||
}
|
||
}
|
||
if len(chosen) == 0 {
|
||
return nil, nil
|
||
}
|
||
docs, err := s.media.GetDocuments(ctx, docIDs)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("load star gift sticker documents: %w", err)
|
||
}
|
||
docByID := make(map[int64]domain.Document, len(docs))
|
||
for _, d := range docs {
|
||
docByID[d.ID] = d
|
||
}
|
||
catalog := make([]domain.StarGift, 0, len(chosen))
|
||
for _, seed := range chosen {
|
||
id := byEmoticon[normalizeStatusEmoticon(seed.emoticon)]
|
||
doc, ok := docByID[id]
|
||
if !ok || doc.ID == 0 {
|
||
continue
|
||
}
|
||
catalog = append(catalog, domain.StarGift{
|
||
ID: seed.id,
|
||
Stars: seed.stars,
|
||
ConvertStars: seed.stars,
|
||
Title: seed.title,
|
||
Sticker: doc,
|
||
})
|
||
}
|
||
return catalog, nil
|
||
}
|