package activityapi import ( "net/http" "strings" activityv1 "hyapp.local/api/proto/activity/v1" "hyapp/services/gateway-service/internal/auth" "hyapp/services/gateway-service/internal/transport/http/httpkit" ) type levelOverviewData struct { Tracks []levelTrackOverviewData `json:"tracks"` ServerTimeMS int64 `json:"server_time_ms"` } type levelTrackOverviewData struct { Track string `json:"track"` Name string `json:"name"` Level int32 `json:"level"` TierID int64 `json:"tier_id"` TotalValue int64 `json:"total_value"` CurrentLevelRequiredValue int64 `json:"current_level_required_value"` NextLevel int32 `json:"next_level"` NextLevelRequiredValue int64 `json:"next_level_required_value"` DisplayAvatarFrameResourceID int64 `json:"display_avatar_frame_resource_id"` DisplayBadgeResourceID int64 `json:"display_badge_resource_id"` DisplayBadgeSourceLevel int32 `json:"display_badge_source_level"` RewardPendingCount int64 `json:"reward_pending_count"` SortOrder int32 `json:"sort_order"` } type levelTrackDetailData struct { Overview levelTrackOverviewData `json:"overview"` Rules []levelRuleData `json:"rules"` Tiers []levelTierData `json:"tiers"` ServerTimeMS int64 `json:"server_time_ms"` } type levelRuleData struct { Track string `json:"track"` Level int32 `json:"level"` RequiredValue int64 `json:"required_value"` Name string `json:"name"` Status string `json:"status"` RewardResourceGroupID int64 `json:"reward_resource_group_id"` SortOrder int32 `json:"sort_order"` DisplayConfigJSON string `json:"display_config_json"` CreatedByAdminID int64 `json:"created_by_admin_id"` UpdatedByAdminID int64 `json:"updated_by_admin_id"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` } type levelTierData struct { TierID int64 `json:"tier_id"` Track string `json:"track"` MinLevel int32 `json:"min_level"` MaxLevel int32 `json:"max_level"` Name string `json:"name"` DisplayAvatarFrameResourceID int64 `json:"display_avatar_frame_resource_id"` DisplayBadgeResourceID int64 `json:"display_badge_resource_id"` RewardResourceGroupID int64 `json:"reward_resource_group_id"` Status string `json:"status"` DisplayConfigJSON string `json:"display_config_json"` CreatedByAdminID int64 `json:"created_by_admin_id"` UpdatedByAdminID int64 `json:"updated_by_admin_id"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` } type levelRewardData struct { RewardJobID string `json:"reward_job_id"` UserID int64 `json:"user_id"` Track string `json:"track"` RewardSourceType string `json:"reward_source_type"` RewardSourceID string `json:"reward_source_id"` ResourceGroupID int64 `json:"resource_group_id"` WalletCommandID string `json:"wallet_command_id"` WalletGrantID string `json:"wallet_grant_id"` Status string `json:"status"` AttemptCount int32 `json:"attempt_count"` FailureReason string `json:"failure_reason"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` } func (h *Handler) getMyLevelOverview(writer http.ResponseWriter, request *http.Request) { if h.growthLevelClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") return } resp, err := h.growthLevelClient.GetMyLevelOverview(request.Context(), &activityv1.GetMyLevelOverviewRequest{ Meta: httpkit.ActivityMeta(request), UserId: auth.UserIDFromContext(request.Context()), }) if err != nil { httpkit.WriteRPCError(writer, request, err) return } tracks := make([]levelTrackOverviewData, 0, len(resp.GetTracks())) for _, item := range resp.GetTracks() { tracks = append(tracks, levelTrackOverviewFromProto(item)) } httpkit.WriteOK(writer, request, levelOverviewData{Tracks: tracks, ServerTimeMS: resp.GetServerTimeMs()}) } func (h *Handler) getLevelTrack(writer http.ResponseWriter, request *http.Request) { if h.growthLevelClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") return } track := strings.TrimSpace(request.PathValue("track")) if track == "" { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } resp, err := h.growthLevelClient.GetLevelTrack(request.Context(), &activityv1.GetLevelTrackRequest{ Meta: httpkit.ActivityMeta(request), UserId: auth.UserIDFromContext(request.Context()), Track: track, }) if err != nil { httpkit.WriteRPCError(writer, request, err) return } rules := make([]levelRuleData, 0, len(resp.GetRules())) for _, rule := range resp.GetRules() { rules = append(rules, levelRuleFromProto(rule)) } tiers := make([]levelTierData, 0, len(resp.GetTiers())) for _, tier := range resp.GetTiers() { tiers = append(tiers, levelTierFromProto(tier)) } httpkit.WriteOK(writer, request, levelTrackDetailData{ Overview: levelTrackOverviewFromProto(resp.GetOverview()), Rules: rules, Tiers: tiers, ServerTimeMS: resp.GetServerTimeMs(), }) } func (h *Handler) listLevelRewards(writer http.ResponseWriter, request *http.Request) { if h.growthLevelClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") return } page, ok := httpkit.PositiveInt32Query(request, "page", 1) if !ok { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } pageSize, ok := httpkit.PositiveInt32Query(request, "page_size", 20) if !ok { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } resp, err := h.growthLevelClient.ListLevelRewards(request.Context(), &activityv1.ListLevelRewardsRequest{ Meta: httpkit.ActivityMeta(request), UserId: auth.UserIDFromContext(request.Context()), Track: strings.TrimSpace(request.URL.Query().Get("track")), Status: strings.TrimSpace(request.URL.Query().Get("status")), Page: page, PageSize: pageSize, }) if err != nil { httpkit.WriteRPCError(writer, request, err) return } rewards := make([]levelRewardData, 0, len(resp.GetRewards())) for _, reward := range resp.GetRewards() { rewards = append(rewards, levelRewardFromProto(reward)) } httpkit.WriteOK(writer, request, map[string]any{ "rewards": rewards, "total": resp.GetTotal(), "page": page, "page_size": pageSize, }) } func levelTrackOverviewFromProto(item *activityv1.LevelTrackOverview) levelTrackOverviewData { return levelTrackOverviewData{ Track: item.GetTrack(), Name: item.GetName(), Level: item.GetLevel(), TierID: item.GetTierId(), TotalValue: item.GetTotalValue(), CurrentLevelRequiredValue: item.GetCurrentLevelRequiredValue(), NextLevel: item.GetNextLevel(), NextLevelRequiredValue: item.GetNextLevelRequiredValue(), DisplayAvatarFrameResourceID: item.GetDisplayAvatarFrameResourceId(), DisplayBadgeResourceID: item.GetDisplayBadgeResourceId(), DisplayBadgeSourceLevel: item.GetDisplayBadgeSourceLevel(), RewardPendingCount: item.GetRewardPendingCount(), SortOrder: item.GetSortOrder(), } } func levelRuleFromProto(item *activityv1.LevelRule) levelRuleData { return levelRuleData{ Track: item.GetTrack(), Level: item.GetLevel(), RequiredValue: item.GetRequiredValue(), Name: item.GetName(), Status: item.GetStatus(), RewardResourceGroupID: item.GetRewardResourceGroupId(), SortOrder: item.GetSortOrder(), DisplayConfigJSON: item.GetDisplayConfigJson(), CreatedByAdminID: item.GetCreatedByAdminId(), UpdatedByAdminID: item.GetUpdatedByAdminId(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), } } func levelTierFromProto(item *activityv1.LevelTier) levelTierData { return levelTierData{ TierID: item.GetTierId(), Track: item.GetTrack(), MinLevel: item.GetMinLevel(), MaxLevel: item.GetMaxLevel(), Name: item.GetName(), DisplayAvatarFrameResourceID: item.GetDisplayAvatarFrameResourceId(), DisplayBadgeResourceID: item.GetDisplayBadgeResourceId(), RewardResourceGroupID: item.GetRewardResourceGroupId(), Status: item.GetStatus(), DisplayConfigJSON: item.GetDisplayConfigJson(), CreatedByAdminID: item.GetCreatedByAdminId(), UpdatedByAdminID: item.GetUpdatedByAdminId(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), } } func levelRewardFromProto(item *activityv1.LevelRewardJob) levelRewardData { return levelRewardData{ RewardJobID: item.GetRewardJobId(), UserID: item.GetUserId(), Track: item.GetTrack(), RewardSourceType: item.GetRewardSourceType(), RewardSourceID: item.GetRewardSourceId(), ResourceGroupID: item.GetResourceGroupId(), WalletCommandID: item.GetWalletCommandId(), WalletGrantID: item.GetWalletGrantId(), Status: item.GetStatus(), AttemptCount: item.GetAttemptCount(), FailureReason: item.GetFailureReason(), CreatedAtMS: item.GetCreatedAtMs(), UpdatedAtMS: item.GetUpdatedAtMs(), } }