package grpc import ( "context" activityv1 "hyapp.local/api/proto/activity/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" domain "hyapp/services/activity-service/internal/domain/luckygift" service "hyapp/services/activity-service/internal/service/luckygift" ) // LuckyGiftServer 暴露房间送礼主链路调用的幸运礼物查询和抽奖入口。 type LuckyGiftServer struct { activityv1.UnimplementedLuckyGiftServiceServer svc *service.Service } func NewLuckyGiftServer(svc *service.Service) *LuckyGiftServer { return &LuckyGiftServer{svc: svc} } func (s *LuckyGiftServer) CheckLuckyGift(ctx context.Context, req *activityv1.CheckLuckyGiftRequest) (*activityv1.CheckLuckyGiftResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) result, err := s.svc.Check(ctx, domain.CheckCommand{ PoolID: req.GetPoolId(), GiftID: req.GetGiftId(), UserID: req.GetUserId(), RoomID: req.GetRoomId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &activityv1.CheckLuckyGiftResponse{ Enabled: result.Enabled, Reason: result.Reason, PoolId: result.PoolID, GiftId: result.GiftID, GiftPrice: result.GiftPrice, RuleVersion: result.RuleVersion, TargetRtpPpm: result.TargetRTPPPM, ExperiencePool: result.ExperiencePool, }, nil } func (s *LuckyGiftServer) ExecuteLuckyGiftDraw(ctx context.Context, req *activityv1.ExecuteLuckyGiftDrawRequest) (*activityv1.ExecuteLuckyGiftDrawResponse, error) { meta := req.GetLuckyGift() ctx = appcode.WithContext(ctx, meta.GetMeta().GetAppCode()) result, err := s.svc.Draw(ctx, domain.DrawCommand{ CommandID: meta.GetCommandId(), PoolID: meta.GetPoolId(), UserID: meta.GetUserId(), DeviceID: meta.GetDeviceId(), RoomID: meta.GetRoomId(), AnchorID: meta.GetAnchorId(), GiftID: meta.GetGiftId(), CoinSpent: meta.GetCoinSpent(), PaidAtMS: meta.GetPaidAtMs(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &activityv1.ExecuteLuckyGiftDrawResponse{Result: luckyDrawResultToProto(result)}, nil } // AdminLuckyGiftServer 暴露后台幸运礼物规则配置和抽奖审计入口。 type AdminLuckyGiftServer struct { activityv1.UnimplementedAdminLuckyGiftServiceServer svc *service.Service } func NewAdminLuckyGiftServer(svc *service.Service) *AdminLuckyGiftServer { return &AdminLuckyGiftServer{svc: svc} } func (s *AdminLuckyGiftServer) GetLuckyGiftConfig(ctx context.Context, req *activityv1.GetLuckyGiftConfigRequest) (*activityv1.GetLuckyGiftConfigResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) config, err := s.svc.GetConfig(ctx, req.GetPoolId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &activityv1.GetLuckyGiftConfigResponse{Config: luckyConfigToProto(config)}, nil } func (s *AdminLuckyGiftServer) UpsertLuckyGiftConfig(ctx context.Context, req *activityv1.UpsertLuckyGiftConfigRequest) (*activityv1.UpsertLuckyGiftConfigResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) config := luckyConfigFromProto(req.GetConfig()) config.UpdatedByAdminID = req.GetOperatorAdminId() updated, err := s.svc.UpsertConfig(ctx, config) if err != nil { return nil, xerr.ToGRPCError(err) } return &activityv1.UpsertLuckyGiftConfigResponse{Config: luckyConfigToProto(updated)}, nil } func (s *AdminLuckyGiftServer) ListLuckyGiftConfigs(ctx context.Context, req *activityv1.ListLuckyGiftConfigsRequest) (*activityv1.ListLuckyGiftConfigsResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) configs, err := s.svc.ListConfigs(ctx) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &activityv1.ListLuckyGiftConfigsResponse{Configs: make([]*activityv1.LuckyGiftConfig, 0, len(configs))} for _, config := range configs { resp.Configs = append(resp.Configs, luckyConfigToProto(config)) } return resp, nil } func (s *AdminLuckyGiftServer) ListLuckyGiftDraws(ctx context.Context, req *activityv1.ListLuckyGiftDrawsRequest) (*activityv1.ListLuckyGiftDrawsResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) draws, total, err := s.svc.ListDraws(ctx, domain.DrawQuery{ GiftID: req.GetGiftId(), PoolID: req.GetPoolId(), UserID: req.GetUserId(), RoomID: req.GetRoomId(), Status: req.GetStatus(), Page: req.GetPage(), PageSize: req.GetPageSize(), }) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &activityv1.ListLuckyGiftDrawsResponse{Draws: make([]*activityv1.LuckyGiftDrawResult, 0, len(draws)), Total: total} for _, draw := range draws { resp.Draws = append(resp.Draws, luckyDrawResultToProto(draw)) } return resp, nil } func (s *AdminLuckyGiftServer) GetLuckyGiftDrawSummary(ctx context.Context, req *activityv1.GetLuckyGiftDrawSummaryRequest) (*activityv1.GetLuckyGiftDrawSummaryResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) summary, err := s.svc.GetDrawSummary(ctx, domain.DrawQuery{ GiftID: req.GetGiftId(), PoolID: req.GetPoolId(), UserID: req.GetUserId(), RoomID: req.GetRoomId(), Status: req.GetStatus(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &activityv1.GetLuckyGiftDrawSummaryResponse{Summary: luckyDrawSummaryToProto(summary)}, nil } func luckyConfigFromProto(config *activityv1.LuckyGiftConfig) domain.Config { if config == nil { return domain.Config{} } tiers := make([]domain.Tier, 0, len(config.GetTiers())) for _, tier := range config.GetTiers() { tiers = append(tiers, domain.Tier{ Pool: tier.GetPool(), TierID: tier.GetTierId(), RewardCoins: tier.GetRewardCoins(), MultiplierPPM: tier.GetMultiplierPpm(), Weight: tier.GetWeight(), HighWaterOnly: tier.GetHighWaterOnly(), Enabled: tier.GetEnabled(), }) } return domain.Config{ AppCode: config.GetAppCode(), GiftID: config.GetGiftId(), PoolID: config.GetPoolId(), Enabled: config.GetEnabled(), RuleVersion: config.GetRuleVersion(), GiftPrice: config.GetGiftPrice(), TargetRTPPPM: config.GetTargetRtpPpm(), PoolRatePPM: config.GetPoolRatePpm(), GlobalWindowDraws: config.GetGlobalWindowDraws(), GiftWindowDraws: config.GetGiftWindowDraws(), NoviceDrawLimit: config.GetNoviceDrawLimit(), IntermediateDrawLimit: config.GetIntermediateDrawLimit(), HighMultiplier: config.GetHighMultiplier(), HighWaterPoolMultiple: config.GetHighWaterPoolMultiple(), PlatformPoolWeightPPM: config.GetPlatformPoolWeightPpm(), RoomPoolWeightPPM: config.GetRoomPoolWeightPpm(), GiftPoolWeightPPM: config.GetGiftPoolWeightPpm(), InitialPlatformPool: config.GetInitialPlatformPool(), InitialGiftPool: config.GetInitialGiftPool(), InitialRoomPool: config.GetInitialRoomPool(), PlatformReserve: config.GetPlatformReserve(), GiftReserve: config.GetGiftReserve(), RoomReserve: config.GetRoomReserve(), MaxSinglePayout: config.GetMaxSinglePayout(), UserHourlyPayoutCap: config.GetUserHourlyPayoutCap(), UserDailyPayoutCap: config.GetUserDailyPayoutCap(), DeviceDailyPayoutCap: config.GetDeviceDailyPayoutCap(), RoomHourlyPayoutCap: config.GetRoomHourlyPayoutCap(), AnchorDailyPayoutCap: config.GetAnchorDailyPayoutCap(), RoomAtmosphereRatePPM: config.GetRoomAtmosphereRatePpm(), RoomAtmosphereInitial: config.GetRoomAtmosphereInitial(), RoomAtmosphereReserve: config.GetRoomAtmosphereReserve(), ActivityBudget: config.GetActivityBudget(), ActivityDailyLimit: config.GetActivityDailyLimit(), LargeTierEnabled: config.GetLargeTierEnabled(), MultiplierPPMs: append([]int64(nil), config.GetMultiplierPpms()...), Tiers: tiers, UpdatedByAdminID: config.GetUpdatedByAdminId(), CreatedAtMS: config.GetCreatedAtMs(), UpdatedAtMS: config.GetUpdatedAtMs(), } } func luckyConfigToProto(config domain.Config) *activityv1.LuckyGiftConfig { tiers := make([]*activityv1.LuckyGiftTier, 0, len(config.Tiers)) for _, tier := range config.Tiers { tiers = append(tiers, &activityv1.LuckyGiftTier{ Pool: tier.Pool, TierId: tier.TierID, RewardCoins: tier.RewardCoins, MultiplierPpm: tier.MultiplierPPM, Weight: tier.Weight, HighWaterOnly: tier.HighWaterOnly, Enabled: tier.Enabled, }) } return &activityv1.LuckyGiftConfig{ AppCode: config.AppCode, GiftId: config.GiftID, PoolId: config.PoolID, Enabled: config.Enabled, RuleVersion: config.RuleVersion, GiftPrice: config.GiftPrice, TargetRtpPpm: config.TargetRTPPPM, PoolRatePpm: config.PoolRatePPM, GlobalWindowDraws: config.GlobalWindowDraws, GiftWindowDraws: config.GiftWindowDraws, NoviceDrawLimit: config.NoviceDrawLimit, IntermediateDrawLimit: config.IntermediateDrawLimit, HighMultiplier: config.HighMultiplier, HighWaterPoolMultiple: config.HighWaterPoolMultiple, PlatformPoolWeightPpm: config.PlatformPoolWeightPPM, RoomPoolWeightPpm: config.RoomPoolWeightPPM, GiftPoolWeightPpm: config.GiftPoolWeightPPM, InitialPlatformPool: config.InitialPlatformPool, InitialGiftPool: config.InitialGiftPool, InitialRoomPool: config.InitialRoomPool, PlatformReserve: config.PlatformReserve, GiftReserve: config.GiftReserve, RoomReserve: config.RoomReserve, MaxSinglePayout: config.MaxSinglePayout, UserHourlyPayoutCap: config.UserHourlyPayoutCap, UserDailyPayoutCap: config.UserDailyPayoutCap, DeviceDailyPayoutCap: config.DeviceDailyPayoutCap, RoomHourlyPayoutCap: config.RoomHourlyPayoutCap, AnchorDailyPayoutCap: config.AnchorDailyPayoutCap, RoomAtmosphereRatePpm: config.RoomAtmosphereRatePPM, RoomAtmosphereInitial: config.RoomAtmosphereInitial, RoomAtmosphereReserve: config.RoomAtmosphereReserve, ActivityBudget: config.ActivityBudget, ActivityDailyLimit: config.ActivityDailyLimit, LargeTierEnabled: config.LargeTierEnabled, MultiplierPpms: append([]int64(nil), config.MultiplierPPMs...), Tiers: tiers, UpdatedByAdminId: config.UpdatedByAdminID, CreatedAtMs: config.CreatedAtMS, UpdatedAtMs: config.UpdatedAtMS, } } func luckyDrawResultToProto(result domain.DrawResult) *activityv1.LuckyGiftDrawResult { return &activityv1.LuckyGiftDrawResult{ DrawId: result.DrawID, CommandId: result.CommandID, PoolId: result.PoolID, GiftId: result.GiftID, RuleVersion: result.RuleVersion, ExperiencePool: result.ExperiencePool, SelectedTierId: result.SelectedTierID, BaseRewardCoins: result.BaseRewardCoins, RoomAtmosphereRewardCoins: result.RoomAtmosphereRewardCoins, ActivitySubsidyCoins: result.ActivitySubsidyCoins, EffectiveRewardCoins: result.EffectiveRewardCoins, BudgetSourcesJson: result.BudgetSourcesJSON, RewardStatus: result.RewardStatus, RtpWindowIndex: result.RTPWindowIndex, GiftRtpWindowIndex: result.GiftRTPWindowIndex, GlobalBaseRtpPpm: result.GlobalBaseRTPPPM, GiftBaseRtpPpm: result.GiftBaseRTPPPM, StageFeedback: result.StageFeedback, HighMultiplier: result.HighMultiplier, CreatedAtMs: result.CreatedAtMS, } } func luckyDrawSummaryToProto(summary domain.DrawSummary) *activityv1.LuckyGiftDrawSummary { return &activityv1.LuckyGiftDrawSummary{ PoolId: summary.PoolID, TotalDraws: summary.TotalDraws, UniqueUsers: summary.UniqueUsers, UniqueRooms: summary.UniqueRooms, TotalSpentCoins: summary.TotalSpentCoins, TotalRewardCoins: summary.TotalRewardCoins, BaseRewardCoins: summary.BaseRewardCoins, RoomAtmosphereRewardCoins: summary.RoomAtmosphereRewardCoins, ActivitySubsidyCoins: summary.ActivitySubsidyCoins, ActualRtpPpm: summary.ActualRTPPPM, PendingDraws: summary.PendingDraws, GrantedDraws: summary.GrantedDraws, FailedDraws: summary.FailedDraws, } }