2026-05-26 05:16:18 +08:00

649 lines
16 KiB
Go

package resource
import (
"strings"
"unicode/utf8"
"hyapp/services/wallet-service/internal/domain/ledger"
)
const (
TypeAvatarFrame = "avatar_frame"
TypeProfileCard = "profile_card"
TypeCoin = "coin"
TypeVehicle = "vehicle"
TypeChatBubble = "chat_bubble"
TypeBadge = "badge"
TypeFloatingScreen = "floating_screen"
TypeGift = "gift"
TypeMicSeatIcon = "mic_seat_icon"
TypeMicSeatAnimation = "mic_seat_animation"
TypeEmojiPack = "emoji_pack"
StatusActive = "active"
StatusDisabled = "disabled"
GrantStrategyWalletCredit = "wallet_credit"
GrantStrategyNewEntitlement = "new_entitlement"
GrantStrategyExtendExpiry = "extend_expiry"
GrantStrategyIncreaseQuantity = "increase_quantity"
GrantStrategySetActiveFlag = "set_active_flag"
GrantSubjectResource = "resource"
GrantSubjectGroup = "resource_group"
GrantSourceAdmin = "admin"
GrantSourceManagerCenter = "manager_center"
GrantSourceGrowthLevel = "growth_level"
GrantSourceAchievement = "achievement"
GrantStatusDone = "succeeded"
ResultWalletCredit = "wallet_credit"
ResultEntitlement = "entitlement"
GroupItemTypeResource = "resource"
GroupItemTypeWalletAsset = "wallet_asset"
GiftTypeNormal = "normal"
GiftTypeCP = "cp"
GiftTypeLucky = "lucky"
GiftTypeSuperLucky = "super_lucky"
GiftTypeExclusive = "exclusive"
GiftTypeNoble = "noble"
GiftTypeFlag = "flag"
GiftTypeActivity = "activity"
GiftTypeMagic = "magic"
GiftTypeCustom = "custom"
GiftTypeTabKeyNormal = "Gift"
GiftTypeTabKeyCP = "CP"
GiftTypeTabKeyLucky = "Lucky"
GiftTypeTabKeySuperLucky = "Super Lucky"
GiftTypeTabKeyExclusive = "Exclusive"
GiftTypeTabKeyNoble = "Noble"
GiftTypeTabKeyFlag = "Flag"
GiftTypeTabKeyActivity = "Activity"
GiftTypeTabKeyMagic = "Magic"
GiftTypeTabKeyCustom = "Custom"
GiftEffectAnimation = "animation"
GiftEffectMusic = "music"
GiftEffectGlobalBroadcast = "global_broadcast"
PriceTypeCoin = "coin"
PriceTypeFree = "free"
ShopDurationOneDay int32 = 1
ShopDurationThreeDays int32 = 3
ShopDurationSevenDays int32 = 7
)
type Resource struct {
AppCode string
ResourceID int64
ResourceCode string
ResourceType string
Name string
Status string
Grantable bool
GrantStrategy string
WalletAssetType string
WalletAssetAmount int64
PriceType string
CoinPrice int64
GiftPointAmount int64
UsageScopes []string
AssetURL string
PreviewURL string
AnimationURL string
MetadataJSON string
SortOrder int32
CreatedByUserID int64
UpdatedByUserID int64
CreatedAtMS int64
UpdatedAtMS int64
ManagerGrantEnabled bool
}
type ResourceGroupItem struct {
GroupItemID int64
GroupID int64
ItemType string
ResourceID int64
Resource Resource
WalletAssetType string
WalletAssetAmount int64
Quantity int64
DurationMS int64
SortOrder int32
CreatedAtMS int64
UpdatedAtMS int64
}
type ResourceGroup struct {
AppCode string
GroupID int64
GroupCode string
Name string
Status string
Description string
SortOrder int32
Items []ResourceGroupItem
CreatedByUserID int64
UpdatedByUserID int64
CreatedAtMS int64
UpdatedAtMS int64
}
type GiftConfig struct {
AppCode string
GiftID string
ResourceID int64
Resource Resource
Status string
Name string
SortOrder int32
PresentationJSON string
PriceVersion string
CoinPrice int64
GiftPointAmount int64
HeatValue int64
GiftTypeCode string
ChargeAssetType string
EffectiveFromMS int64
EffectiveToMS int64
EffectTypes []string
CreatedByUserID int64
UpdatedByUserID int64
CreatedAtMS int64
UpdatedAtMS int64
RegionIDs []int64
}
type GiftTypeConfig struct {
AppCode string
TypeCode string
Name string
TabKey string
Status string
SortOrder int32
CreatedByUserID int64
UpdatedByUserID int64
CreatedAtMS int64
UpdatedAtMS int64
}
type ResourceShopItem struct {
AppCode string
ShopItemID int64
ResourceID int64
Resource Resource
Status string
DurationDays int32
PriceType string
CoinPrice int64
EffectiveFromMS int64
EffectiveToMS int64
SortOrder int32
CreatedByUserID int64
UpdatedByUserID int64
CreatedAtMS int64
UpdatedAtMS int64
}
type UserResourceEntitlement struct {
AppCode string
EntitlementID string
UserID int64
ResourceID int64
Resource Resource
Status string
Quantity int64
RemainingQuantity int64
EffectiveAtMS int64
ExpiresAtMS int64
SourceGrantID string
CreatedAtMS int64
UpdatedAtMS int64
}
type ResourceGrantItem struct {
GrantItemID int64
GrantID string
ResourceID int64
ResourceSnapshotJSON string
Quantity int64
DurationMS int64
ResultType string
WalletTransactionID string
EntitlementID string
CreatedAtMS int64
}
type ResourceGrant struct {
AppCode string
GrantID string
CommandID string
TargetUserID int64
GrantSource string
GrantSubjectType string
GrantSubjectID string
Status string
Reason string
OperatorUserID int64
Items []ResourceGrantItem
CreatedAtMS int64
UpdatedAtMS int64
}
type ListResourcesQuery struct {
AppCode string
ResourceType string
Status string
Keyword string
Page int32
PageSize int32
ActiveOnly bool
ManagerGrantOnly bool
}
type ResourceCommand struct {
AppCode string
ResourceID int64
ResourceCode string
ResourceType string
Name string
Status string
Grantable bool
GrantStrategy string
WalletAssetType string
WalletAssetAmount int64
PriceType string
CoinPrice int64
GiftPointAmount int64
UsageScopes []string
AssetURL string
PreviewURL string
AnimationURL string
MetadataJSON string
SortOrder int32
OperatorUserID int64
ManagerGrantEnabled bool
}
type StatusCommand struct {
AppCode string
ID int64
StringID string
Status string
OperatorUserID int64
}
type ResourceGroupItemInput struct {
ItemType string
ResourceID int64
WalletAssetType string
WalletAssetAmount int64
Quantity int64
DurationMS int64
SortOrder int32
}
type ListResourceGroupsQuery struct {
AppCode string
Status string
Keyword string
Page int32
PageSize int32
ActiveOnly bool
}
type ResourceGroupCommand struct {
AppCode string
GroupID int64
GroupCode string
Name string
Status string
Description string
SortOrder int32
Items []ResourceGroupItemInput
OperatorUserID int64
}
type ListGiftConfigsQuery struct {
AppCode string
Status string
Keyword string
Page int32
PageSize int32
ActiveOnly bool
RegionID int64
FilterRegion bool
}
type ListGiftTypeConfigsQuery struct {
AppCode string
Status string
ActiveOnly bool
}
type GiftConfigCommand struct {
AppCode string
GiftID string
ResourceID int64
Status string
Name string
SortOrder int32
PresentationJSON string
PriceVersion string
CoinPrice int64
GiftPointAmount int64
HeatValue int64
EffectiveAtMS int64
GiftTypeCode string
ChargeAssetType string
EffectiveFromMS int64
EffectiveToMS int64
EffectTypes []string
OperatorUserID int64
RegionIDs []int64
}
type GiftTypeConfigCommand struct {
AppCode string
TypeCode string
Name string
TabKey string
Status string
SortOrder int32
OperatorUserID int64
}
type GrantResourceCommand struct {
AppCode string
CommandID string
TargetUserID int64
ResourceID int64
Quantity int64
DurationMS int64
Reason string
OperatorUserID int64
GrantSource string
}
type GrantResourceGroupCommand struct {
AppCode string
CommandID string
TargetUserID int64
GroupID int64
Reason string
OperatorUserID int64
GrantSource string
}
type ListUserResourcesQuery struct {
AppCode string
UserID int64
ResourceType string
ActiveOnly bool
}
type EquipUserResourceCommand struct {
AppCode string
UserID int64
ResourceID int64
EntitlementID string
}
type ListResourceGrantsQuery struct {
AppCode string
TargetUserID int64
Status string
Page int32
PageSize int32
}
type ResourceShopItemInput struct {
ShopItemID int64
ResourceID int64
Status string
DurationDays int32
EffectiveFromMS int64
EffectiveToMS int64
SortOrder int32
}
type ListResourceShopItemsQuery struct {
AppCode string
ResourceType string
Status string
Keyword string
Page int32
PageSize int32
ActiveOnly bool
}
type ResourceShopItemsCommand struct {
AppCode string
Items []ResourceShopItemInput
OperatorUserID int64
}
type ResourceShopItemStatusCommand struct {
AppCode string
ShopItemID int64
Status string
OperatorUserID int64
}
// BadgeGrantOutbox is a wallet resource grant event relayed to activity-service badge display projection.
type BadgeGrantOutbox struct {
AppCode string
EventID string
EventType string
CommandID string
UserID int64
GrantID string
GrantSource string
PayloadJSON string
Status string
AttemptCount int32
FailureReason string
CreatedAtMS int64
UpdatedAtMS int64
Items []BadgeGrantItem
}
// BadgeGrantItem is the badge subset of a resource grant item.
type BadgeGrantItem struct {
ResourceID int64 `json:"resource_id"`
ResourceCode string `json:"resource_code"`
ResourceType string `json:"resource_type"`
Name string `json:"name"`
EntitlementID string `json:"entitlement_id"`
ResourceSnapshotJSON string `json:"resource_snapshot_json"`
MetadataJSON string `json:"metadata_json"`
}
func NormalizeStatus(value string) string {
value = strings.ToLower(strings.TrimSpace(value))
if value == "" {
return StatusActive
}
return value
}
func NormalizeGrantSource(value string) string {
value = strings.ToLower(strings.TrimSpace(value))
if value == "" {
return GrantSourceAdmin
}
return value
}
func ValidResourceType(value string) bool {
switch strings.ToLower(strings.TrimSpace(value)) {
case TypeAvatarFrame, TypeProfileCard, TypeCoin, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeGift, TypeMicSeatIcon, TypeMicSeatAnimation, TypeEmojiPack:
return true
default:
return false
}
}
func ResourceTypeSellableInShop(value string) bool {
switch NormalizeResourceType(value) {
case TypeAvatarFrame, TypeProfileCard, TypeVehicle, TypeChatBubble, TypeBadge, TypeMicSeatIcon, TypeMicSeatAnimation:
return true
default:
return false
}
}
func ValidShopDurationDays(value int32) bool {
switch value {
case ShopDurationOneDay, ShopDurationThreeDays, ShopDurationSevenDays:
return true
default:
return false
}
}
func ValidStatus(value string) bool {
switch NormalizeStatus(value) {
case StatusActive, StatusDisabled:
return true
default:
return false
}
}
func ValidGrantStrategy(value string) bool {
switch strings.ToLower(strings.TrimSpace(value)) {
case GrantStrategyWalletCredit, GrantStrategyNewEntitlement, GrantStrategyExtendExpiry, GrantStrategyIncreaseQuantity, GrantStrategySetActiveFlag:
return true
default:
return false
}
}
func NormalizeGroupItemType(value string) string {
value = strings.ToLower(strings.TrimSpace(value))
if value == "" {
return GroupItemTypeResource
}
return value
}
func ValidGroupItemType(value string) bool {
switch NormalizeGroupItemType(value) {
case GroupItemTypeResource, GroupItemTypeWalletAsset:
return true
default:
return false
}
}
func NormalizeResourceType(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
func NormalizeGrantStrategy(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
func NormalizeWalletAssetType(value string) string {
return strings.ToUpper(strings.TrimSpace(value))
}
func NormalizePriceType(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
func ValidPriceType(value string) bool {
switch NormalizePriceType(value) {
case PriceTypeCoin, PriceTypeFree:
return true
default:
return false
}
}
func NormalizeGiftTypeCode(value string) string {
value = strings.ToLower(strings.TrimSpace(value))
value = strings.ReplaceAll(value, "-", "_")
if value == "" {
return GiftTypeNormal
}
return value
}
func ValidGiftTypeCode(value string) bool {
value = NormalizeGiftTypeCode(value)
if value == "" || len(value) > 32 {
return false
}
for index, char := range value {
if index == 0 && (char < 'a' || char > 'z') {
return false
}
if (char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char == '_' {
continue
}
return false
}
return true
}
func NormalizeGiftTypeTabKey(value string) string {
return strings.TrimSpace(value)
}
func ValidGiftTypeTabKey(value string) bool {
value = NormalizeGiftTypeTabKey(value)
return value != "" && utf8.RuneCountInString(value) <= 32
}
func DefaultGiftTypeConfigs(appCode string) []GiftTypeConfig {
appCode = strings.TrimSpace(appCode)
defaults := []GiftTypeConfig{
{TypeCode: GiftTypeNormal, Name: "普通礼物", TabKey: GiftTypeTabKeyNormal, Status: StatusActive, SortOrder: 10},
{TypeCode: GiftTypeCP, Name: "CP礼物", TabKey: GiftTypeTabKeyCP, Status: StatusActive, SortOrder: 20},
{TypeCode: GiftTypeLucky, Name: "幸运礼物", TabKey: GiftTypeTabKeyLucky, Status: StatusActive, SortOrder: 30},
{TypeCode: GiftTypeSuperLucky, Name: "超级幸运礼物", TabKey: GiftTypeTabKeySuperLucky, Status: StatusActive, SortOrder: 40},
{TypeCode: GiftTypeExclusive, Name: "专属礼物", TabKey: GiftTypeTabKeyExclusive, Status: StatusActive, SortOrder: 50},
{TypeCode: GiftTypeNoble, Name: "贵族礼物", TabKey: GiftTypeTabKeyNoble, Status: StatusActive, SortOrder: 60},
{TypeCode: GiftTypeFlag, Name: "国旗礼物", TabKey: GiftTypeTabKeyFlag, Status: StatusActive, SortOrder: 70},
{TypeCode: GiftTypeActivity, Name: "活动礼物", TabKey: GiftTypeTabKeyActivity, Status: StatusActive, SortOrder: 80},
{TypeCode: GiftTypeMagic, Name: "魔法礼物", TabKey: GiftTypeTabKeyMagic, Status: StatusActive, SortOrder: 90},
{TypeCode: GiftTypeCustom, Name: "定制礼物", TabKey: GiftTypeTabKeyCustom, Status: StatusActive, SortOrder: 100},
}
for index := range defaults {
defaults[index].AppCode = appCode
}
return defaults
}
func NormalizeGiftEffectType(value string) string {
return strings.ToLower(strings.TrimSpace(value))
}
func ValidGiftEffectType(value string) bool {
switch NormalizeGiftEffectType(value) {
case GiftEffectAnimation, GiftEffectMusic, GiftEffectGlobalBroadcast:
return true
default:
return false
}
}
func IsWalletCredit(resource Resource) bool {
return NormalizeGrantStrategy(resource.GrantStrategy) == GrantStrategyWalletCredit
}
func IsCoinResource(resource Resource) bool {
return NormalizeResourceType(resource.ResourceType) == TypeCoin
}
func WalletAssetForCoin() string {
return ledger.AssetCoin
}