From 4af7844d1b554159afa40cfdc11a0b2496f6ce08 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 22 May 2026 11:57:04 +0800 Subject: [PATCH] =?UTF-8?q?zeeone=20=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/proto/activity/v1/activity.pb.go | 2072 +++++++++++++---- api/proto/activity/v1/activity.proto | 129 + api/proto/activity/v1/activity_grpc.pb.go | 330 ++- server/admin/cmd/server/main.go | 60 +- .../integration/activityclient/client.go | 45 +- .../modules/firstrechargereward/handler.go | 348 +++ .../modules/firstrechargereward/routes.go | 16 + server/admin/internal/router/router.go | 61 +- .../020_first_recharge_reward_navigation.sql | 59 + .../configs/config.docker.yaml | 5 + .../configs/config.tencent.example.yaml | 5 + services/activity-service/configs/config.yaml | 5 + .../mysql/initdb/001_activity_service.sql | 54 + services/activity-service/internal/app/app.go | 66 +- .../internal/config/config.go | 30 + .../domain/firstrecharge/first_recharge.go | 115 + .../internal/service/firstrecharge/service.go | 366 +++ .../service/firstrecharge/service_test.go | 105 + .../mysql/first_recharge_repository.go | 557 +++++ .../first_recharge_wallet_outbox_reader.go | 88 + .../transport/grpc/first_recharge_server.go | 189 ++ .../game-service/internal/domain/game/game.go | 1 + .../service/game/app_token_session.go | 54 + .../internal/service/game/leadercc_adapter.go | 45 +- .../internal/service/game/service.go | 42 +- .../internal/service/game/service_test.go | 154 ++ .../internal/service/game/zeeone_adapter.go | 408 ++++ .../internal/transport/grpc/server.go | 2 + services/gateway-service/internal/app/app.go | 2 + .../client/first_recharge_reward_client.go | 25 + .../first_recharge_reward_handler.go | 125 + .../transport/http/activityapi/handler.go | 52 +- .../internal/transport/http/handler.go | 6 + .../transport/http/httproutes/router.go | 2 + .../internal/transport/http/router.go | 17 +- .../mysql/initdb/001_wallet_service.sql | 23 + .../internal/domain/ledger/ledger.go | 1 + .../internal/storage/mysql/repository.go | 54 +- 38 files changed, 5125 insertions(+), 593 deletions(-) create mode 100644 server/admin/internal/modules/firstrechargereward/handler.go create mode 100644 server/admin/internal/modules/firstrechargereward/routes.go create mode 100644 server/admin/migrations/020_first_recharge_reward_navigation.sql create mode 100644 services/activity-service/internal/domain/firstrecharge/first_recharge.go create mode 100644 services/activity-service/internal/service/firstrecharge/service.go create mode 100644 services/activity-service/internal/service/firstrecharge/service_test.go create mode 100644 services/activity-service/internal/storage/mysql/first_recharge_repository.go create mode 100644 services/activity-service/internal/storage/mysql/first_recharge_wallet_outbox_reader.go create mode 100644 services/activity-service/internal/transport/grpc/first_recharge_server.go create mode 100644 services/game-service/internal/service/game/app_token_session.go create mode 100644 services/game-service/internal/service/game/zeeone_adapter.go create mode 100644 services/gateway-service/internal/client/first_recharge_reward_client.go create mode 100644 services/gateway-service/internal/transport/http/activityapi/first_recharge_reward_handler.go diff --git a/api/proto/activity/v1/activity.pb.go b/api/proto/activity/v1/activity.pb.go index 4d7ec8b1..107b59f4 100644 --- a/api/proto/activity/v1/activity.pb.go +++ b/api/proto/activity/v1/activity.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.36.11 -// protoc (unknown) +// protoc v4.25.3 // source: proto/activity/v1/activity.proto package activityv1 @@ -4651,6 +4651,1067 @@ func (x *ListRegistrationRewardClaimsResponse) GetTotal() int64 { return 0 } +// FirstRechargeRewardTier 是首冲奖励的一个金币充值档位;max_coin_amount=0 表示无上限。 +type FirstRechargeRewardTier struct { + state protoimpl.MessageState `protogen:"open.v1"` + TierId int64 `protobuf:"varint,1,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,2,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + TierName string `protobuf:"bytes,3,opt,name=tier_name,json=tierName,proto3" json:"tier_name,omitempty"` + MinCoinAmount int64 `protobuf:"varint,4,opt,name=min_coin_amount,json=minCoinAmount,proto3" json:"min_coin_amount,omitempty"` + MaxCoinAmount int64 `protobuf:"varint,5,opt,name=max_coin_amount,json=maxCoinAmount,proto3" json:"max_coin_amount,omitempty"` + ResourceGroupId int64 `protobuf:"varint,6,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,8,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,9,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,10,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FirstRechargeRewardTier) Reset() { + *x = FirstRechargeRewardTier{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FirstRechargeRewardTier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FirstRechargeRewardTier) ProtoMessage() {} + +func (x *FirstRechargeRewardTier) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[62] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FirstRechargeRewardTier.ProtoReflect.Descriptor instead. +func (*FirstRechargeRewardTier) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{62} +} + +func (x *FirstRechargeRewardTier) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *FirstRechargeRewardTier) GetTierName() string { + if x != nil { + return x.TierName + } + return "" +} + +func (x *FirstRechargeRewardTier) GetMinCoinAmount() int64 { + if x != nil { + return x.MinCoinAmount + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetMaxCoinAmount() int64 { + if x != nil { + return x.MaxCoinAmount + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *FirstRechargeRewardTier) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *FirstRechargeRewardTier) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// FirstRechargeRewardConfig 是当前 App 的首冲奖励配置;档位内容在 activity-service 内保持版本一致。 +type FirstRechargeRewardConfig struct { + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + Tiers []*FirstRechargeRewardTier `protobuf:"bytes,3,rep,name=tiers,proto3" json:"tiers,omitempty"` + UpdatedByAdminId int64 `protobuf:"varint,4,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,5,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,6,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FirstRechargeRewardConfig) Reset() { + *x = FirstRechargeRewardConfig{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FirstRechargeRewardConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FirstRechargeRewardConfig) ProtoMessage() {} + +func (x *FirstRechargeRewardConfig) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[63] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FirstRechargeRewardConfig.ProtoReflect.Descriptor instead. +func (*FirstRechargeRewardConfig) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{63} +} + +func (x *FirstRechargeRewardConfig) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *FirstRechargeRewardConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *FirstRechargeRewardConfig) GetTiers() []*FirstRechargeRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *FirstRechargeRewardConfig) GetUpdatedByAdminId() int64 { + if x != nil { + return x.UpdatedByAdminId + } + return 0 +} + +func (x *FirstRechargeRewardConfig) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *FirstRechargeRewardConfig) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// FirstRechargeRewardClaim 是某个用户首笔充值触发后的发奖事实;user_id 唯一保证一生只处理一次。 +type FirstRechargeRewardClaim struct { + state protoimpl.MessageState `protogen:"open.v1"` + ClaimId string `protobuf:"bytes,1,opt,name=claim_id,json=claimId,proto3" json:"claim_id,omitempty"` + EventId string `protobuf:"bytes,2,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + TransactionId string `protobuf:"bytes,3,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + TierId int64 `protobuf:"varint,6,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,7,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + ResourceGroupId int64 `protobuf:"varint,8,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + RechargeCoinAmount int64 `protobuf:"varint,9,opt,name=recharge_coin_amount,json=rechargeCoinAmount,proto3" json:"recharge_coin_amount,omitempty"` + RechargeSequence int64 `protobuf:"varint,10,opt,name=recharge_sequence,json=rechargeSequence,proto3" json:"recharge_sequence,omitempty"` + RechargeType string `protobuf:"bytes,11,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` + Status string `protobuf:"bytes,12,opt,name=status,proto3" json:"status,omitempty"` + WalletCommandId string `protobuf:"bytes,13,opt,name=wallet_command_id,json=walletCommandId,proto3" json:"wallet_command_id,omitempty"` + WalletGrantId string `protobuf:"bytes,14,opt,name=wallet_grant_id,json=walletGrantId,proto3" json:"wallet_grant_id,omitempty"` + FailureReason string `protobuf:"bytes,15,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + RechargedAtMs int64 `protobuf:"varint,16,opt,name=recharged_at_ms,json=rechargedAtMs,proto3" json:"recharged_at_ms,omitempty"` + GrantedAtMs int64 `protobuf:"varint,17,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` + CreatedAtMs int64 `protobuf:"varint,18,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,19,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FirstRechargeRewardClaim) Reset() { + *x = FirstRechargeRewardClaim{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FirstRechargeRewardClaim) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FirstRechargeRewardClaim) ProtoMessage() {} + +func (x *FirstRechargeRewardClaim) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[64] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FirstRechargeRewardClaim.ProtoReflect.Descriptor instead. +func (*FirstRechargeRewardClaim) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{64} +} + +func (x *FirstRechargeRewardClaim) GetClaimId() string { + if x != nil { + return x.ClaimId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetRechargeCoinAmount() int64 { + if x != nil { + return x.RechargeCoinAmount + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetRechargeSequence() int64 { + if x != nil { + return x.RechargeSequence + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetRechargeType() string { + if x != nil { + return x.RechargeType + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetWalletCommandId() string { + if x != nil { + return x.WalletCommandId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetWalletGrantId() string { + if x != nil { + return x.WalletGrantId + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetFailureReason() string { + if x != nil { + return x.FailureReason + } + return "" +} + +func (x *FirstRechargeRewardClaim) GetRechargedAtMs() int64 { + if x != nil { + return x.RechargedAtMs + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetGrantedAtMs() int64 { + if x != nil { + return x.GrantedAtMs + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *FirstRechargeRewardClaim) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// FirstRechargeRewardStatus 是 App 首冲奖励面板可直接展示的当前状态。 +type FirstRechargeRewardStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Tiers []*FirstRechargeRewardTier `protobuf:"bytes,2,rep,name=tiers,proto3" json:"tiers,omitempty"` + Rewarded bool `protobuf:"varint,3,opt,name=rewarded,proto3" json:"rewarded,omitempty"` + Claim *FirstRechargeRewardClaim `protobuf:"bytes,4,opt,name=claim,proto3" json:"claim,omitempty"` + ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FirstRechargeRewardStatus) Reset() { + *x = FirstRechargeRewardStatus{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FirstRechargeRewardStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FirstRechargeRewardStatus) ProtoMessage() {} + +func (x *FirstRechargeRewardStatus) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[65] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FirstRechargeRewardStatus.ProtoReflect.Descriptor instead. +func (*FirstRechargeRewardStatus) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{65} +} + +func (x *FirstRechargeRewardStatus) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *FirstRechargeRewardStatus) GetTiers() []*FirstRechargeRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *FirstRechargeRewardStatus) GetRewarded() bool { + if x != nil { + return x.Rewarded + } + return false +} + +func (x *FirstRechargeRewardStatus) GetClaim() *FirstRechargeRewardClaim { + if x != nil { + return x.Claim + } + return nil +} + +func (x *FirstRechargeRewardStatus) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type GetFirstRechargeRewardStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFirstRechargeRewardStatusRequest) Reset() { + *x = GetFirstRechargeRewardStatusRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[66] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFirstRechargeRewardStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFirstRechargeRewardStatusRequest) ProtoMessage() {} + +func (x *GetFirstRechargeRewardStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[66] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFirstRechargeRewardStatusRequest.ProtoReflect.Descriptor instead. +func (*GetFirstRechargeRewardStatusRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{66} +} + +func (x *GetFirstRechargeRewardStatusRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetFirstRechargeRewardStatusRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type GetFirstRechargeRewardStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Status *FirstRechargeRewardStatus `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFirstRechargeRewardStatusResponse) Reset() { + *x = GetFirstRechargeRewardStatusResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[67] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFirstRechargeRewardStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFirstRechargeRewardStatusResponse) ProtoMessage() {} + +func (x *GetFirstRechargeRewardStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[67] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFirstRechargeRewardStatusResponse.ProtoReflect.Descriptor instead. +func (*GetFirstRechargeRewardStatusResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{67} +} + +func (x *GetFirstRechargeRewardStatusResponse) GetStatus() *FirstRechargeRewardStatus { + if x != nil { + return x.Status + } + return nil +} + +// ConsumeFirstRechargeRewardRequest 是 wallet 充值事实消费入口;只处理 recharge_sequence=1 的成功充值。 +type ConsumeFirstRechargeRewardRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + EventId string `protobuf:"bytes,2,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + TransactionId string `protobuf:"bytes,3,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CommandId string `protobuf:"bytes,4,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RechargeCoinAmount int64 `protobuf:"varint,6,opt,name=recharge_coin_amount,json=rechargeCoinAmount,proto3" json:"recharge_coin_amount,omitempty"` + RechargeSequence int64 `protobuf:"varint,7,opt,name=recharge_sequence,json=rechargeSequence,proto3" json:"recharge_sequence,omitempty"` + RechargeType string `protobuf:"bytes,8,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` + OccurredAtMs int64 `protobuf:"varint,9,opt,name=occurred_at_ms,json=occurredAtMs,proto3" json:"occurred_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConsumeFirstRechargeRewardRequest) Reset() { + *x = ConsumeFirstRechargeRewardRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsumeFirstRechargeRewardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsumeFirstRechargeRewardRequest) ProtoMessage() {} + +func (x *ConsumeFirstRechargeRewardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[68] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConsumeFirstRechargeRewardRequest.ProtoReflect.Descriptor instead. +func (*ConsumeFirstRechargeRewardRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{68} +} + +func (x *ConsumeFirstRechargeRewardRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ConsumeFirstRechargeRewardRequest) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *ConsumeFirstRechargeRewardRequest) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *ConsumeFirstRechargeRewardRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *ConsumeFirstRechargeRewardRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ConsumeFirstRechargeRewardRequest) GetRechargeCoinAmount() int64 { + if x != nil { + return x.RechargeCoinAmount + } + return 0 +} + +func (x *ConsumeFirstRechargeRewardRequest) GetRechargeSequence() int64 { + if x != nil { + return x.RechargeSequence + } + return 0 +} + +func (x *ConsumeFirstRechargeRewardRequest) GetRechargeType() string { + if x != nil { + return x.RechargeType + } + return "" +} + +func (x *ConsumeFirstRechargeRewardRequest) GetOccurredAtMs() int64 { + if x != nil { + return x.OccurredAtMs + } + return 0 +} + +type ConsumeFirstRechargeRewardResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Claim *FirstRechargeRewardClaim `protobuf:"bytes,1,opt,name=claim,proto3" json:"claim,omitempty"` + Consumed bool `protobuf:"varint,2,opt,name=consumed,proto3" json:"consumed,omitempty"` + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConsumeFirstRechargeRewardResponse) Reset() { + *x = ConsumeFirstRechargeRewardResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsumeFirstRechargeRewardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsumeFirstRechargeRewardResponse) ProtoMessage() {} + +func (x *ConsumeFirstRechargeRewardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[69] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConsumeFirstRechargeRewardResponse.ProtoReflect.Descriptor instead. +func (*ConsumeFirstRechargeRewardResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{69} +} + +func (x *ConsumeFirstRechargeRewardResponse) GetClaim() *FirstRechargeRewardClaim { + if x != nil { + return x.Claim + } + return nil +} + +func (x *ConsumeFirstRechargeRewardResponse) GetConsumed() bool { + if x != nil { + return x.Consumed + } + return false +} + +func (x *ConsumeFirstRechargeRewardResponse) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type GetFirstRechargeRewardConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFirstRechargeRewardConfigRequest) Reset() { + *x = GetFirstRechargeRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFirstRechargeRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFirstRechargeRewardConfigRequest) ProtoMessage() {} + +func (x *GetFirstRechargeRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[70] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFirstRechargeRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*GetFirstRechargeRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{70} +} + +func (x *GetFirstRechargeRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +type GetFirstRechargeRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *FirstRechargeRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFirstRechargeRewardConfigResponse) Reset() { + *x = GetFirstRechargeRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFirstRechargeRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFirstRechargeRewardConfigResponse) ProtoMessage() {} + +func (x *GetFirstRechargeRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[71] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFirstRechargeRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*GetFirstRechargeRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{71} +} + +func (x *GetFirstRechargeRewardConfigResponse) GetConfig() *FirstRechargeRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type UpdateFirstRechargeRewardConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` + Tiers []*FirstRechargeRewardTier `protobuf:"bytes,3,rep,name=tiers,proto3" json:"tiers,omitempty"` + OperatorAdminId int64 `protobuf:"varint,4,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateFirstRechargeRewardConfigRequest) Reset() { + *x = UpdateFirstRechargeRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateFirstRechargeRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFirstRechargeRewardConfigRequest) ProtoMessage() {} + +func (x *UpdateFirstRechargeRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[72] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFirstRechargeRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*UpdateFirstRechargeRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{72} +} + +func (x *UpdateFirstRechargeRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *UpdateFirstRechargeRewardConfigRequest) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *UpdateFirstRechargeRewardConfigRequest) GetTiers() []*FirstRechargeRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *UpdateFirstRechargeRewardConfigRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type UpdateFirstRechargeRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *FirstRechargeRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateFirstRechargeRewardConfigResponse) Reset() { + *x = UpdateFirstRechargeRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateFirstRechargeRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateFirstRechargeRewardConfigResponse) ProtoMessage() {} + +func (x *UpdateFirstRechargeRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[73] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateFirstRechargeRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*UpdateFirstRechargeRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{73} +} + +func (x *UpdateFirstRechargeRewardConfigResponse) GetConfig() *FirstRechargeRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type ListFirstRechargeRewardClaimsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Page int32 `protobuf:"varint,4,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,5,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListFirstRechargeRewardClaimsRequest) Reset() { + *x = ListFirstRechargeRewardClaimsRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListFirstRechargeRewardClaimsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFirstRechargeRewardClaimsRequest) ProtoMessage() {} + +func (x *ListFirstRechargeRewardClaimsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[74] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFirstRechargeRewardClaimsRequest.ProtoReflect.Descriptor instead. +func (*ListFirstRechargeRewardClaimsRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{74} +} + +func (x *ListFirstRechargeRewardClaimsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListFirstRechargeRewardClaimsRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListFirstRechargeRewardClaimsRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ListFirstRechargeRewardClaimsRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListFirstRechargeRewardClaimsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListFirstRechargeRewardClaimsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Claims []*FirstRechargeRewardClaim `protobuf:"bytes,1,rep,name=claims,proto3" json:"claims,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListFirstRechargeRewardClaimsResponse) Reset() { + *x = ListFirstRechargeRewardClaimsResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListFirstRechargeRewardClaimsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFirstRechargeRewardClaimsResponse) ProtoMessage() {} + +func (x *ListFirstRechargeRewardClaimsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[75] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFirstRechargeRewardClaimsResponse.ProtoReflect.Descriptor instead. +func (*ListFirstRechargeRewardClaimsResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{75} +} + +func (x *ListFirstRechargeRewardClaimsResponse) GetClaims() []*FirstRechargeRewardClaim { + if x != nil { + return x.Claims + } + return nil +} + +func (x *ListFirstRechargeRewardClaimsResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + // SevenDayCheckInReward 是七日签到配置中某一天的资源组奖励。 type SevenDayCheckInReward struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -4662,7 +5723,7 @@ type SevenDayCheckInReward struct { func (x *SevenDayCheckInReward) Reset() { *x = SevenDayCheckInReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[62] + mi := &file_proto_activity_v1_activity_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4674,7 +5735,7 @@ func (x *SevenDayCheckInReward) String() string { func (*SevenDayCheckInReward) ProtoMessage() {} func (x *SevenDayCheckInReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[62] + mi := &file_proto_activity_v1_activity_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4687,7 +5748,7 @@ func (x *SevenDayCheckInReward) ProtoReflect() protoreflect.Message { // Deprecated: Use SevenDayCheckInReward.ProtoReflect.Descriptor instead. func (*SevenDayCheckInReward) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{62} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{76} } func (x *SevenDayCheckInReward) GetDayIndex() int32 { @@ -4720,7 +5781,7 @@ type SevenDayCheckInConfig struct { func (x *SevenDayCheckInConfig) Reset() { *x = SevenDayCheckInConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[63] + mi := &file_proto_activity_v1_activity_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4732,7 +5793,7 @@ func (x *SevenDayCheckInConfig) String() string { func (*SevenDayCheckInConfig) ProtoMessage() {} func (x *SevenDayCheckInConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[63] + mi := &file_proto_activity_v1_activity_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4745,7 +5806,7 @@ func (x *SevenDayCheckInConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use SevenDayCheckInConfig.ProtoReflect.Descriptor instead. func (*SevenDayCheckInConfig) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{63} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{77} } func (x *SevenDayCheckInConfig) GetAppCode() string { @@ -4812,7 +5873,7 @@ type SevenDayCheckInRewardStatus struct { func (x *SevenDayCheckInRewardStatus) Reset() { *x = SevenDayCheckInRewardStatus{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[64] + mi := &file_proto_activity_v1_activity_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4824,7 +5885,7 @@ func (x *SevenDayCheckInRewardStatus) String() string { func (*SevenDayCheckInRewardStatus) ProtoMessage() {} func (x *SevenDayCheckInRewardStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[64] + mi := &file_proto_activity_v1_activity_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4837,7 +5898,7 @@ func (x *SevenDayCheckInRewardStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use SevenDayCheckInRewardStatus.ProtoReflect.Descriptor instead. func (*SevenDayCheckInRewardStatus) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{64} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{78} } func (x *SevenDayCheckInRewardStatus) GetDayIndex() int32 { @@ -4892,7 +5953,7 @@ type GetSevenDayCheckInStatusRequest struct { func (x *GetSevenDayCheckInStatusRequest) Reset() { *x = GetSevenDayCheckInStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[65] + mi := &file_proto_activity_v1_activity_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4904,7 +5965,7 @@ func (x *GetSevenDayCheckInStatusRequest) String() string { func (*GetSevenDayCheckInStatusRequest) ProtoMessage() {} func (x *GetSevenDayCheckInStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[65] + mi := &file_proto_activity_v1_activity_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4917,7 +5978,7 @@ func (x *GetSevenDayCheckInStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSevenDayCheckInStatusRequest.ProtoReflect.Descriptor instead. func (*GetSevenDayCheckInStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{65} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{79} } func (x *GetSevenDayCheckInStatusRequest) GetMeta() *RequestMeta { @@ -4954,7 +6015,7 @@ type GetSevenDayCheckInStatusResponse struct { func (x *GetSevenDayCheckInStatusResponse) Reset() { *x = GetSevenDayCheckInStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[66] + mi := &file_proto_activity_v1_activity_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4966,7 +6027,7 @@ func (x *GetSevenDayCheckInStatusResponse) String() string { func (*GetSevenDayCheckInStatusResponse) ProtoMessage() {} func (x *GetSevenDayCheckInStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[66] + mi := &file_proto_activity_v1_activity_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4979,7 +6040,7 @@ func (x *GetSevenDayCheckInStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSevenDayCheckInStatusResponse.ProtoReflect.Descriptor instead. func (*GetSevenDayCheckInStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{66} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{80} } func (x *GetSevenDayCheckInStatusResponse) GetEnabled() bool { @@ -5077,7 +6138,7 @@ type SignSevenDayCheckInRequest struct { func (x *SignSevenDayCheckInRequest) Reset() { *x = SignSevenDayCheckInRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[67] + mi := &file_proto_activity_v1_activity_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5089,7 +6150,7 @@ func (x *SignSevenDayCheckInRequest) String() string { func (*SignSevenDayCheckInRequest) ProtoMessage() {} func (x *SignSevenDayCheckInRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[67] + mi := &file_proto_activity_v1_activity_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5102,7 +6163,7 @@ func (x *SignSevenDayCheckInRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SignSevenDayCheckInRequest.ProtoReflect.Descriptor instead. func (*SignSevenDayCheckInRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{67} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{81} } func (x *SignSevenDayCheckInRequest) GetMeta() *RequestMeta { @@ -5143,7 +6204,7 @@ type SignSevenDayCheckInResponse struct { func (x *SignSevenDayCheckInResponse) Reset() { *x = SignSevenDayCheckInResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[68] + mi := &file_proto_activity_v1_activity_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5155,7 +6216,7 @@ func (x *SignSevenDayCheckInResponse) String() string { func (*SignSevenDayCheckInResponse) ProtoMessage() {} func (x *SignSevenDayCheckInResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[68] + mi := &file_proto_activity_v1_activity_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5168,7 +6229,7 @@ func (x *SignSevenDayCheckInResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SignSevenDayCheckInResponse.ProtoReflect.Descriptor instead. func (*SignSevenDayCheckInResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{68} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{82} } func (x *SignSevenDayCheckInResponse) GetClaimId() string { @@ -5243,7 +6304,7 @@ type GetSevenDayCheckInConfigRequest struct { func (x *GetSevenDayCheckInConfigRequest) Reset() { *x = GetSevenDayCheckInConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[69] + mi := &file_proto_activity_v1_activity_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5255,7 +6316,7 @@ func (x *GetSevenDayCheckInConfigRequest) String() string { func (*GetSevenDayCheckInConfigRequest) ProtoMessage() {} func (x *GetSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[69] + mi := &file_proto_activity_v1_activity_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5268,7 +6329,7 @@ func (x *GetSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSevenDayCheckInConfigRequest.ProtoReflect.Descriptor instead. func (*GetSevenDayCheckInConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{69} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{83} } func (x *GetSevenDayCheckInConfigRequest) GetMeta() *RequestMeta { @@ -5287,7 +6348,7 @@ type GetSevenDayCheckInConfigResponse struct { func (x *GetSevenDayCheckInConfigResponse) Reset() { *x = GetSevenDayCheckInConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[70] + mi := &file_proto_activity_v1_activity_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5299,7 +6360,7 @@ func (x *GetSevenDayCheckInConfigResponse) String() string { func (*GetSevenDayCheckInConfigResponse) ProtoMessage() {} func (x *GetSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[70] + mi := &file_proto_activity_v1_activity_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5312,7 +6373,7 @@ func (x *GetSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSevenDayCheckInConfigResponse.ProtoReflect.Descriptor instead. func (*GetSevenDayCheckInConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{70} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{84} } func (x *GetSevenDayCheckInConfigResponse) GetConfig() *SevenDayCheckInConfig { @@ -5334,7 +6395,7 @@ type UpdateSevenDayCheckInConfigRequest struct { func (x *UpdateSevenDayCheckInConfigRequest) Reset() { *x = UpdateSevenDayCheckInConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[71] + mi := &file_proto_activity_v1_activity_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5346,7 +6407,7 @@ func (x *UpdateSevenDayCheckInConfigRequest) String() string { func (*UpdateSevenDayCheckInConfigRequest) ProtoMessage() {} func (x *UpdateSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[71] + mi := &file_proto_activity_v1_activity_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5359,7 +6420,7 @@ func (x *UpdateSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message // Deprecated: Use UpdateSevenDayCheckInConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateSevenDayCheckInConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{71} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{85} } func (x *UpdateSevenDayCheckInConfigRequest) GetMeta() *RequestMeta { @@ -5399,7 +6460,7 @@ type UpdateSevenDayCheckInConfigResponse struct { func (x *UpdateSevenDayCheckInConfigResponse) Reset() { *x = UpdateSevenDayCheckInConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[72] + mi := &file_proto_activity_v1_activity_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5411,7 +6472,7 @@ func (x *UpdateSevenDayCheckInConfigResponse) String() string { func (*UpdateSevenDayCheckInConfigResponse) ProtoMessage() {} func (x *UpdateSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[72] + mi := &file_proto_activity_v1_activity_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5424,7 +6485,7 @@ func (x *UpdateSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use UpdateSevenDayCheckInConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateSevenDayCheckInConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{72} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{86} } func (x *UpdateSevenDayCheckInConfigResponse) GetConfig() *SevenDayCheckInConfig { @@ -5459,7 +6520,7 @@ type SevenDayCheckInClaim struct { func (x *SevenDayCheckInClaim) Reset() { *x = SevenDayCheckInClaim{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[73] + mi := &file_proto_activity_v1_activity_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5471,7 +6532,7 @@ func (x *SevenDayCheckInClaim) String() string { func (*SevenDayCheckInClaim) ProtoMessage() {} func (x *SevenDayCheckInClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[73] + mi := &file_proto_activity_v1_activity_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5484,7 +6545,7 @@ func (x *SevenDayCheckInClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use SevenDayCheckInClaim.ProtoReflect.Descriptor instead. func (*SevenDayCheckInClaim) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{73} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{87} } func (x *SevenDayCheckInClaim) GetClaimId() string { @@ -5614,7 +6675,7 @@ type ListSevenDayCheckInClaimsRequest struct { func (x *ListSevenDayCheckInClaimsRequest) Reset() { *x = ListSevenDayCheckInClaimsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[74] + mi := &file_proto_activity_v1_activity_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5626,7 +6687,7 @@ func (x *ListSevenDayCheckInClaimsRequest) String() string { func (*ListSevenDayCheckInClaimsRequest) ProtoMessage() {} func (x *ListSevenDayCheckInClaimsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[74] + mi := &file_proto_activity_v1_activity_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5639,7 +6700,7 @@ func (x *ListSevenDayCheckInClaimsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListSevenDayCheckInClaimsRequest.ProtoReflect.Descriptor instead. func (*ListSevenDayCheckInClaimsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{74} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{88} } func (x *ListSevenDayCheckInClaimsRequest) GetMeta() *RequestMeta { @@ -5701,7 +6762,7 @@ type ListSevenDayCheckInClaimsResponse struct { func (x *ListSevenDayCheckInClaimsResponse) Reset() { *x = ListSevenDayCheckInClaimsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[75] + mi := &file_proto_activity_v1_activity_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5713,7 +6774,7 @@ func (x *ListSevenDayCheckInClaimsResponse) String() string { func (*ListSevenDayCheckInClaimsResponse) ProtoMessage() {} func (x *ListSevenDayCheckInClaimsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[75] + mi := &file_proto_activity_v1_activity_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5726,7 +6787,7 @@ func (x *ListSevenDayCheckInClaimsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListSevenDayCheckInClaimsResponse.ProtoReflect.Descriptor instead. func (*ListSevenDayCheckInClaimsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{75} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{89} } func (x *ListSevenDayCheckInClaimsResponse) GetClaims() []*SevenDayCheckInClaim { @@ -5759,7 +6820,7 @@ type LevelTrack struct { func (x *LevelTrack) Reset() { *x = LevelTrack{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + mi := &file_proto_activity_v1_activity_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5771,7 +6832,7 @@ func (x *LevelTrack) String() string { func (*LevelTrack) ProtoMessage() {} func (x *LevelTrack) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + mi := &file_proto_activity_v1_activity_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5784,7 +6845,7 @@ func (x *LevelTrack) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelTrack.ProtoReflect.Descriptor instead. func (*LevelTrack) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{76} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{90} } func (x *LevelTrack) GetTrack() string { @@ -5857,7 +6918,7 @@ type LevelRule struct { func (x *LevelRule) Reset() { *x = LevelRule{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + mi := &file_proto_activity_v1_activity_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5869,7 +6930,7 @@ func (x *LevelRule) String() string { func (*LevelRule) ProtoMessage() {} func (x *LevelRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + mi := &file_proto_activity_v1_activity_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5882,7 +6943,7 @@ func (x *LevelRule) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelRule.ProtoReflect.Descriptor instead. func (*LevelRule) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{77} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{91} } func (x *LevelRule) GetTrack() string { @@ -5992,7 +7053,7 @@ type LevelTier struct { func (x *LevelTier) Reset() { *x = LevelTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + mi := &file_proto_activity_v1_activity_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6004,7 +7065,7 @@ func (x *LevelTier) String() string { func (*LevelTier) ProtoMessage() {} func (x *LevelTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + mi := &file_proto_activity_v1_activity_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6017,7 +7078,7 @@ func (x *LevelTier) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelTier.ProtoReflect.Descriptor instead. func (*LevelTier) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{78} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{92} } func (x *LevelTier) GetTierId() int64 { @@ -6139,7 +7200,7 @@ type LevelTrackOverview struct { func (x *LevelTrackOverview) Reset() { *x = LevelTrackOverview{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + mi := &file_proto_activity_v1_activity_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6151,7 +7212,7 @@ func (x *LevelTrackOverview) String() string { func (*LevelTrackOverview) ProtoMessage() {} func (x *LevelTrackOverview) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + mi := &file_proto_activity_v1_activity_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6164,7 +7225,7 @@ func (x *LevelTrackOverview) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelTrackOverview.ProtoReflect.Descriptor instead. func (*LevelTrackOverview) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{79} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{93} } func (x *LevelTrackOverview) GetTrack() string { @@ -6261,7 +7322,7 @@ type GetMyLevelOverviewRequest struct { func (x *GetMyLevelOverviewRequest) Reset() { *x = GetMyLevelOverviewRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + mi := &file_proto_activity_v1_activity_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6273,7 +7334,7 @@ func (x *GetMyLevelOverviewRequest) String() string { func (*GetMyLevelOverviewRequest) ProtoMessage() {} func (x *GetMyLevelOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + mi := &file_proto_activity_v1_activity_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6286,7 +7347,7 @@ func (x *GetMyLevelOverviewRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyLevelOverviewRequest.ProtoReflect.Descriptor instead. func (*GetMyLevelOverviewRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{80} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{94} } func (x *GetMyLevelOverviewRequest) GetMeta() *RequestMeta { @@ -6313,7 +7374,7 @@ type GetMyLevelOverviewResponse struct { func (x *GetMyLevelOverviewResponse) Reset() { *x = GetMyLevelOverviewResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + mi := &file_proto_activity_v1_activity_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6325,7 +7386,7 @@ func (x *GetMyLevelOverviewResponse) String() string { func (*GetMyLevelOverviewResponse) ProtoMessage() {} func (x *GetMyLevelOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + mi := &file_proto_activity_v1_activity_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6338,7 +7399,7 @@ func (x *GetMyLevelOverviewResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyLevelOverviewResponse.ProtoReflect.Descriptor instead. func (*GetMyLevelOverviewResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{81} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{95} } func (x *GetMyLevelOverviewResponse) GetTracks() []*LevelTrackOverview { @@ -6366,7 +7427,7 @@ type GetLevelTrackRequest struct { func (x *GetLevelTrackRequest) Reset() { *x = GetLevelTrackRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + mi := &file_proto_activity_v1_activity_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6378,7 +7439,7 @@ func (x *GetLevelTrackRequest) String() string { func (*GetLevelTrackRequest) ProtoMessage() {} func (x *GetLevelTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + mi := &file_proto_activity_v1_activity_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6391,7 +7452,7 @@ func (x *GetLevelTrackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLevelTrackRequest.ProtoReflect.Descriptor instead. func (*GetLevelTrackRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{82} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{96} } func (x *GetLevelTrackRequest) GetMeta() *RequestMeta { @@ -6427,7 +7488,7 @@ type GetLevelTrackResponse struct { func (x *GetLevelTrackResponse) Reset() { *x = GetLevelTrackResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + mi := &file_proto_activity_v1_activity_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6439,7 +7500,7 @@ func (x *GetLevelTrackResponse) String() string { func (*GetLevelTrackResponse) ProtoMessage() {} func (x *GetLevelTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + mi := &file_proto_activity_v1_activity_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6452,7 +7513,7 @@ func (x *GetLevelTrackResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLevelTrackResponse.ProtoReflect.Descriptor instead. func (*GetLevelTrackResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{83} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{97} } func (x *GetLevelTrackResponse) GetOverview() *LevelTrackOverview { @@ -6505,7 +7566,7 @@ type LevelRewardJob struct { func (x *LevelRewardJob) Reset() { *x = LevelRewardJob{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + mi := &file_proto_activity_v1_activity_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6517,7 +7578,7 @@ func (x *LevelRewardJob) String() string { func (*LevelRewardJob) ProtoMessage() {} func (x *LevelRewardJob) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + mi := &file_proto_activity_v1_activity_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6530,7 +7591,7 @@ func (x *LevelRewardJob) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelRewardJob.ProtoReflect.Descriptor instead. func (*LevelRewardJob) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{84} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{98} } func (x *LevelRewardJob) GetRewardJobId() string { @@ -6638,7 +7699,7 @@ type ListLevelRewardsRequest struct { func (x *ListLevelRewardsRequest) Reset() { *x = ListLevelRewardsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + mi := &file_proto_activity_v1_activity_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6650,7 +7711,7 @@ func (x *ListLevelRewardsRequest) String() string { func (*ListLevelRewardsRequest) ProtoMessage() {} func (x *ListLevelRewardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + mi := &file_proto_activity_v1_activity_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6663,7 +7724,7 @@ func (x *ListLevelRewardsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelRewardsRequest.ProtoReflect.Descriptor instead. func (*ListLevelRewardsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{85} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{99} } func (x *ListLevelRewardsRequest) GetMeta() *RequestMeta { @@ -6718,7 +7779,7 @@ type ListLevelRewardsResponse struct { func (x *ListLevelRewardsResponse) Reset() { *x = ListLevelRewardsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + mi := &file_proto_activity_v1_activity_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6730,7 +7791,7 @@ func (x *ListLevelRewardsResponse) String() string { func (*ListLevelRewardsResponse) ProtoMessage() {} func (x *ListLevelRewardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + mi := &file_proto_activity_v1_activity_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6743,7 +7804,7 @@ func (x *ListLevelRewardsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelRewardsResponse.ProtoReflect.Descriptor instead. func (*ListLevelRewardsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{86} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{100} } func (x *ListLevelRewardsResponse) GetRewards() []*LevelRewardJob { @@ -6780,7 +7841,7 @@ type ConsumeLevelEventRequest struct { func (x *ConsumeLevelEventRequest) Reset() { *x = ConsumeLevelEventRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + mi := &file_proto_activity_v1_activity_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6792,7 +7853,7 @@ func (x *ConsumeLevelEventRequest) String() string { func (*ConsumeLevelEventRequest) ProtoMessage() {} func (x *ConsumeLevelEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + mi := &file_proto_activity_v1_activity_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6805,7 +7866,7 @@ func (x *ConsumeLevelEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeLevelEventRequest.ProtoReflect.Descriptor instead. func (*ConsumeLevelEventRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{87} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{101} } func (x *ConsumeLevelEventRequest) GetMeta() *RequestMeta { @@ -6899,7 +7960,7 @@ type ConsumeLevelEventResponse struct { func (x *ConsumeLevelEventResponse) Reset() { *x = ConsumeLevelEventResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + mi := &file_proto_activity_v1_activity_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6911,7 +7972,7 @@ func (x *ConsumeLevelEventResponse) String() string { func (*ConsumeLevelEventResponse) ProtoMessage() {} func (x *ConsumeLevelEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + mi := &file_proto_activity_v1_activity_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6924,7 +7985,7 @@ func (x *ConsumeLevelEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeLevelEventResponse.ProtoReflect.Descriptor instead. func (*ConsumeLevelEventResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{88} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{102} } func (x *ConsumeLevelEventResponse) GetEventId() string { @@ -6983,7 +8044,7 @@ type UpsertLevelTrackRequest struct { func (x *UpsertLevelTrackRequest) Reset() { *x = UpsertLevelTrackRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + mi := &file_proto_activity_v1_activity_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6995,7 +8056,7 @@ func (x *UpsertLevelTrackRequest) String() string { func (*UpsertLevelTrackRequest) ProtoMessage() {} func (x *UpsertLevelTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + mi := &file_proto_activity_v1_activity_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7008,7 +8069,7 @@ func (x *UpsertLevelTrackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTrackRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelTrackRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{89} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{103} } func (x *UpsertLevelTrackRequest) GetMeta() *RequestMeta { @@ -7063,7 +8124,7 @@ type UpsertLevelTrackResponse struct { func (x *UpsertLevelTrackResponse) Reset() { *x = UpsertLevelTrackResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + mi := &file_proto_activity_v1_activity_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7075,7 +8136,7 @@ func (x *UpsertLevelTrackResponse) String() string { func (*UpsertLevelTrackResponse) ProtoMessage() {} func (x *UpsertLevelTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + mi := &file_proto_activity_v1_activity_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7088,7 +8149,7 @@ func (x *UpsertLevelTrackResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTrackResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelTrackResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{90} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{104} } func (x *UpsertLevelTrackResponse) GetTrack() *LevelTrack { @@ -7123,7 +8184,7 @@ type UpsertLevelRuleRequest struct { func (x *UpsertLevelRuleRequest) Reset() { *x = UpsertLevelRuleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + mi := &file_proto_activity_v1_activity_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7135,7 +8196,7 @@ func (x *UpsertLevelRuleRequest) String() string { func (*UpsertLevelRuleRequest) ProtoMessage() {} func (x *UpsertLevelRuleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + mi := &file_proto_activity_v1_activity_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7148,7 +8209,7 @@ func (x *UpsertLevelRuleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelRuleRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelRuleRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{91} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{105} } func (x *UpsertLevelRuleRequest) GetMeta() *RequestMeta { @@ -7231,7 +8292,7 @@ type UpsertLevelRuleResponse struct { func (x *UpsertLevelRuleResponse) Reset() { *x = UpsertLevelRuleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + mi := &file_proto_activity_v1_activity_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7243,7 +8304,7 @@ func (x *UpsertLevelRuleResponse) String() string { func (*UpsertLevelRuleResponse) ProtoMessage() {} func (x *UpsertLevelRuleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + mi := &file_proto_activity_v1_activity_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7256,7 +8317,7 @@ func (x *UpsertLevelRuleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelRuleResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelRuleResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{92} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{106} } func (x *UpsertLevelRuleResponse) GetRule() *LevelRule { @@ -7293,7 +8354,7 @@ type UpsertLevelTierRequest struct { func (x *UpsertLevelTierRequest) Reset() { *x = UpsertLevelTierRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + mi := &file_proto_activity_v1_activity_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7305,7 +8366,7 @@ func (x *UpsertLevelTierRequest) String() string { func (*UpsertLevelTierRequest) ProtoMessage() {} func (x *UpsertLevelTierRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + mi := &file_proto_activity_v1_activity_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7318,7 +8379,7 @@ func (x *UpsertLevelTierRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTierRequest.ProtoReflect.Descriptor instead. func (*UpsertLevelTierRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{93} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{107} } func (x *UpsertLevelTierRequest) GetMeta() *RequestMeta { @@ -7415,7 +8476,7 @@ type UpsertLevelTierResponse struct { func (x *UpsertLevelTierResponse) Reset() { *x = UpsertLevelTierResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + mi := &file_proto_activity_v1_activity_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7427,7 +8488,7 @@ func (x *UpsertLevelTierResponse) String() string { func (*UpsertLevelTierResponse) ProtoMessage() {} func (x *UpsertLevelTierResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + mi := &file_proto_activity_v1_activity_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7440,7 +8501,7 @@ func (x *UpsertLevelTierResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLevelTierResponse.ProtoReflect.Descriptor instead. func (*UpsertLevelTierResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{94} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{108} } func (x *UpsertLevelTierResponse) GetTier() *LevelTier { @@ -7469,7 +8530,7 @@ type ListLevelConfigRequest struct { func (x *ListLevelConfigRequest) Reset() { *x = ListLevelConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + mi := &file_proto_activity_v1_activity_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7481,7 +8542,7 @@ func (x *ListLevelConfigRequest) String() string { func (*ListLevelConfigRequest) ProtoMessage() {} func (x *ListLevelConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + mi := &file_proto_activity_v1_activity_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7494,7 +8555,7 @@ func (x *ListLevelConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelConfigRequest.ProtoReflect.Descriptor instead. func (*ListLevelConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{95} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{109} } func (x *ListLevelConfigRequest) GetMeta() *RequestMeta { @@ -7530,7 +8591,7 @@ type ListLevelConfigResponse struct { func (x *ListLevelConfigResponse) Reset() { *x = ListLevelConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + mi := &file_proto_activity_v1_activity_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7542,7 +8603,7 @@ func (x *ListLevelConfigResponse) String() string { func (*ListLevelConfigResponse) ProtoMessage() {} func (x *ListLevelConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + mi := &file_proto_activity_v1_activity_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7555,7 +8616,7 @@ func (x *ListLevelConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLevelConfigResponse.ProtoReflect.Descriptor instead. func (*ListLevelConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{96} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{110} } func (x *ListLevelConfigResponse) GetTracks() []*LevelTrack { @@ -7601,7 +8662,7 @@ type AchievementCondition struct { func (x *AchievementCondition) Reset() { *x = AchievementCondition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + mi := &file_proto_activity_v1_activity_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7613,7 +8674,7 @@ func (x *AchievementCondition) String() string { func (*AchievementCondition) ProtoMessage() {} func (x *AchievementCondition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + mi := &file_proto_activity_v1_activity_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7626,7 +8687,7 @@ func (x *AchievementCondition) ProtoReflect() protoreflect.Message { // Deprecated: Use AchievementCondition.ProtoReflect.Descriptor instead. func (*AchievementCondition) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{97} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{111} } func (x *AchievementCondition) GetConditionId() string { @@ -7707,7 +8768,7 @@ type AchievementDefinition struct { func (x *AchievementDefinition) Reset() { *x = AchievementDefinition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + mi := &file_proto_activity_v1_activity_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7719,7 +8780,7 @@ func (x *AchievementDefinition) String() string { func (*AchievementDefinition) ProtoMessage() {} func (x *AchievementDefinition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + mi := &file_proto_activity_v1_activity_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7732,7 +8793,7 @@ func (x *AchievementDefinition) ProtoReflect() protoreflect.Message { // Deprecated: Use AchievementDefinition.ProtoReflect.Descriptor instead. func (*AchievementDefinition) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{98} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{112} } func (x *AchievementDefinition) GetAchievementId() string { @@ -7897,7 +8958,7 @@ type UserAchievement struct { func (x *UserAchievement) Reset() { *x = UserAchievement{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + mi := &file_proto_activity_v1_activity_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7909,7 +8970,7 @@ func (x *UserAchievement) String() string { func (*UserAchievement) ProtoMessage() {} func (x *UserAchievement) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + mi := &file_proto_activity_v1_activity_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7922,7 +8983,7 @@ func (x *UserAchievement) ProtoReflect() protoreflect.Message { // Deprecated: Use UserAchievement.ProtoReflect.Descriptor instead. func (*UserAchievement) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{99} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{113} } func (x *UserAchievement) GetDefinition() *AchievementDefinition { @@ -7988,7 +9049,7 @@ type ListAchievementsRequest struct { func (x *ListAchievementsRequest) Reset() { *x = ListAchievementsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + mi := &file_proto_activity_v1_activity_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8000,7 +9061,7 @@ func (x *ListAchievementsRequest) String() string { func (*ListAchievementsRequest) ProtoMessage() {} func (x *ListAchievementsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + mi := &file_proto_activity_v1_activity_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8013,7 +9074,7 @@ func (x *ListAchievementsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAchievementsRequest.ProtoReflect.Descriptor instead. func (*ListAchievementsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{100} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{114} } func (x *ListAchievementsRequest) GetMeta() *RequestMeta { @@ -8069,7 +9130,7 @@ type ListAchievementsResponse struct { func (x *ListAchievementsResponse) Reset() { *x = ListAchievementsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + mi := &file_proto_activity_v1_activity_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8081,7 +9142,7 @@ func (x *ListAchievementsResponse) String() string { func (*ListAchievementsResponse) ProtoMessage() {} func (x *ListAchievementsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + mi := &file_proto_activity_v1_activity_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8094,7 +9155,7 @@ func (x *ListAchievementsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAchievementsResponse.ProtoReflect.Descriptor instead. func (*ListAchievementsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{101} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{115} } func (x *ListAchievementsResponse) GetAchievements() []*UserAchievement { @@ -8135,7 +9196,7 @@ type ConsumeAchievementEventRequest struct { func (x *ConsumeAchievementEventRequest) Reset() { *x = ConsumeAchievementEventRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + mi := &file_proto_activity_v1_activity_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8147,7 +9208,7 @@ func (x *ConsumeAchievementEventRequest) String() string { func (*ConsumeAchievementEventRequest) ProtoMessage() {} func (x *ConsumeAchievementEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + mi := &file_proto_activity_v1_activity_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8160,7 +9221,7 @@ func (x *ConsumeAchievementEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeAchievementEventRequest.ProtoReflect.Descriptor instead. func (*ConsumeAchievementEventRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{102} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{116} } func (x *ConsumeAchievementEventRequest) GetMeta() *RequestMeta { @@ -8239,7 +9300,7 @@ type ConsumeAchievementEventResponse struct { func (x *ConsumeAchievementEventResponse) Reset() { *x = ConsumeAchievementEventResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + mi := &file_proto_activity_v1_activity_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8251,7 +9312,7 @@ func (x *ConsumeAchievementEventResponse) String() string { func (*ConsumeAchievementEventResponse) ProtoMessage() {} func (x *ConsumeAchievementEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + mi := &file_proto_activity_v1_activity_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8264,7 +9325,7 @@ func (x *ConsumeAchievementEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConsumeAchievementEventResponse.ProtoReflect.Descriptor instead. func (*ConsumeAchievementEventResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{103} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{117} } func (x *ConsumeAchievementEventResponse) GetEventId() string { @@ -8319,7 +9380,7 @@ type BadgeDisplayItem struct { func (x *BadgeDisplayItem) Reset() { *x = BadgeDisplayItem{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + mi := &file_proto_activity_v1_activity_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8331,7 +9392,7 @@ func (x *BadgeDisplayItem) String() string { func (*BadgeDisplayItem) ProtoMessage() {} func (x *BadgeDisplayItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + mi := &file_proto_activity_v1_activity_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8344,7 +9405,7 @@ func (x *BadgeDisplayItem) ProtoReflect() protoreflect.Message { // Deprecated: Use BadgeDisplayItem.ProtoReflect.Descriptor instead. func (*BadgeDisplayItem) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{104} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{118} } func (x *BadgeDisplayItem) GetSlot() string { @@ -8420,7 +9481,7 @@ type ListMyBadgesRequest struct { func (x *ListMyBadgesRequest) Reset() { *x = ListMyBadgesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[105] + mi := &file_proto_activity_v1_activity_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8432,7 +9493,7 @@ func (x *ListMyBadgesRequest) String() string { func (*ListMyBadgesRequest) ProtoMessage() {} func (x *ListMyBadgesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[105] + mi := &file_proto_activity_v1_activity_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8445,7 +9506,7 @@ func (x *ListMyBadgesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMyBadgesRequest.ProtoReflect.Descriptor instead. func (*ListMyBadgesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{105} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{119} } func (x *ListMyBadgesRequest) GetMeta() *RequestMeta { @@ -8474,7 +9535,7 @@ type ListMyBadgesResponse struct { func (x *ListMyBadgesResponse) Reset() { *x = ListMyBadgesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[106] + mi := &file_proto_activity_v1_activity_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8486,7 +9547,7 @@ func (x *ListMyBadgesResponse) String() string { func (*ListMyBadgesResponse) ProtoMessage() {} func (x *ListMyBadgesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[106] + mi := &file_proto_activity_v1_activity_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8499,7 +9560,7 @@ func (x *ListMyBadgesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMyBadgesResponse.ProtoReflect.Descriptor instead. func (*ListMyBadgesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{106} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{120} } func (x *ListMyBadgesResponse) GetStripBadges() []*BadgeDisplayItem { @@ -8543,7 +9604,7 @@ type SetBadgeDisplayRequest struct { func (x *SetBadgeDisplayRequest) Reset() { *x = SetBadgeDisplayRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[107] + mi := &file_proto_activity_v1_activity_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8555,7 +9616,7 @@ func (x *SetBadgeDisplayRequest) String() string { func (*SetBadgeDisplayRequest) ProtoMessage() {} func (x *SetBadgeDisplayRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[107] + mi := &file_proto_activity_v1_activity_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8568,7 +9629,7 @@ func (x *SetBadgeDisplayRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBadgeDisplayRequest.ProtoReflect.Descriptor instead. func (*SetBadgeDisplayRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{107} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{121} } func (x *SetBadgeDisplayRequest) GetMeta() *RequestMeta { @@ -8615,7 +9676,7 @@ type SetBadgeDisplayResponse struct { func (x *SetBadgeDisplayResponse) Reset() { *x = SetBadgeDisplayResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[108] + mi := &file_proto_activity_v1_activity_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8627,7 +9688,7 @@ func (x *SetBadgeDisplayResponse) String() string { func (*SetBadgeDisplayResponse) ProtoMessage() {} func (x *SetBadgeDisplayResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[108] + mi := &file_proto_activity_v1_activity_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8640,7 +9701,7 @@ func (x *SetBadgeDisplayResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBadgeDisplayResponse.ProtoReflect.Descriptor instead. func (*SetBadgeDisplayResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{108} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{122} } func (x *SetBadgeDisplayResponse) GetProfile() *ListMyBadgesResponse { @@ -8676,7 +9737,7 @@ type UpsertAchievementDefinitionRequest struct { func (x *UpsertAchievementDefinitionRequest) Reset() { *x = UpsertAchievementDefinitionRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[109] + mi := &file_proto_activity_v1_activity_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8688,7 +9749,7 @@ func (x *UpsertAchievementDefinitionRequest) String() string { func (*UpsertAchievementDefinitionRequest) ProtoMessage() {} func (x *UpsertAchievementDefinitionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[109] + mi := &file_proto_activity_v1_activity_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8701,7 +9762,7 @@ func (x *UpsertAchievementDefinitionRequest) ProtoReflect() protoreflect.Message // Deprecated: Use UpsertAchievementDefinitionRequest.ProtoReflect.Descriptor instead. func (*UpsertAchievementDefinitionRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{109} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{123} } func (x *UpsertAchievementDefinitionRequest) GetMeta() *RequestMeta { @@ -8840,7 +9901,7 @@ type UpsertAchievementDefinitionResponse struct { func (x *UpsertAchievementDefinitionResponse) Reset() { *x = UpsertAchievementDefinitionResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[110] + mi := &file_proto_activity_v1_activity_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8852,7 +9913,7 @@ func (x *UpsertAchievementDefinitionResponse) String() string { func (*UpsertAchievementDefinitionResponse) ProtoMessage() {} func (x *UpsertAchievementDefinitionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[110] + mi := &file_proto_activity_v1_activity_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8865,7 +9926,7 @@ func (x *UpsertAchievementDefinitionResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use UpsertAchievementDefinitionResponse.ProtoReflect.Descriptor instead. func (*UpsertAchievementDefinitionResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{110} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{124} } func (x *UpsertAchievementDefinitionResponse) GetAchievement() *AchievementDefinition { @@ -8900,7 +9961,7 @@ type LuckyGiftMeta struct { func (x *LuckyGiftMeta) Reset() { *x = LuckyGiftMeta{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[111] + mi := &file_proto_activity_v1_activity_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8912,7 +9973,7 @@ func (x *LuckyGiftMeta) String() string { func (*LuckyGiftMeta) ProtoMessage() {} func (x *LuckyGiftMeta) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[111] + mi := &file_proto_activity_v1_activity_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8925,7 +9986,7 @@ func (x *LuckyGiftMeta) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftMeta.ProtoReflect.Descriptor instead. func (*LuckyGiftMeta) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{111} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{125} } func (x *LuckyGiftMeta) GetMeta() *RequestMeta { @@ -9013,7 +10074,7 @@ type LuckyGiftTier struct { func (x *LuckyGiftTier) Reset() { *x = LuckyGiftTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[112] + mi := &file_proto_activity_v1_activity_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9025,7 +10086,7 @@ func (x *LuckyGiftTier) String() string { func (*LuckyGiftTier) ProtoMessage() {} func (x *LuckyGiftTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[112] + mi := &file_proto_activity_v1_activity_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9038,7 +10099,7 @@ func (x *LuckyGiftTier) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftTier.ProtoReflect.Descriptor instead. func (*LuckyGiftTier) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{112} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{126} } func (x *LuckyGiftTier) GetPool() string { @@ -9138,7 +10199,7 @@ type LuckyGiftConfig struct { func (x *LuckyGiftConfig) Reset() { *x = LuckyGiftConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[113] + mi := &file_proto_activity_v1_activity_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9150,7 +10211,7 @@ func (x *LuckyGiftConfig) String() string { func (*LuckyGiftConfig) ProtoMessage() {} func (x *LuckyGiftConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[113] + mi := &file_proto_activity_v1_activity_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9163,7 +10224,7 @@ func (x *LuckyGiftConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftConfig.ProtoReflect.Descriptor instead. func (*LuckyGiftConfig) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{113} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{127} } func (x *LuckyGiftConfig) GetAppCode() string { @@ -9459,7 +10520,7 @@ type CheckLuckyGiftRequest struct { func (x *CheckLuckyGiftRequest) Reset() { *x = CheckLuckyGiftRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[114] + mi := &file_proto_activity_v1_activity_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9471,7 +10532,7 @@ func (x *CheckLuckyGiftRequest) String() string { func (*CheckLuckyGiftRequest) ProtoMessage() {} func (x *CheckLuckyGiftRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[114] + mi := &file_proto_activity_v1_activity_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9484,7 +10545,7 @@ func (x *CheckLuckyGiftRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckLuckyGiftRequest.ProtoReflect.Descriptor instead. func (*CheckLuckyGiftRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{114} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{128} } func (x *CheckLuckyGiftRequest) GetMeta() *RequestMeta { @@ -9538,7 +10599,7 @@ type CheckLuckyGiftResponse struct { func (x *CheckLuckyGiftResponse) Reset() { *x = CheckLuckyGiftResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[115] + mi := &file_proto_activity_v1_activity_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9550,7 +10611,7 @@ func (x *CheckLuckyGiftResponse) String() string { func (*CheckLuckyGiftResponse) ProtoMessage() {} func (x *CheckLuckyGiftResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[115] + mi := &file_proto_activity_v1_activity_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9563,7 +10624,7 @@ func (x *CheckLuckyGiftResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckLuckyGiftResponse.ProtoReflect.Descriptor instead. func (*CheckLuckyGiftResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{115} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{129} } func (x *CheckLuckyGiftResponse) GetEnabled() bool { @@ -9650,7 +10711,7 @@ type LuckyGiftDrawResult struct { func (x *LuckyGiftDrawResult) Reset() { *x = LuckyGiftDrawResult{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[116] + mi := &file_proto_activity_v1_activity_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9662,7 +10723,7 @@ func (x *LuckyGiftDrawResult) String() string { func (*LuckyGiftDrawResult) ProtoMessage() {} func (x *LuckyGiftDrawResult) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[116] + mi := &file_proto_activity_v1_activity_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9675,7 +10736,7 @@ func (x *LuckyGiftDrawResult) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftDrawResult.ProtoReflect.Descriptor instead. func (*LuckyGiftDrawResult) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{116} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{130} } func (x *LuckyGiftDrawResult) GetDrawId() string { @@ -9827,7 +10888,7 @@ type ExecuteLuckyGiftDrawRequest struct { func (x *ExecuteLuckyGiftDrawRequest) Reset() { *x = ExecuteLuckyGiftDrawRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[117] + mi := &file_proto_activity_v1_activity_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9839,7 +10900,7 @@ func (x *ExecuteLuckyGiftDrawRequest) String() string { func (*ExecuteLuckyGiftDrawRequest) ProtoMessage() {} func (x *ExecuteLuckyGiftDrawRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[117] + mi := &file_proto_activity_v1_activity_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9852,7 +10913,7 @@ func (x *ExecuteLuckyGiftDrawRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteLuckyGiftDrawRequest.ProtoReflect.Descriptor instead. func (*ExecuteLuckyGiftDrawRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{117} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{131} } func (x *ExecuteLuckyGiftDrawRequest) GetLuckyGift() *LuckyGiftMeta { @@ -9871,7 +10932,7 @@ type ExecuteLuckyGiftDrawResponse struct { func (x *ExecuteLuckyGiftDrawResponse) Reset() { *x = ExecuteLuckyGiftDrawResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[118] + mi := &file_proto_activity_v1_activity_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9883,7 +10944,7 @@ func (x *ExecuteLuckyGiftDrawResponse) String() string { func (*ExecuteLuckyGiftDrawResponse) ProtoMessage() {} func (x *ExecuteLuckyGiftDrawResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[118] + mi := &file_proto_activity_v1_activity_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9896,7 +10957,7 @@ func (x *ExecuteLuckyGiftDrawResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteLuckyGiftDrawResponse.ProtoReflect.Descriptor instead. func (*ExecuteLuckyGiftDrawResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{118} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{132} } func (x *ExecuteLuckyGiftDrawResponse) GetResult() *LuckyGiftDrawResult { @@ -9917,7 +10978,7 @@ type GetLuckyGiftConfigRequest struct { func (x *GetLuckyGiftConfigRequest) Reset() { *x = GetLuckyGiftConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[119] + mi := &file_proto_activity_v1_activity_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9929,7 +10990,7 @@ func (x *GetLuckyGiftConfigRequest) String() string { func (*GetLuckyGiftConfigRequest) ProtoMessage() {} func (x *GetLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[119] + mi := &file_proto_activity_v1_activity_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9942,7 +11003,7 @@ func (x *GetLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLuckyGiftConfigRequest.ProtoReflect.Descriptor instead. func (*GetLuckyGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{119} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{133} } func (x *GetLuckyGiftConfigRequest) GetMeta() *RequestMeta { @@ -9975,7 +11036,7 @@ type GetLuckyGiftConfigResponse struct { func (x *GetLuckyGiftConfigResponse) Reset() { *x = GetLuckyGiftConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[120] + mi := &file_proto_activity_v1_activity_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9987,7 +11048,7 @@ func (x *GetLuckyGiftConfigResponse) String() string { func (*GetLuckyGiftConfigResponse) ProtoMessage() {} func (x *GetLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[120] + mi := &file_proto_activity_v1_activity_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10000,7 +11061,7 @@ func (x *GetLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLuckyGiftConfigResponse.ProtoReflect.Descriptor instead. func (*GetLuckyGiftConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{120} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{134} } func (x *GetLuckyGiftConfigResponse) GetConfig() *LuckyGiftConfig { @@ -10021,7 +11082,7 @@ type UpsertLuckyGiftConfigRequest struct { func (x *UpsertLuckyGiftConfigRequest) Reset() { *x = UpsertLuckyGiftConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[121] + mi := &file_proto_activity_v1_activity_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10033,7 +11094,7 @@ func (x *UpsertLuckyGiftConfigRequest) String() string { func (*UpsertLuckyGiftConfigRequest) ProtoMessage() {} func (x *UpsertLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[121] + mi := &file_proto_activity_v1_activity_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10046,7 +11107,7 @@ func (x *UpsertLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLuckyGiftConfigRequest.ProtoReflect.Descriptor instead. func (*UpsertLuckyGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{121} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{135} } func (x *UpsertLuckyGiftConfigRequest) GetMeta() *RequestMeta { @@ -10079,7 +11140,7 @@ type UpsertLuckyGiftConfigResponse struct { func (x *UpsertLuckyGiftConfigResponse) Reset() { *x = UpsertLuckyGiftConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[122] + mi := &file_proto_activity_v1_activity_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10091,7 +11152,7 @@ func (x *UpsertLuckyGiftConfigResponse) String() string { func (*UpsertLuckyGiftConfigResponse) ProtoMessage() {} func (x *UpsertLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[122] + mi := &file_proto_activity_v1_activity_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10104,7 +11165,7 @@ func (x *UpsertLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertLuckyGiftConfigResponse.ProtoReflect.Descriptor instead. func (*UpsertLuckyGiftConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{122} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{136} } func (x *UpsertLuckyGiftConfigResponse) GetConfig() *LuckyGiftConfig { @@ -10123,7 +11184,7 @@ type ListLuckyGiftConfigsRequest struct { func (x *ListLuckyGiftConfigsRequest) Reset() { *x = ListLuckyGiftConfigsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[123] + mi := &file_proto_activity_v1_activity_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10135,7 +11196,7 @@ func (x *ListLuckyGiftConfigsRequest) String() string { func (*ListLuckyGiftConfigsRequest) ProtoMessage() {} func (x *ListLuckyGiftConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[123] + mi := &file_proto_activity_v1_activity_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10148,7 +11209,7 @@ func (x *ListLuckyGiftConfigsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLuckyGiftConfigsRequest.ProtoReflect.Descriptor instead. func (*ListLuckyGiftConfigsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{123} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{137} } func (x *ListLuckyGiftConfigsRequest) GetMeta() *RequestMeta { @@ -10167,7 +11228,7 @@ type ListLuckyGiftConfigsResponse struct { func (x *ListLuckyGiftConfigsResponse) Reset() { *x = ListLuckyGiftConfigsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[124] + mi := &file_proto_activity_v1_activity_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10179,7 +11240,7 @@ func (x *ListLuckyGiftConfigsResponse) String() string { func (*ListLuckyGiftConfigsResponse) ProtoMessage() {} func (x *ListLuckyGiftConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[124] + mi := &file_proto_activity_v1_activity_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10192,7 +11253,7 @@ func (x *ListLuckyGiftConfigsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLuckyGiftConfigsResponse.ProtoReflect.Descriptor instead. func (*ListLuckyGiftConfigsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{124} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{138} } func (x *ListLuckyGiftConfigsResponse) GetConfigs() []*LuckyGiftConfig { @@ -10218,7 +11279,7 @@ type ListLuckyGiftDrawsRequest struct { func (x *ListLuckyGiftDrawsRequest) Reset() { *x = ListLuckyGiftDrawsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[125] + mi := &file_proto_activity_v1_activity_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10230,7 +11291,7 @@ func (x *ListLuckyGiftDrawsRequest) String() string { func (*ListLuckyGiftDrawsRequest) ProtoMessage() {} func (x *ListLuckyGiftDrawsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[125] + mi := &file_proto_activity_v1_activity_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10243,7 +11304,7 @@ func (x *ListLuckyGiftDrawsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLuckyGiftDrawsRequest.ProtoReflect.Descriptor instead. func (*ListLuckyGiftDrawsRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{125} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{139} } func (x *ListLuckyGiftDrawsRequest) GetMeta() *RequestMeta { @@ -10312,7 +11373,7 @@ type ListLuckyGiftDrawsResponse struct { func (x *ListLuckyGiftDrawsResponse) Reset() { *x = ListLuckyGiftDrawsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[126] + mi := &file_proto_activity_v1_activity_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10324,7 +11385,7 @@ func (x *ListLuckyGiftDrawsResponse) String() string { func (*ListLuckyGiftDrawsResponse) ProtoMessage() {} func (x *ListLuckyGiftDrawsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[126] + mi := &file_proto_activity_v1_activity_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10337,7 +11398,7 @@ func (x *ListLuckyGiftDrawsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListLuckyGiftDrawsResponse.ProtoReflect.Descriptor instead. func (*ListLuckyGiftDrawsResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{126} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{140} } func (x *ListLuckyGiftDrawsResponse) GetDraws() []*LuckyGiftDrawResult { @@ -10773,6 +11834,94 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"\x80\x01\n" + "$ListRegistrationRewardClaimsResponse\x12B\n" + "\x06claims\x18\x01 \x03(\v2*.hyapp.activity.v1.RegistrationRewardClaimR\x06claims\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xe7\x02\n" + + "\x17FirstRechargeRewardTier\x12\x17\n" + + "\atier_id\x18\x01 \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\x02 \x01(\tR\btierCode\x12\x1b\n" + + "\ttier_name\x18\x03 \x01(\tR\btierName\x12&\n" + + "\x0fmin_coin_amount\x18\x04 \x01(\x03R\rminCoinAmount\x12&\n" + + "\x0fmax_coin_amount\x18\x05 \x01(\x03R\rmaxCoinAmount\x12*\n" + + "\x11resource_group_id\x18\x06 \x01(\x03R\x0fresourceGroupId\x12\x16\n" + + "\x06status\x18\a \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\b \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\n" + + " \x01(\x03R\vupdatedAtMs\"\x89\x02\n" + + "\x19FirstRechargeRewardConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\x12@\n" + + "\x05tiers\x18\x03 \x03(\v2*.hyapp.activity.v1.FirstRechargeRewardTierR\x05tiers\x12-\n" + + "\x13updated_by_admin_id\x18\x04 \x01(\x03R\x10updatedByAdminId\x12\"\n" + + "\rcreated_at_ms\x18\x05 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x06 \x01(\x03R\vupdatedAtMs\"\xbc\x05\n" + + "\x18FirstRechargeRewardClaim\x12\x19\n" + + "\bclaim_id\x18\x01 \x01(\tR\aclaimId\x12\x19\n" + + "\bevent_id\x18\x02 \x01(\tR\aeventId\x12%\n" + + "\x0etransaction_id\x18\x03 \x01(\tR\rtransactionId\x12\x1d\n" + + "\n" + + "command_id\x18\x04 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x05 \x01(\x03R\x06userId\x12\x17\n" + + "\atier_id\x18\x06 \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\a \x01(\tR\btierCode\x12*\n" + + "\x11resource_group_id\x18\b \x01(\x03R\x0fresourceGroupId\x120\n" + + "\x14recharge_coin_amount\x18\t \x01(\x03R\x12rechargeCoinAmount\x12+\n" + + "\x11recharge_sequence\x18\n" + + " \x01(\x03R\x10rechargeSequence\x12#\n" + + "\rrecharge_type\x18\v \x01(\tR\frechargeType\x12\x16\n" + + "\x06status\x18\f \x01(\tR\x06status\x12*\n" + + "\x11wallet_command_id\x18\r \x01(\tR\x0fwalletCommandId\x12&\n" + + "\x0fwallet_grant_id\x18\x0e \x01(\tR\rwalletGrantId\x12%\n" + + "\x0efailure_reason\x18\x0f \x01(\tR\rfailureReason\x12&\n" + + "\x0frecharged_at_ms\x18\x10 \x01(\x03R\rrechargedAtMs\x12\"\n" + + "\rgranted_at_ms\x18\x11 \x01(\x03R\vgrantedAtMs\x12\"\n" + + "\rcreated_at_ms\x18\x12 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x13 \x01(\x03R\vupdatedAtMs\"\xfc\x01\n" + + "\x19FirstRechargeRewardStatus\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x12@\n" + + "\x05tiers\x18\x02 \x03(\v2*.hyapp.activity.v1.FirstRechargeRewardTierR\x05tiers\x12\x1a\n" + + "\brewarded\x18\x03 \x01(\bR\brewarded\x12A\n" + + "\x05claim\x18\x04 \x01(\v2+.hyapp.activity.v1.FirstRechargeRewardClaimR\x05claim\x12$\n" + + "\x0eserver_time_ms\x18\x05 \x01(\x03R\fserverTimeMs\"r\n" + + "#GetFirstRechargeRewardStatusRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"l\n" + + "$GetFirstRechargeRewardStatusResponse\x12D\n" + + "\x06status\x18\x01 \x01(\v2,.hyapp.activity.v1.FirstRechargeRewardStatusR\x06status\"\xfb\x02\n" + + "!ConsumeFirstRechargeRewardRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bevent_id\x18\x02 \x01(\tR\aeventId\x12%\n" + + "\x0etransaction_id\x18\x03 \x01(\tR\rtransactionId\x12\x1d\n" + + "\n" + + "command_id\x18\x04 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x05 \x01(\x03R\x06userId\x120\n" + + "\x14recharge_coin_amount\x18\x06 \x01(\x03R\x12rechargeCoinAmount\x12+\n" + + "\x11recharge_sequence\x18\a \x01(\x03R\x10rechargeSequence\x12#\n" + + "\rrecharge_type\x18\b \x01(\tR\frechargeType\x12$\n" + + "\x0eoccurred_at_ms\x18\t \x01(\x03R\foccurredAtMs\"\x9b\x01\n" + + "\"ConsumeFirstRechargeRewardResponse\x12A\n" + + "\x05claim\x18\x01 \x01(\v2+.hyapp.activity.v1.FirstRechargeRewardClaimR\x05claim\x12\x1a\n" + + "\bconsumed\x18\x02 \x01(\bR\bconsumed\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\"Y\n" + + "#GetFirstRechargeRewardConfigRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\"l\n" + + "$GetFirstRechargeRewardConfigResponse\x12D\n" + + "\x06config\x18\x01 \x01(\v2,.hyapp.activity.v1.FirstRechargeRewardConfigR\x06config\"\xe4\x01\n" + + "&UpdateFirstRechargeRewardConfigRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x18\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\x12@\n" + + "\x05tiers\x18\x03 \x03(\v2*.hyapp.activity.v1.FirstRechargeRewardTierR\x05tiers\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\"o\n" + + "'UpdateFirstRechargeRewardConfigResponse\x12D\n" + + "\x06config\x18\x01 \x01(\v2,.hyapp.activity.v1.FirstRechargeRewardConfigR\x06config\"\xbc\x01\n" + + "$ListFirstRechargeRewardClaimsRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x12\n" + + "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"\x82\x01\n" + + "%ListFirstRechargeRewardClaimsResponse\x12C\n" + + "\x06claims\x18\x01 \x03(\v2+.hyapp.activity.v1.FirstRechargeRewardClaimR\x06claims\x12\x14\n" + "\x05total\x18\x02 \x01(\x03R\x05total\"`\n" + "\x15SevenDayCheckInReward\x12\x1b\n" + "\tday_index\x18\x01 \x01(\x05R\bdayIndex\x12*\n" + @@ -11363,7 +12512,14 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\x1eAdminRegistrationRewardService\x12\x8c\x01\n" + "\x1bGetRegistrationRewardConfig\x125.hyapp.activity.v1.GetRegistrationRewardConfigRequest\x1a6.hyapp.activity.v1.GetRegistrationRewardConfigResponse\x12\x95\x01\n" + "\x1eUpdateRegistrationRewardConfig\x128.hyapp.activity.v1.UpdateRegistrationRewardConfigRequest\x1a9.hyapp.activity.v1.UpdateRegistrationRewardConfigResponse\x12\x8f\x01\n" + - "\x1cListRegistrationRewardClaims\x126.hyapp.activity.v1.ListRegistrationRewardClaimsRequest\x1a7.hyapp.activity.v1.ListRegistrationRewardClaimsResponse2\x94\x02\n" + + "\x1cListRegistrationRewardClaims\x126.hyapp.activity.v1.ListRegistrationRewardClaimsRequest\x1a7.hyapp.activity.v1.ListRegistrationRewardClaimsResponse2\xba\x02\n" + + "\x1aFirstRechargeRewardService\x12\x8f\x01\n" + + "\x1cGetFirstRechargeRewardStatus\x126.hyapp.activity.v1.GetFirstRechargeRewardStatusRequest\x1a7.hyapp.activity.v1.GetFirstRechargeRewardStatusResponse\x12\x89\x01\n" + + "\x1aConsumeFirstRechargeReward\x124.hyapp.activity.v1.ConsumeFirstRechargeRewardRequest\x1a5.hyapp.activity.v1.ConsumeFirstRechargeRewardResponse2\xe3\x03\n" + + "\x1fAdminFirstRechargeRewardService\x12\x8f\x01\n" + + "\x1cGetFirstRechargeRewardConfig\x126.hyapp.activity.v1.GetFirstRechargeRewardConfigRequest\x1a7.hyapp.activity.v1.GetFirstRechargeRewardConfigResponse\x12\x98\x01\n" + + "\x1fUpdateFirstRechargeRewardConfig\x129.hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest\x1a:.hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse\x12\x92\x01\n" + + "\x1dListFirstRechargeRewardClaims\x127.hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest\x1a8.hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse2\x94\x02\n" + "\x16SevenDayCheckInService\x12\x83\x01\n" + "\x18GetSevenDayCheckInStatus\x122.hyapp.activity.v1.GetSevenDayCheckInStatusRequest\x1a3.hyapp.activity.v1.GetSevenDayCheckInStatusResponse\x12t\n" + "\x13SignSevenDayCheckIn\x12-.hyapp.activity.v1.SignSevenDayCheckInRequest\x1a..hyapp.activity.v1.SignSevenDayCheckInResponse2\xbb\x03\n" + @@ -11397,7 +12553,7 @@ func file_proto_activity_v1_activity_proto_rawDescGZIP() []byte { return file_proto_activity_v1_activity_proto_rawDescData } -var file_proto_activity_v1_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 127) +var file_proto_activity_v1_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 141) var file_proto_activity_v1_activity_proto_goTypes = []any{ (*RequestMeta)(nil), // 0: hyapp.activity.v1.RequestMeta (*PingActivityRequest)(nil), // 1: hyapp.activity.v1.PingActivityRequest @@ -11461,72 +12617,86 @@ var file_proto_activity_v1_activity_proto_goTypes = []any{ (*UpdateRegistrationRewardConfigResponse)(nil), // 59: hyapp.activity.v1.UpdateRegistrationRewardConfigResponse (*ListRegistrationRewardClaimsRequest)(nil), // 60: hyapp.activity.v1.ListRegistrationRewardClaimsRequest (*ListRegistrationRewardClaimsResponse)(nil), // 61: hyapp.activity.v1.ListRegistrationRewardClaimsResponse - (*SevenDayCheckInReward)(nil), // 62: hyapp.activity.v1.SevenDayCheckInReward - (*SevenDayCheckInConfig)(nil), // 63: hyapp.activity.v1.SevenDayCheckInConfig - (*SevenDayCheckInRewardStatus)(nil), // 64: hyapp.activity.v1.SevenDayCheckInRewardStatus - (*GetSevenDayCheckInStatusRequest)(nil), // 65: hyapp.activity.v1.GetSevenDayCheckInStatusRequest - (*GetSevenDayCheckInStatusResponse)(nil), // 66: hyapp.activity.v1.GetSevenDayCheckInStatusResponse - (*SignSevenDayCheckInRequest)(nil), // 67: hyapp.activity.v1.SignSevenDayCheckInRequest - (*SignSevenDayCheckInResponse)(nil), // 68: hyapp.activity.v1.SignSevenDayCheckInResponse - (*GetSevenDayCheckInConfigRequest)(nil), // 69: hyapp.activity.v1.GetSevenDayCheckInConfigRequest - (*GetSevenDayCheckInConfigResponse)(nil), // 70: hyapp.activity.v1.GetSevenDayCheckInConfigResponse - (*UpdateSevenDayCheckInConfigRequest)(nil), // 71: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest - (*UpdateSevenDayCheckInConfigResponse)(nil), // 72: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse - (*SevenDayCheckInClaim)(nil), // 73: hyapp.activity.v1.SevenDayCheckInClaim - (*ListSevenDayCheckInClaimsRequest)(nil), // 74: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest - (*ListSevenDayCheckInClaimsResponse)(nil), // 75: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse - (*LevelTrack)(nil), // 76: hyapp.activity.v1.LevelTrack - (*LevelRule)(nil), // 77: hyapp.activity.v1.LevelRule - (*LevelTier)(nil), // 78: hyapp.activity.v1.LevelTier - (*LevelTrackOverview)(nil), // 79: hyapp.activity.v1.LevelTrackOverview - (*GetMyLevelOverviewRequest)(nil), // 80: hyapp.activity.v1.GetMyLevelOverviewRequest - (*GetMyLevelOverviewResponse)(nil), // 81: hyapp.activity.v1.GetMyLevelOverviewResponse - (*GetLevelTrackRequest)(nil), // 82: hyapp.activity.v1.GetLevelTrackRequest - (*GetLevelTrackResponse)(nil), // 83: hyapp.activity.v1.GetLevelTrackResponse - (*LevelRewardJob)(nil), // 84: hyapp.activity.v1.LevelRewardJob - (*ListLevelRewardsRequest)(nil), // 85: hyapp.activity.v1.ListLevelRewardsRequest - (*ListLevelRewardsResponse)(nil), // 86: hyapp.activity.v1.ListLevelRewardsResponse - (*ConsumeLevelEventRequest)(nil), // 87: hyapp.activity.v1.ConsumeLevelEventRequest - (*ConsumeLevelEventResponse)(nil), // 88: hyapp.activity.v1.ConsumeLevelEventResponse - (*UpsertLevelTrackRequest)(nil), // 89: hyapp.activity.v1.UpsertLevelTrackRequest - (*UpsertLevelTrackResponse)(nil), // 90: hyapp.activity.v1.UpsertLevelTrackResponse - (*UpsertLevelRuleRequest)(nil), // 91: hyapp.activity.v1.UpsertLevelRuleRequest - (*UpsertLevelRuleResponse)(nil), // 92: hyapp.activity.v1.UpsertLevelRuleResponse - (*UpsertLevelTierRequest)(nil), // 93: hyapp.activity.v1.UpsertLevelTierRequest - (*UpsertLevelTierResponse)(nil), // 94: hyapp.activity.v1.UpsertLevelTierResponse - (*ListLevelConfigRequest)(nil), // 95: hyapp.activity.v1.ListLevelConfigRequest - (*ListLevelConfigResponse)(nil), // 96: hyapp.activity.v1.ListLevelConfigResponse - (*AchievementCondition)(nil), // 97: hyapp.activity.v1.AchievementCondition - (*AchievementDefinition)(nil), // 98: hyapp.activity.v1.AchievementDefinition - (*UserAchievement)(nil), // 99: hyapp.activity.v1.UserAchievement - (*ListAchievementsRequest)(nil), // 100: hyapp.activity.v1.ListAchievementsRequest - (*ListAchievementsResponse)(nil), // 101: hyapp.activity.v1.ListAchievementsResponse - (*ConsumeAchievementEventRequest)(nil), // 102: hyapp.activity.v1.ConsumeAchievementEventRequest - (*ConsumeAchievementEventResponse)(nil), // 103: hyapp.activity.v1.ConsumeAchievementEventResponse - (*BadgeDisplayItem)(nil), // 104: hyapp.activity.v1.BadgeDisplayItem - (*ListMyBadgesRequest)(nil), // 105: hyapp.activity.v1.ListMyBadgesRequest - (*ListMyBadgesResponse)(nil), // 106: hyapp.activity.v1.ListMyBadgesResponse - (*SetBadgeDisplayRequest)(nil), // 107: hyapp.activity.v1.SetBadgeDisplayRequest - (*SetBadgeDisplayResponse)(nil), // 108: hyapp.activity.v1.SetBadgeDisplayResponse - (*UpsertAchievementDefinitionRequest)(nil), // 109: hyapp.activity.v1.UpsertAchievementDefinitionRequest - (*UpsertAchievementDefinitionResponse)(nil), // 110: hyapp.activity.v1.UpsertAchievementDefinitionResponse - (*LuckyGiftMeta)(nil), // 111: hyapp.activity.v1.LuckyGiftMeta - (*LuckyGiftTier)(nil), // 112: hyapp.activity.v1.LuckyGiftTier - (*LuckyGiftConfig)(nil), // 113: hyapp.activity.v1.LuckyGiftConfig - (*CheckLuckyGiftRequest)(nil), // 114: hyapp.activity.v1.CheckLuckyGiftRequest - (*CheckLuckyGiftResponse)(nil), // 115: hyapp.activity.v1.CheckLuckyGiftResponse - (*LuckyGiftDrawResult)(nil), // 116: hyapp.activity.v1.LuckyGiftDrawResult - (*ExecuteLuckyGiftDrawRequest)(nil), // 117: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest - (*ExecuteLuckyGiftDrawResponse)(nil), // 118: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse - (*GetLuckyGiftConfigRequest)(nil), // 119: hyapp.activity.v1.GetLuckyGiftConfigRequest - (*GetLuckyGiftConfigResponse)(nil), // 120: hyapp.activity.v1.GetLuckyGiftConfigResponse - (*UpsertLuckyGiftConfigRequest)(nil), // 121: hyapp.activity.v1.UpsertLuckyGiftConfigRequest - (*UpsertLuckyGiftConfigResponse)(nil), // 122: hyapp.activity.v1.UpsertLuckyGiftConfigResponse - (*ListLuckyGiftConfigsRequest)(nil), // 123: hyapp.activity.v1.ListLuckyGiftConfigsRequest - (*ListLuckyGiftConfigsResponse)(nil), // 124: hyapp.activity.v1.ListLuckyGiftConfigsResponse - (*ListLuckyGiftDrawsRequest)(nil), // 125: hyapp.activity.v1.ListLuckyGiftDrawsRequest - (*ListLuckyGiftDrawsResponse)(nil), // 126: hyapp.activity.v1.ListLuckyGiftDrawsResponse - (*v1.EventEnvelope)(nil), // 127: hyapp.events.room.v1.EventEnvelope + (*FirstRechargeRewardTier)(nil), // 62: hyapp.activity.v1.FirstRechargeRewardTier + (*FirstRechargeRewardConfig)(nil), // 63: hyapp.activity.v1.FirstRechargeRewardConfig + (*FirstRechargeRewardClaim)(nil), // 64: hyapp.activity.v1.FirstRechargeRewardClaim + (*FirstRechargeRewardStatus)(nil), // 65: hyapp.activity.v1.FirstRechargeRewardStatus + (*GetFirstRechargeRewardStatusRequest)(nil), // 66: hyapp.activity.v1.GetFirstRechargeRewardStatusRequest + (*GetFirstRechargeRewardStatusResponse)(nil), // 67: hyapp.activity.v1.GetFirstRechargeRewardStatusResponse + (*ConsumeFirstRechargeRewardRequest)(nil), // 68: hyapp.activity.v1.ConsumeFirstRechargeRewardRequest + (*ConsumeFirstRechargeRewardResponse)(nil), // 69: hyapp.activity.v1.ConsumeFirstRechargeRewardResponse + (*GetFirstRechargeRewardConfigRequest)(nil), // 70: hyapp.activity.v1.GetFirstRechargeRewardConfigRequest + (*GetFirstRechargeRewardConfigResponse)(nil), // 71: hyapp.activity.v1.GetFirstRechargeRewardConfigResponse + (*UpdateFirstRechargeRewardConfigRequest)(nil), // 72: hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest + (*UpdateFirstRechargeRewardConfigResponse)(nil), // 73: hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse + (*ListFirstRechargeRewardClaimsRequest)(nil), // 74: hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest + (*ListFirstRechargeRewardClaimsResponse)(nil), // 75: hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse + (*SevenDayCheckInReward)(nil), // 76: hyapp.activity.v1.SevenDayCheckInReward + (*SevenDayCheckInConfig)(nil), // 77: hyapp.activity.v1.SevenDayCheckInConfig + (*SevenDayCheckInRewardStatus)(nil), // 78: hyapp.activity.v1.SevenDayCheckInRewardStatus + (*GetSevenDayCheckInStatusRequest)(nil), // 79: hyapp.activity.v1.GetSevenDayCheckInStatusRequest + (*GetSevenDayCheckInStatusResponse)(nil), // 80: hyapp.activity.v1.GetSevenDayCheckInStatusResponse + (*SignSevenDayCheckInRequest)(nil), // 81: hyapp.activity.v1.SignSevenDayCheckInRequest + (*SignSevenDayCheckInResponse)(nil), // 82: hyapp.activity.v1.SignSevenDayCheckInResponse + (*GetSevenDayCheckInConfigRequest)(nil), // 83: hyapp.activity.v1.GetSevenDayCheckInConfigRequest + (*GetSevenDayCheckInConfigResponse)(nil), // 84: hyapp.activity.v1.GetSevenDayCheckInConfigResponse + (*UpdateSevenDayCheckInConfigRequest)(nil), // 85: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest + (*UpdateSevenDayCheckInConfigResponse)(nil), // 86: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse + (*SevenDayCheckInClaim)(nil), // 87: hyapp.activity.v1.SevenDayCheckInClaim + (*ListSevenDayCheckInClaimsRequest)(nil), // 88: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest + (*ListSevenDayCheckInClaimsResponse)(nil), // 89: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse + (*LevelTrack)(nil), // 90: hyapp.activity.v1.LevelTrack + (*LevelRule)(nil), // 91: hyapp.activity.v1.LevelRule + (*LevelTier)(nil), // 92: hyapp.activity.v1.LevelTier + (*LevelTrackOverview)(nil), // 93: hyapp.activity.v1.LevelTrackOverview + (*GetMyLevelOverviewRequest)(nil), // 94: hyapp.activity.v1.GetMyLevelOverviewRequest + (*GetMyLevelOverviewResponse)(nil), // 95: hyapp.activity.v1.GetMyLevelOverviewResponse + (*GetLevelTrackRequest)(nil), // 96: hyapp.activity.v1.GetLevelTrackRequest + (*GetLevelTrackResponse)(nil), // 97: hyapp.activity.v1.GetLevelTrackResponse + (*LevelRewardJob)(nil), // 98: hyapp.activity.v1.LevelRewardJob + (*ListLevelRewardsRequest)(nil), // 99: hyapp.activity.v1.ListLevelRewardsRequest + (*ListLevelRewardsResponse)(nil), // 100: hyapp.activity.v1.ListLevelRewardsResponse + (*ConsumeLevelEventRequest)(nil), // 101: hyapp.activity.v1.ConsumeLevelEventRequest + (*ConsumeLevelEventResponse)(nil), // 102: hyapp.activity.v1.ConsumeLevelEventResponse + (*UpsertLevelTrackRequest)(nil), // 103: hyapp.activity.v1.UpsertLevelTrackRequest + (*UpsertLevelTrackResponse)(nil), // 104: hyapp.activity.v1.UpsertLevelTrackResponse + (*UpsertLevelRuleRequest)(nil), // 105: hyapp.activity.v1.UpsertLevelRuleRequest + (*UpsertLevelRuleResponse)(nil), // 106: hyapp.activity.v1.UpsertLevelRuleResponse + (*UpsertLevelTierRequest)(nil), // 107: hyapp.activity.v1.UpsertLevelTierRequest + (*UpsertLevelTierResponse)(nil), // 108: hyapp.activity.v1.UpsertLevelTierResponse + (*ListLevelConfigRequest)(nil), // 109: hyapp.activity.v1.ListLevelConfigRequest + (*ListLevelConfigResponse)(nil), // 110: hyapp.activity.v1.ListLevelConfigResponse + (*AchievementCondition)(nil), // 111: hyapp.activity.v1.AchievementCondition + (*AchievementDefinition)(nil), // 112: hyapp.activity.v1.AchievementDefinition + (*UserAchievement)(nil), // 113: hyapp.activity.v1.UserAchievement + (*ListAchievementsRequest)(nil), // 114: hyapp.activity.v1.ListAchievementsRequest + (*ListAchievementsResponse)(nil), // 115: hyapp.activity.v1.ListAchievementsResponse + (*ConsumeAchievementEventRequest)(nil), // 116: hyapp.activity.v1.ConsumeAchievementEventRequest + (*ConsumeAchievementEventResponse)(nil), // 117: hyapp.activity.v1.ConsumeAchievementEventResponse + (*BadgeDisplayItem)(nil), // 118: hyapp.activity.v1.BadgeDisplayItem + (*ListMyBadgesRequest)(nil), // 119: hyapp.activity.v1.ListMyBadgesRequest + (*ListMyBadgesResponse)(nil), // 120: hyapp.activity.v1.ListMyBadgesResponse + (*SetBadgeDisplayRequest)(nil), // 121: hyapp.activity.v1.SetBadgeDisplayRequest + (*SetBadgeDisplayResponse)(nil), // 122: hyapp.activity.v1.SetBadgeDisplayResponse + (*UpsertAchievementDefinitionRequest)(nil), // 123: hyapp.activity.v1.UpsertAchievementDefinitionRequest + (*UpsertAchievementDefinitionResponse)(nil), // 124: hyapp.activity.v1.UpsertAchievementDefinitionResponse + (*LuckyGiftMeta)(nil), // 125: hyapp.activity.v1.LuckyGiftMeta + (*LuckyGiftTier)(nil), // 126: hyapp.activity.v1.LuckyGiftTier + (*LuckyGiftConfig)(nil), // 127: hyapp.activity.v1.LuckyGiftConfig + (*CheckLuckyGiftRequest)(nil), // 128: hyapp.activity.v1.CheckLuckyGiftRequest + (*CheckLuckyGiftResponse)(nil), // 129: hyapp.activity.v1.CheckLuckyGiftResponse + (*LuckyGiftDrawResult)(nil), // 130: hyapp.activity.v1.LuckyGiftDrawResult + (*ExecuteLuckyGiftDrawRequest)(nil), // 131: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest + (*ExecuteLuckyGiftDrawResponse)(nil), // 132: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse + (*GetLuckyGiftConfigRequest)(nil), // 133: hyapp.activity.v1.GetLuckyGiftConfigRequest + (*GetLuckyGiftConfigResponse)(nil), // 134: hyapp.activity.v1.GetLuckyGiftConfigResponse + (*UpsertLuckyGiftConfigRequest)(nil), // 135: hyapp.activity.v1.UpsertLuckyGiftConfigRequest + (*UpsertLuckyGiftConfigResponse)(nil), // 136: hyapp.activity.v1.UpsertLuckyGiftConfigResponse + (*ListLuckyGiftConfigsRequest)(nil), // 137: hyapp.activity.v1.ListLuckyGiftConfigsRequest + (*ListLuckyGiftConfigsResponse)(nil), // 138: hyapp.activity.v1.ListLuckyGiftConfigsResponse + (*ListLuckyGiftDrawsRequest)(nil), // 139: hyapp.activity.v1.ListLuckyGiftDrawsRequest + (*ListLuckyGiftDrawsResponse)(nil), // 140: hyapp.activity.v1.ListLuckyGiftDrawsResponse + (*v1.EventEnvelope)(nil), // 141: hyapp.events.room.v1.EventEnvelope } var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 0, // 0: hyapp.activity.v1.PingActivityRequest.meta:type_name -> hyapp.activity.v1.RequestMeta @@ -11551,7 +12721,7 @@ var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 0, // 19: hyapp.activity.v1.PublishGlobalBroadcastRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 0, // 20: hyapp.activity.v1.RemoveRegionBroadcastMemberRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 0, // 21: hyapp.activity.v1.ConsumeRoomEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 127, // 22: hyapp.activity.v1.ConsumeRoomEventRequest.envelope:type_name -> hyapp.events.room.v1.EventEnvelope + 141, // 22: hyapp.activity.v1.ConsumeRoomEventRequest.envelope:type_name -> hyapp.events.room.v1.EventEnvelope 0, // 23: hyapp.activity.v1.ListTaskDefinitionsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 42, // 24: hyapp.activity.v1.ListTaskDefinitionsResponse.tasks:type_name -> hyapp.activity.v1.TaskDefinition 0, // 25: hyapp.activity.v1.UpsertTaskDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta @@ -11569,178 +12739,202 @@ var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 49, // 37: hyapp.activity.v1.UpdateRegistrationRewardConfigResponse.config:type_name -> hyapp.activity.v1.RegistrationRewardConfig 0, // 38: hyapp.activity.v1.ListRegistrationRewardClaimsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta 50, // 39: hyapp.activity.v1.ListRegistrationRewardClaimsResponse.claims:type_name -> hyapp.activity.v1.RegistrationRewardClaim - 62, // 40: hyapp.activity.v1.SevenDayCheckInConfig.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward - 0, // 41: hyapp.activity.v1.GetSevenDayCheckInStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 64, // 42: hyapp.activity.v1.GetSevenDayCheckInStatusResponse.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInRewardStatus - 0, // 43: hyapp.activity.v1.SignSevenDayCheckInRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 44: hyapp.activity.v1.GetSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 63, // 45: hyapp.activity.v1.GetSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig - 0, // 46: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 62, // 47: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward - 63, // 48: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig - 0, // 49: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 73, // 50: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse.claims:type_name -> hyapp.activity.v1.SevenDayCheckInClaim - 0, // 51: hyapp.activity.v1.GetMyLevelOverviewRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 79, // 52: hyapp.activity.v1.GetMyLevelOverviewResponse.tracks:type_name -> hyapp.activity.v1.LevelTrackOverview - 0, // 53: hyapp.activity.v1.GetLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 79, // 54: hyapp.activity.v1.GetLevelTrackResponse.overview:type_name -> hyapp.activity.v1.LevelTrackOverview - 77, // 55: hyapp.activity.v1.GetLevelTrackResponse.rules:type_name -> hyapp.activity.v1.LevelRule - 78, // 56: hyapp.activity.v1.GetLevelTrackResponse.tiers:type_name -> hyapp.activity.v1.LevelTier - 0, // 57: hyapp.activity.v1.ListLevelRewardsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 84, // 58: hyapp.activity.v1.ListLevelRewardsResponse.rewards:type_name -> hyapp.activity.v1.LevelRewardJob - 0, // 59: hyapp.activity.v1.ConsumeLevelEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 60: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 76, // 61: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack - 0, // 62: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 77, // 63: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule - 0, // 64: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 78, // 65: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier - 0, // 66: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 76, // 67: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack - 77, // 68: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule - 78, // 69: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier - 97, // 70: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 98, // 71: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 72: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 99, // 73: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement - 0, // 74: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 75: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 104, // 76: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 104, // 77: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 104, // 78: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 0, // 79: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 104, // 80: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem - 106, // 81: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse - 0, // 82: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 97, // 83: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 98, // 84: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 85: hyapp.activity.v1.LuckyGiftMeta.meta:type_name -> hyapp.activity.v1.RequestMeta - 112, // 86: hyapp.activity.v1.LuckyGiftConfig.tiers:type_name -> hyapp.activity.v1.LuckyGiftTier - 0, // 87: hyapp.activity.v1.CheckLuckyGiftRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 111, // 88: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest.lucky_gift:type_name -> hyapp.activity.v1.LuckyGiftMeta - 116, // 89: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse.result:type_name -> hyapp.activity.v1.LuckyGiftDrawResult - 0, // 90: hyapp.activity.v1.GetLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 113, // 91: hyapp.activity.v1.GetLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftConfig - 0, // 92: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 113, // 93: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.config:type_name -> hyapp.activity.v1.LuckyGiftConfig - 113, // 94: hyapp.activity.v1.UpsertLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftConfig - 0, // 95: hyapp.activity.v1.ListLuckyGiftConfigsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 113, // 96: hyapp.activity.v1.ListLuckyGiftConfigsResponse.configs:type_name -> hyapp.activity.v1.LuckyGiftConfig - 0, // 97: hyapp.activity.v1.ListLuckyGiftDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 116, // 98: hyapp.activity.v1.ListLuckyGiftDrawsResponse.draws:type_name -> hyapp.activity.v1.LuckyGiftDrawResult - 1, // 99: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest - 3, // 100: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest - 6, // 101: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest - 9, // 102: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest - 11, // 103: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest - 13, // 104: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest - 15, // 105: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest - 17, // 106: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest - 19, // 107: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest - 21, // 108: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 21, // 109: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 21, // 110: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 25, // 111: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest - 27, // 112: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest - 29, // 113: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest - 80, // 114: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest - 82, // 115: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest - 85, // 116: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest - 87, // 117: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest - 100, // 118: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest - 102, // 119: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest - 105, // 120: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest - 107, // 121: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest - 114, // 122: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:input_type -> hyapp.activity.v1.CheckLuckyGiftRequest - 117, // 123: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:input_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawRequest - 32, // 124: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest - 34, // 125: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest - 35, // 126: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest - 37, // 127: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest - 21, // 128: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 40, // 129: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest - 43, // 130: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest - 45, // 131: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest - 47, // 132: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest - 52, // 133: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest - 54, // 134: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest - 56, // 135: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest - 58, // 136: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest - 60, // 137: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest - 65, // 138: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest - 67, // 139: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest - 69, // 140: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest - 71, // 141: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest - 74, // 142: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest - 95, // 143: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest - 89, // 144: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest - 91, // 145: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest - 93, // 146: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest - 100, // 147: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest - 109, // 148: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest - 119, // 149: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:input_type -> hyapp.activity.v1.GetLuckyGiftConfigRequest - 121, // 150: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:input_type -> hyapp.activity.v1.UpsertLuckyGiftConfigRequest - 123, // 151: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:input_type -> hyapp.activity.v1.ListLuckyGiftConfigsRequest - 125, // 152: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:input_type -> hyapp.activity.v1.ListLuckyGiftDrawsRequest - 2, // 153: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse - 4, // 154: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse - 7, // 155: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse - 10, // 156: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse - 12, // 157: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse - 14, // 158: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse - 16, // 159: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse - 18, // 160: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse - 20, // 161: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse - 22, // 162: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 22, // 163: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 22, // 164: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 26, // 165: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse - 28, // 166: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse - 30, // 167: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse - 81, // 168: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse - 83, // 169: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse - 86, // 170: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse - 88, // 171: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse - 101, // 172: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse - 103, // 173: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse - 106, // 174: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse - 108, // 175: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse - 115, // 176: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:output_type -> hyapp.activity.v1.CheckLuckyGiftResponse - 118, // 177: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:output_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawResponse - 33, // 178: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse - 36, // 179: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 36, // 180: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 38, // 181: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse - 39, // 182: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse - 41, // 183: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse - 44, // 184: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse - 46, // 185: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse - 48, // 186: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse - 53, // 187: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse - 55, // 188: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse - 57, // 189: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse - 59, // 190: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse - 61, // 191: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse - 66, // 192: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse - 68, // 193: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse - 70, // 194: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse - 72, // 195: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse - 75, // 196: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse - 96, // 197: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse - 90, // 198: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse - 92, // 199: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse - 94, // 200: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse - 101, // 201: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse - 110, // 202: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse - 120, // 203: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:output_type -> hyapp.activity.v1.GetLuckyGiftConfigResponse - 122, // 204: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:output_type -> hyapp.activity.v1.UpsertLuckyGiftConfigResponse - 124, // 205: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:output_type -> hyapp.activity.v1.ListLuckyGiftConfigsResponse - 126, // 206: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:output_type -> hyapp.activity.v1.ListLuckyGiftDrawsResponse - 153, // [153:207] is the sub-list for method output_type - 99, // [99:153] is the sub-list for method input_type - 99, // [99:99] is the sub-list for extension type_name - 99, // [99:99] is the sub-list for extension extendee - 0, // [0:99] is the sub-list for field type_name + 62, // 40: hyapp.activity.v1.FirstRechargeRewardConfig.tiers:type_name -> hyapp.activity.v1.FirstRechargeRewardTier + 62, // 41: hyapp.activity.v1.FirstRechargeRewardStatus.tiers:type_name -> hyapp.activity.v1.FirstRechargeRewardTier + 64, // 42: hyapp.activity.v1.FirstRechargeRewardStatus.claim:type_name -> hyapp.activity.v1.FirstRechargeRewardClaim + 0, // 43: hyapp.activity.v1.GetFirstRechargeRewardStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 65, // 44: hyapp.activity.v1.GetFirstRechargeRewardStatusResponse.status:type_name -> hyapp.activity.v1.FirstRechargeRewardStatus + 0, // 45: hyapp.activity.v1.ConsumeFirstRechargeRewardRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 64, // 46: hyapp.activity.v1.ConsumeFirstRechargeRewardResponse.claim:type_name -> hyapp.activity.v1.FirstRechargeRewardClaim + 0, // 47: hyapp.activity.v1.GetFirstRechargeRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 63, // 48: hyapp.activity.v1.GetFirstRechargeRewardConfigResponse.config:type_name -> hyapp.activity.v1.FirstRechargeRewardConfig + 0, // 49: hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 62, // 50: hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest.tiers:type_name -> hyapp.activity.v1.FirstRechargeRewardTier + 63, // 51: hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse.config:type_name -> hyapp.activity.v1.FirstRechargeRewardConfig + 0, // 52: hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 64, // 53: hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse.claims:type_name -> hyapp.activity.v1.FirstRechargeRewardClaim + 76, // 54: hyapp.activity.v1.SevenDayCheckInConfig.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward + 0, // 55: hyapp.activity.v1.GetSevenDayCheckInStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 78, // 56: hyapp.activity.v1.GetSevenDayCheckInStatusResponse.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInRewardStatus + 0, // 57: hyapp.activity.v1.SignSevenDayCheckInRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 58: hyapp.activity.v1.GetSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 77, // 59: hyapp.activity.v1.GetSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig + 0, // 60: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 76, // 61: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward + 77, // 62: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig + 0, // 63: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 87, // 64: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse.claims:type_name -> hyapp.activity.v1.SevenDayCheckInClaim + 0, // 65: hyapp.activity.v1.GetMyLevelOverviewRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 93, // 66: hyapp.activity.v1.GetMyLevelOverviewResponse.tracks:type_name -> hyapp.activity.v1.LevelTrackOverview + 0, // 67: hyapp.activity.v1.GetLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 93, // 68: hyapp.activity.v1.GetLevelTrackResponse.overview:type_name -> hyapp.activity.v1.LevelTrackOverview + 91, // 69: hyapp.activity.v1.GetLevelTrackResponse.rules:type_name -> hyapp.activity.v1.LevelRule + 92, // 70: hyapp.activity.v1.GetLevelTrackResponse.tiers:type_name -> hyapp.activity.v1.LevelTier + 0, // 71: hyapp.activity.v1.ListLevelRewardsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 98, // 72: hyapp.activity.v1.ListLevelRewardsResponse.rewards:type_name -> hyapp.activity.v1.LevelRewardJob + 0, // 73: hyapp.activity.v1.ConsumeLevelEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 74: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 90, // 75: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack + 0, // 76: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 91, // 77: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule + 0, // 78: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 92, // 79: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier + 0, // 80: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 90, // 81: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack + 91, // 82: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule + 92, // 83: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier + 111, // 84: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 112, // 85: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 86: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 113, // 87: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement + 0, // 88: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 89: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 118, // 90: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 118, // 91: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 118, // 92: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 0, // 93: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 118, // 94: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem + 120, // 95: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse + 0, // 96: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 111, // 97: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 112, // 98: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 99: hyapp.activity.v1.LuckyGiftMeta.meta:type_name -> hyapp.activity.v1.RequestMeta + 126, // 100: hyapp.activity.v1.LuckyGiftConfig.tiers:type_name -> hyapp.activity.v1.LuckyGiftTier + 0, // 101: hyapp.activity.v1.CheckLuckyGiftRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 125, // 102: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest.lucky_gift:type_name -> hyapp.activity.v1.LuckyGiftMeta + 130, // 103: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse.result:type_name -> hyapp.activity.v1.LuckyGiftDrawResult + 0, // 104: hyapp.activity.v1.GetLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 127, // 105: hyapp.activity.v1.GetLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftConfig + 0, // 106: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 127, // 107: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.config:type_name -> hyapp.activity.v1.LuckyGiftConfig + 127, // 108: hyapp.activity.v1.UpsertLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftConfig + 0, // 109: hyapp.activity.v1.ListLuckyGiftConfigsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 127, // 110: hyapp.activity.v1.ListLuckyGiftConfigsResponse.configs:type_name -> hyapp.activity.v1.LuckyGiftConfig + 0, // 111: hyapp.activity.v1.ListLuckyGiftDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 130, // 112: hyapp.activity.v1.ListLuckyGiftDrawsResponse.draws:type_name -> hyapp.activity.v1.LuckyGiftDrawResult + 1, // 113: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest + 3, // 114: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest + 6, // 115: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest + 9, // 116: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest + 11, // 117: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest + 13, // 118: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest + 15, // 119: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest + 17, // 120: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest + 19, // 121: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest + 21, // 122: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 123: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 124: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 25, // 125: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest + 27, // 126: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest + 29, // 127: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest + 94, // 128: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest + 96, // 129: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest + 99, // 130: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest + 101, // 131: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest + 114, // 132: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest + 116, // 133: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest + 119, // 134: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest + 121, // 135: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest + 128, // 136: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:input_type -> hyapp.activity.v1.CheckLuckyGiftRequest + 131, // 137: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:input_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawRequest + 32, // 138: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest + 34, // 139: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest + 35, // 140: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest + 37, // 141: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest + 21, // 142: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 40, // 143: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest + 43, // 144: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest + 45, // 145: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest + 47, // 146: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest + 52, // 147: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest + 54, // 148: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest + 56, // 149: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest + 58, // 150: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest + 60, // 151: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest + 66, // 152: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:input_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusRequest + 68, // 153: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:input_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardRequest + 70, // 154: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigRequest + 72, // 155: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest + 74, // 156: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:input_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest + 79, // 157: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest + 81, // 158: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest + 83, // 159: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest + 85, // 160: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest + 88, // 161: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest + 109, // 162: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest + 103, // 163: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest + 105, // 164: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest + 107, // 165: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest + 114, // 166: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest + 123, // 167: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest + 133, // 168: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:input_type -> hyapp.activity.v1.GetLuckyGiftConfigRequest + 135, // 169: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:input_type -> hyapp.activity.v1.UpsertLuckyGiftConfigRequest + 137, // 170: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:input_type -> hyapp.activity.v1.ListLuckyGiftConfigsRequest + 139, // 171: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:input_type -> hyapp.activity.v1.ListLuckyGiftDrawsRequest + 2, // 172: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse + 4, // 173: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse + 7, // 174: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse + 10, // 175: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse + 12, // 176: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse + 14, // 177: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse + 16, // 178: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse + 18, // 179: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse + 20, // 180: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse + 22, // 181: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 182: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 183: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 26, // 184: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse + 28, // 185: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse + 30, // 186: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse + 95, // 187: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse + 97, // 188: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse + 100, // 189: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse + 102, // 190: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse + 115, // 191: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse + 117, // 192: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse + 120, // 193: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse + 122, // 194: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse + 129, // 195: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:output_type -> hyapp.activity.v1.CheckLuckyGiftResponse + 132, // 196: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:output_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawResponse + 33, // 197: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse + 36, // 198: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 36, // 199: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 38, // 200: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse + 39, // 201: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse + 41, // 202: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse + 44, // 203: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse + 46, // 204: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse + 48, // 205: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse + 53, // 206: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse + 55, // 207: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse + 57, // 208: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse + 59, // 209: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse + 61, // 210: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse + 67, // 211: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:output_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusResponse + 69, // 212: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:output_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardResponse + 71, // 213: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigResponse + 73, // 214: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse + 75, // 215: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:output_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse + 80, // 216: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse + 82, // 217: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse + 84, // 218: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse + 86, // 219: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse + 89, // 220: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse + 110, // 221: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse + 104, // 222: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse + 106, // 223: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse + 108, // 224: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse + 115, // 225: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse + 124, // 226: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse + 134, // 227: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:output_type -> hyapp.activity.v1.GetLuckyGiftConfigResponse + 136, // 228: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:output_type -> hyapp.activity.v1.UpsertLuckyGiftConfigResponse + 138, // 229: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:output_type -> hyapp.activity.v1.ListLuckyGiftConfigsResponse + 140, // 230: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:output_type -> hyapp.activity.v1.ListLuckyGiftDrawsResponse + 172, // [172:231] is the sub-list for method output_type + 113, // [113:172] is the sub-list for method input_type + 113, // [113:113] is the sub-list for extension type_name + 113, // [113:113] is the sub-list for extension extendee + 0, // [0:113] is the sub-list for field type_name } func init() { file_proto_activity_v1_activity_proto_init() } @@ -11754,9 +12948,9 @@ func file_proto_activity_v1_activity_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_activity_v1_activity_proto_rawDesc), len(file_proto_activity_v1_activity_proto_rawDesc)), NumEnums: 0, - NumMessages: 127, + NumMessages: 141, NumExtensions: 0, - NumServices: 17, + NumServices: 19, }, GoTypes: file_proto_activity_v1_activity_proto_goTypes, DependencyIndexes: file_proto_activity_v1_activity_proto_depIdxs, diff --git a/api/proto/activity/v1/activity.proto b/api/proto/activity/v1/activity.proto index 6b18e8cc..284dc8e5 100644 --- a/api/proto/activity/v1/activity.proto +++ b/api/proto/activity/v1/activity.proto @@ -531,6 +531,122 @@ message ListRegistrationRewardClaimsResponse { int64 total = 2; } +// FirstRechargeRewardTier 是首冲奖励的一个金币充值档位;max_coin_amount=0 表示无上限。 +message FirstRechargeRewardTier { + int64 tier_id = 1; + string tier_code = 2; + string tier_name = 3; + int64 min_coin_amount = 4; + int64 max_coin_amount = 5; + int64 resource_group_id = 6; + string status = 7; + int32 sort_order = 8; + int64 created_at_ms = 9; + int64 updated_at_ms = 10; +} + +// FirstRechargeRewardConfig 是当前 App 的首冲奖励配置;档位内容在 activity-service 内保持版本一致。 +message FirstRechargeRewardConfig { + string app_code = 1; + bool enabled = 2; + repeated FirstRechargeRewardTier tiers = 3; + int64 updated_by_admin_id = 4; + int64 created_at_ms = 5; + int64 updated_at_ms = 6; +} + +// FirstRechargeRewardClaim 是某个用户首笔充值触发后的发奖事实;user_id 唯一保证一生只处理一次。 +message FirstRechargeRewardClaim { + string claim_id = 1; + string event_id = 2; + string transaction_id = 3; + string command_id = 4; + int64 user_id = 5; + int64 tier_id = 6; + string tier_code = 7; + int64 resource_group_id = 8; + int64 recharge_coin_amount = 9; + int64 recharge_sequence = 10; + string recharge_type = 11; + string status = 12; + string wallet_command_id = 13; + string wallet_grant_id = 14; + string failure_reason = 15; + int64 recharged_at_ms = 16; + int64 granted_at_ms = 17; + int64 created_at_ms = 18; + int64 updated_at_ms = 19; +} + +// FirstRechargeRewardStatus 是 App 首冲奖励面板可直接展示的当前状态。 +message FirstRechargeRewardStatus { + bool enabled = 1; + repeated FirstRechargeRewardTier tiers = 2; + bool rewarded = 3; + FirstRechargeRewardClaim claim = 4; + int64 server_time_ms = 5; +} + +message GetFirstRechargeRewardStatusRequest { + RequestMeta meta = 1; + int64 user_id = 2; +} + +message GetFirstRechargeRewardStatusResponse { + FirstRechargeRewardStatus status = 1; +} + +// ConsumeFirstRechargeRewardRequest 是 wallet 充值事实消费入口;只处理 recharge_sequence=1 的成功充值。 +message ConsumeFirstRechargeRewardRequest { + RequestMeta meta = 1; + string event_id = 2; + string transaction_id = 3; + string command_id = 4; + int64 user_id = 5; + int64 recharge_coin_amount = 6; + int64 recharge_sequence = 7; + string recharge_type = 8; + int64 occurred_at_ms = 9; +} + +message ConsumeFirstRechargeRewardResponse { + FirstRechargeRewardClaim claim = 1; + bool consumed = 2; + string reason = 3; +} + +message GetFirstRechargeRewardConfigRequest { + RequestMeta meta = 1; +} + +message GetFirstRechargeRewardConfigResponse { + FirstRechargeRewardConfig config = 1; +} + +message UpdateFirstRechargeRewardConfigRequest { + RequestMeta meta = 1; + bool enabled = 2; + repeated FirstRechargeRewardTier tiers = 3; + int64 operator_admin_id = 4; +} + +message UpdateFirstRechargeRewardConfigResponse { + FirstRechargeRewardConfig config = 1; +} + +message ListFirstRechargeRewardClaimsRequest { + RequestMeta meta = 1; + string status = 2; + int64 user_id = 3; + int32 page = 4; + int32 page_size = 5; +} + +message ListFirstRechargeRewardClaimsResponse { + repeated FirstRechargeRewardClaim claims = 1; + int64 total = 2; +} + // SevenDayCheckInReward 是七日签到配置中某一天的资源组奖励。 message SevenDayCheckInReward { int32 day_index = 1; @@ -1243,6 +1359,19 @@ service AdminRegistrationRewardService { rpc ListRegistrationRewardClaims(ListRegistrationRewardClaimsRequest) returns (ListRegistrationRewardClaimsResponse); } +// FirstRechargeRewardService 拥有 App 首冲奖励查询和 wallet 充值事实消费入口。 +service FirstRechargeRewardService { + rpc GetFirstRechargeRewardStatus(GetFirstRechargeRewardStatusRequest) returns (GetFirstRechargeRewardStatusResponse); + rpc ConsumeFirstRechargeReward(ConsumeFirstRechargeRewardRequest) returns (ConsumeFirstRechargeRewardResponse); +} + +// AdminFirstRechargeRewardService 是后台活动管理访问首冲奖励配置和发放记录的唯一入口。 +service AdminFirstRechargeRewardService { + rpc GetFirstRechargeRewardConfig(GetFirstRechargeRewardConfigRequest) returns (GetFirstRechargeRewardConfigResponse); + rpc UpdateFirstRechargeRewardConfig(UpdateFirstRechargeRewardConfigRequest) returns (UpdateFirstRechargeRewardConfigResponse); + rpc ListFirstRechargeRewardClaims(ListFirstRechargeRewardClaimsRequest) returns (ListFirstRechargeRewardClaimsResponse); +} + // SevenDayCheckInService 拥有 App 七日签到查询和签到命令。 service SevenDayCheckInService { rpc GetSevenDayCheckInStatus(GetSevenDayCheckInStatusRequest) returns (GetSevenDayCheckInStatusResponse); diff --git a/api/proto/activity/v1/activity_grpc.pb.go b/api/proto/activity/v1/activity_grpc.pb.go index 3e67207b..8eb91683 100644 --- a/api/proto/activity/v1/activity_grpc.pb.go +++ b/api/proto/activity/v1/activity_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.6.2 -// - protoc (unknown) +// - protoc v4.25.3 // source: proto/activity/v1/activity.proto package activityv1 @@ -2319,6 +2319,334 @@ var AdminRegistrationRewardService_ServiceDesc = grpc.ServiceDesc{ Metadata: "proto/activity/v1/activity.proto", } +const ( + FirstRechargeRewardService_GetFirstRechargeRewardStatus_FullMethodName = "/hyapp.activity.v1.FirstRechargeRewardService/GetFirstRechargeRewardStatus" + FirstRechargeRewardService_ConsumeFirstRechargeReward_FullMethodName = "/hyapp.activity.v1.FirstRechargeRewardService/ConsumeFirstRechargeReward" +) + +// FirstRechargeRewardServiceClient is the client API for FirstRechargeRewardService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// FirstRechargeRewardService 拥有 App 首冲奖励查询和 wallet 充值事实消费入口。 +type FirstRechargeRewardServiceClient interface { + GetFirstRechargeRewardStatus(ctx context.Context, in *GetFirstRechargeRewardStatusRequest, opts ...grpc.CallOption) (*GetFirstRechargeRewardStatusResponse, error) + ConsumeFirstRechargeReward(ctx context.Context, in *ConsumeFirstRechargeRewardRequest, opts ...grpc.CallOption) (*ConsumeFirstRechargeRewardResponse, error) +} + +type firstRechargeRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewFirstRechargeRewardServiceClient(cc grpc.ClientConnInterface) FirstRechargeRewardServiceClient { + return &firstRechargeRewardServiceClient{cc} +} + +func (c *firstRechargeRewardServiceClient) GetFirstRechargeRewardStatus(ctx context.Context, in *GetFirstRechargeRewardStatusRequest, opts ...grpc.CallOption) (*GetFirstRechargeRewardStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetFirstRechargeRewardStatusResponse) + err := c.cc.Invoke(ctx, FirstRechargeRewardService_GetFirstRechargeRewardStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *firstRechargeRewardServiceClient) ConsumeFirstRechargeReward(ctx context.Context, in *ConsumeFirstRechargeRewardRequest, opts ...grpc.CallOption) (*ConsumeFirstRechargeRewardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ConsumeFirstRechargeRewardResponse) + err := c.cc.Invoke(ctx, FirstRechargeRewardService_ConsumeFirstRechargeReward_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// FirstRechargeRewardServiceServer is the server API for FirstRechargeRewardService service. +// All implementations must embed UnimplementedFirstRechargeRewardServiceServer +// for forward compatibility. +// +// FirstRechargeRewardService 拥有 App 首冲奖励查询和 wallet 充值事实消费入口。 +type FirstRechargeRewardServiceServer interface { + GetFirstRechargeRewardStatus(context.Context, *GetFirstRechargeRewardStatusRequest) (*GetFirstRechargeRewardStatusResponse, error) + ConsumeFirstRechargeReward(context.Context, *ConsumeFirstRechargeRewardRequest) (*ConsumeFirstRechargeRewardResponse, error) + mustEmbedUnimplementedFirstRechargeRewardServiceServer() +} + +// UnimplementedFirstRechargeRewardServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedFirstRechargeRewardServiceServer struct{} + +func (UnimplementedFirstRechargeRewardServiceServer) GetFirstRechargeRewardStatus(context.Context, *GetFirstRechargeRewardStatusRequest) (*GetFirstRechargeRewardStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetFirstRechargeRewardStatus not implemented") +} +func (UnimplementedFirstRechargeRewardServiceServer) ConsumeFirstRechargeReward(context.Context, *ConsumeFirstRechargeRewardRequest) (*ConsumeFirstRechargeRewardResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ConsumeFirstRechargeReward not implemented") +} +func (UnimplementedFirstRechargeRewardServiceServer) mustEmbedUnimplementedFirstRechargeRewardServiceServer() { +} +func (UnimplementedFirstRechargeRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeFirstRechargeRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to FirstRechargeRewardServiceServer will +// result in compilation errors. +type UnsafeFirstRechargeRewardServiceServer interface { + mustEmbedUnimplementedFirstRechargeRewardServiceServer() +} + +func RegisterFirstRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv FirstRechargeRewardServiceServer) { + // If the following call panics, it indicates UnimplementedFirstRechargeRewardServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&FirstRechargeRewardService_ServiceDesc, srv) +} + +func _FirstRechargeRewardService_GetFirstRechargeRewardStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFirstRechargeRewardStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FirstRechargeRewardServiceServer).GetFirstRechargeRewardStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FirstRechargeRewardService_GetFirstRechargeRewardStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FirstRechargeRewardServiceServer).GetFirstRechargeRewardStatus(ctx, req.(*GetFirstRechargeRewardStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _FirstRechargeRewardService_ConsumeFirstRechargeReward_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConsumeFirstRechargeRewardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(FirstRechargeRewardServiceServer).ConsumeFirstRechargeReward(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: FirstRechargeRewardService_ConsumeFirstRechargeReward_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(FirstRechargeRewardServiceServer).ConsumeFirstRechargeReward(ctx, req.(*ConsumeFirstRechargeRewardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// FirstRechargeRewardService_ServiceDesc is the grpc.ServiceDesc for FirstRechargeRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var FirstRechargeRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.FirstRechargeRewardService", + HandlerType: (*FirstRechargeRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFirstRechargeRewardStatus", + Handler: _FirstRechargeRewardService_GetFirstRechargeRewardStatus_Handler, + }, + { + MethodName: "ConsumeFirstRechargeReward", + Handler: _FirstRechargeRewardService_ConsumeFirstRechargeReward_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + +const ( + AdminFirstRechargeRewardService_GetFirstRechargeRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminFirstRechargeRewardService/GetFirstRechargeRewardConfig" + AdminFirstRechargeRewardService_UpdateFirstRechargeRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminFirstRechargeRewardService/UpdateFirstRechargeRewardConfig" + AdminFirstRechargeRewardService_ListFirstRechargeRewardClaims_FullMethodName = "/hyapp.activity.v1.AdminFirstRechargeRewardService/ListFirstRechargeRewardClaims" +) + +// AdminFirstRechargeRewardServiceClient is the client API for AdminFirstRechargeRewardService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// AdminFirstRechargeRewardService 是后台活动管理访问首冲奖励配置和发放记录的唯一入口。 +type AdminFirstRechargeRewardServiceClient interface { + GetFirstRechargeRewardConfig(ctx context.Context, in *GetFirstRechargeRewardConfigRequest, opts ...grpc.CallOption) (*GetFirstRechargeRewardConfigResponse, error) + UpdateFirstRechargeRewardConfig(ctx context.Context, in *UpdateFirstRechargeRewardConfigRequest, opts ...grpc.CallOption) (*UpdateFirstRechargeRewardConfigResponse, error) + ListFirstRechargeRewardClaims(ctx context.Context, in *ListFirstRechargeRewardClaimsRequest, opts ...grpc.CallOption) (*ListFirstRechargeRewardClaimsResponse, error) +} + +type adminFirstRechargeRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAdminFirstRechargeRewardServiceClient(cc grpc.ClientConnInterface) AdminFirstRechargeRewardServiceClient { + return &adminFirstRechargeRewardServiceClient{cc} +} + +func (c *adminFirstRechargeRewardServiceClient) GetFirstRechargeRewardConfig(ctx context.Context, in *GetFirstRechargeRewardConfigRequest, opts ...grpc.CallOption) (*GetFirstRechargeRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetFirstRechargeRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminFirstRechargeRewardService_GetFirstRechargeRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminFirstRechargeRewardServiceClient) UpdateFirstRechargeRewardConfig(ctx context.Context, in *UpdateFirstRechargeRewardConfigRequest, opts ...grpc.CallOption) (*UpdateFirstRechargeRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateFirstRechargeRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminFirstRechargeRewardService_UpdateFirstRechargeRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminFirstRechargeRewardServiceClient) ListFirstRechargeRewardClaims(ctx context.Context, in *ListFirstRechargeRewardClaimsRequest, opts ...grpc.CallOption) (*ListFirstRechargeRewardClaimsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListFirstRechargeRewardClaimsResponse) + err := c.cc.Invoke(ctx, AdminFirstRechargeRewardService_ListFirstRechargeRewardClaims_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AdminFirstRechargeRewardServiceServer is the server API for AdminFirstRechargeRewardService service. +// All implementations must embed UnimplementedAdminFirstRechargeRewardServiceServer +// for forward compatibility. +// +// AdminFirstRechargeRewardService 是后台活动管理访问首冲奖励配置和发放记录的唯一入口。 +type AdminFirstRechargeRewardServiceServer interface { + GetFirstRechargeRewardConfig(context.Context, *GetFirstRechargeRewardConfigRequest) (*GetFirstRechargeRewardConfigResponse, error) + UpdateFirstRechargeRewardConfig(context.Context, *UpdateFirstRechargeRewardConfigRequest) (*UpdateFirstRechargeRewardConfigResponse, error) + ListFirstRechargeRewardClaims(context.Context, *ListFirstRechargeRewardClaimsRequest) (*ListFirstRechargeRewardClaimsResponse, error) + mustEmbedUnimplementedAdminFirstRechargeRewardServiceServer() +} + +// UnimplementedAdminFirstRechargeRewardServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAdminFirstRechargeRewardServiceServer struct{} + +func (UnimplementedAdminFirstRechargeRewardServiceServer) GetFirstRechargeRewardConfig(context.Context, *GetFirstRechargeRewardConfigRequest) (*GetFirstRechargeRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetFirstRechargeRewardConfig not implemented") +} +func (UnimplementedAdminFirstRechargeRewardServiceServer) UpdateFirstRechargeRewardConfig(context.Context, *UpdateFirstRechargeRewardConfigRequest) (*UpdateFirstRechargeRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateFirstRechargeRewardConfig not implemented") +} +func (UnimplementedAdminFirstRechargeRewardServiceServer) ListFirstRechargeRewardClaims(context.Context, *ListFirstRechargeRewardClaimsRequest) (*ListFirstRechargeRewardClaimsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListFirstRechargeRewardClaims not implemented") +} +func (UnimplementedAdminFirstRechargeRewardServiceServer) mustEmbedUnimplementedAdminFirstRechargeRewardServiceServer() { +} +func (UnimplementedAdminFirstRechargeRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeAdminFirstRechargeRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AdminFirstRechargeRewardServiceServer will +// result in compilation errors. +type UnsafeAdminFirstRechargeRewardServiceServer interface { + mustEmbedUnimplementedAdminFirstRechargeRewardServiceServer() +} + +func RegisterAdminFirstRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv AdminFirstRechargeRewardServiceServer) { + // If the following call panics, it indicates UnimplementedAdminFirstRechargeRewardServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AdminFirstRechargeRewardService_ServiceDesc, srv) +} + +func _AdminFirstRechargeRewardService_GetFirstRechargeRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFirstRechargeRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminFirstRechargeRewardServiceServer).GetFirstRechargeRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminFirstRechargeRewardService_GetFirstRechargeRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminFirstRechargeRewardServiceServer).GetFirstRechargeRewardConfig(ctx, req.(*GetFirstRechargeRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminFirstRechargeRewardService_UpdateFirstRechargeRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateFirstRechargeRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminFirstRechargeRewardServiceServer).UpdateFirstRechargeRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminFirstRechargeRewardService_UpdateFirstRechargeRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminFirstRechargeRewardServiceServer).UpdateFirstRechargeRewardConfig(ctx, req.(*UpdateFirstRechargeRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminFirstRechargeRewardService_ListFirstRechargeRewardClaims_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListFirstRechargeRewardClaimsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminFirstRechargeRewardServiceServer).ListFirstRechargeRewardClaims(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminFirstRechargeRewardService_ListFirstRechargeRewardClaims_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminFirstRechargeRewardServiceServer).ListFirstRechargeRewardClaims(ctx, req.(*ListFirstRechargeRewardClaimsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AdminFirstRechargeRewardService_ServiceDesc is the grpc.ServiceDesc for AdminFirstRechargeRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AdminFirstRechargeRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.AdminFirstRechargeRewardService", + HandlerType: (*AdminFirstRechargeRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetFirstRechargeRewardConfig", + Handler: _AdminFirstRechargeRewardService_GetFirstRechargeRewardConfig_Handler, + }, + { + MethodName: "UpdateFirstRechargeRewardConfig", + Handler: _AdminFirstRechargeRewardService_UpdateFirstRechargeRewardConfig_Handler, + }, + { + MethodName: "ListFirstRechargeRewardClaims", + Handler: _AdminFirstRechargeRewardService_ListFirstRechargeRewardClaims_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + const ( SevenDayCheckInService_GetSevenDayCheckInStatus_FullMethodName = "/hyapp.activity.v1.SevenDayCheckInService/GetSevenDayCheckInStatus" SevenDayCheckInService_SignSevenDayCheckIn_FullMethodName = "/hyapp.activity.v1.SevenDayCheckInService/SignSevenDayCheckIn" diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index ab3a1793..e340a694 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -34,6 +34,7 @@ import ( countryregionmodule "hyapp-admin-server/internal/modules/countryregion" dailytaskmodule "hyapp-admin-server/internal/modules/dailytask" dashboardmodule "hyapp-admin-server/internal/modules/dashboard" + firstrechargerewardmodule "hyapp-admin-server/internal/modules/firstrechargereward" gamemanagementmodule "hyapp-admin-server/internal/modules/gamemanagement" healthmodule "hyapp-admin-server/internal/modules/health" hostorgmodule "hyapp-admin-server/internal/modules/hostorg" @@ -210,35 +211,36 @@ func main() { objectUploader = uploader } handlers := router.Handlers{ - Audit: auditHandler, - Auth: authmodule.New(store, auth, auditHandler, cfg), - AdminUser: adminusermodule.New(store, cfg, auditHandler), - AchievementConfig: achievementconfigmodule.New(activityclient.NewGRPC(activityConn), auditHandler), - AppConfig: appconfigmodule.New(store, auditHandler), - AppRegistry: appregistrymodule.New(userDB), - AppUser: appusermodule.New(userclient.NewGRPC(userConn), activityclient.NewGRPC(activityConn), sqlDB, userDB, walletDB, cfg, auditHandler), - CoinLedger: coinledgermodule.New(userDB, walletDB, sqlDB, walletclient.NewGRPC(walletConn), auditHandler), - CountryRegion: countryregionmodule.New(userclient.NewGRPC(userConn), userDB, cfg, auditHandler), - DailyTask: dailytaskmodule.New(activityclient.NewGRPC(activityConn), auditHandler), - Dashboard: dashboardmodule.New(store), - Game: gamemanagementmodule.New(gameclient.NewGRPC(gameConn), auditHandler), - Health: healthmodule.New(store, redisClient, jobStatus), - HostOrg: hostorgmodule.New(userclient.NewGRPC(userConn), walletclient.NewGRPC(walletConn), userDB, walletDB, sqlDB, auditHandler), - Job: jobmodule.New(store, cfg, auditHandler), - LevelConfig: levelconfigmodule.New(activityclient.NewGRPC(activityConn), auditHandler), - LuckyGift: luckygiftmodule.New(activityclient.NewGRPC(activityConn), auditHandler), - Menu: menumodule.New(store, auditHandler), - Payment: paymentmodule.New(walletclient.NewGRPC(walletConn), auditHandler), - RBAC: rbacmodule.New(store, auditHandler), - RegistrationReward: registrationrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), - RegionBlock: regionblockmodule.New(userDB, auditHandler), - Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, auditHandler), - RoomAdmin: roomadminmodule.New(roomDB, userDB, roomclient.NewGRPC(roomConn), auditHandler), - RoomTreasure: roomtreasuremodule.New(roomDB, auditHandler), - Search: searchmodule.New(store), - SevenDayCheckIn: sevendaycheckinmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), - Upload: uploadmodule.New(objectUploader, cfg.TencentCOS.ObjectPrefix, auditHandler), - UserLeaderboard: userleaderboardmodule.New(walletDB, userDB, roomDB), + Audit: auditHandler, + Auth: authmodule.New(store, auth, auditHandler, cfg), + AdminUser: adminusermodule.New(store, cfg, auditHandler), + AchievementConfig: achievementconfigmodule.New(activityclient.NewGRPC(activityConn), auditHandler), + AppConfig: appconfigmodule.New(store, auditHandler), + AppRegistry: appregistrymodule.New(userDB), + AppUser: appusermodule.New(userclient.NewGRPC(userConn), activityclient.NewGRPC(activityConn), sqlDB, userDB, walletDB, cfg, auditHandler), + CoinLedger: coinledgermodule.New(userDB, walletDB, sqlDB, walletclient.NewGRPC(walletConn), auditHandler), + CountryRegion: countryregionmodule.New(userclient.NewGRPC(userConn), userDB, cfg, auditHandler), + DailyTask: dailytaskmodule.New(activityclient.NewGRPC(activityConn), auditHandler), + Dashboard: dashboardmodule.New(store), + FirstRechargeReward: firstrechargerewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), + Game: gamemanagementmodule.New(gameclient.NewGRPC(gameConn), auditHandler), + Health: healthmodule.New(store, redisClient, jobStatus), + HostOrg: hostorgmodule.New(userclient.NewGRPC(userConn), walletclient.NewGRPC(walletConn), userDB, walletDB, sqlDB, auditHandler), + Job: jobmodule.New(store, cfg, auditHandler), + LevelConfig: levelconfigmodule.New(activityclient.NewGRPC(activityConn), auditHandler), + LuckyGift: luckygiftmodule.New(activityclient.NewGRPC(activityConn), auditHandler), + Menu: menumodule.New(store, auditHandler), + Payment: paymentmodule.New(walletclient.NewGRPC(walletConn), auditHandler), + RBAC: rbacmodule.New(store, auditHandler), + RegistrationReward: registrationrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), + RegionBlock: regionblockmodule.New(userDB, auditHandler), + Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, auditHandler), + RoomAdmin: roomadminmodule.New(roomDB, userDB, roomclient.NewGRPC(roomConn), auditHandler), + RoomTreasure: roomtreasuremodule.New(roomDB, auditHandler), + Search: searchmodule.New(store), + SevenDayCheckIn: sevendaycheckinmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), + Upload: uploadmodule.New(objectUploader, cfg.TencentCOS.ObjectPrefix, auditHandler), + UserLeaderboard: userleaderboardmodule.New(walletDB, userDB, roomDB), } engine := router.New(cfg, auth, handlers) diff --git a/server/admin/internal/integration/activityclient/client.go b/server/admin/internal/integration/activityclient/client.go index a3de8b6e..0b416fec 100644 --- a/server/admin/internal/integration/activityclient/client.go +++ b/server/admin/internal/integration/activityclient/client.go @@ -18,6 +18,9 @@ type Client interface { GetRegistrationRewardConfig(ctx context.Context, req *activityv1.GetRegistrationRewardConfigRequest) (*activityv1.GetRegistrationRewardConfigResponse, error) UpdateRegistrationRewardConfig(ctx context.Context, req *activityv1.UpdateRegistrationRewardConfigRequest) (*activityv1.UpdateRegistrationRewardConfigResponse, error) ListRegistrationRewardClaims(ctx context.Context, req *activityv1.ListRegistrationRewardClaimsRequest) (*activityv1.ListRegistrationRewardClaimsResponse, error) + GetFirstRechargeRewardConfig(ctx context.Context, req *activityv1.GetFirstRechargeRewardConfigRequest) (*activityv1.GetFirstRechargeRewardConfigResponse, error) + UpdateFirstRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateFirstRechargeRewardConfigRequest) (*activityv1.UpdateFirstRechargeRewardConfigResponse, error) + ListFirstRechargeRewardClaims(ctx context.Context, req *activityv1.ListFirstRechargeRewardClaimsRequest) (*activityv1.ListFirstRechargeRewardClaimsResponse, error) GetSevenDayCheckInConfig(ctx context.Context, req *activityv1.GetSevenDayCheckInConfigRequest) (*activityv1.GetSevenDayCheckInConfigResponse, error) UpdateSevenDayCheckInConfig(ctx context.Context, req *activityv1.UpdateSevenDayCheckInConfigRequest) (*activityv1.UpdateSevenDayCheckInConfigResponse, error) ListSevenDayCheckInClaims(ctx context.Context, req *activityv1.ListSevenDayCheckInClaimsRequest) (*activityv1.ListSevenDayCheckInClaimsResponse, error) @@ -33,24 +36,26 @@ type Client interface { } type GRPCClient struct { - taskClient activityv1.AdminTaskServiceClient - achievementClient activityv1.AdminAchievementServiceClient - registrationRewardClient activityv1.AdminRegistrationRewardServiceClient - sevenDayCheckInClient activityv1.AdminSevenDayCheckInServiceClient - luckyGiftClient activityv1.AdminLuckyGiftServiceClient - broadcastClient activityv1.BroadcastServiceClient - growthClient activityv1.AdminGrowthLevelServiceClient + taskClient activityv1.AdminTaskServiceClient + achievementClient activityv1.AdminAchievementServiceClient + registrationRewardClient activityv1.AdminRegistrationRewardServiceClient + firstRechargeRewardClient activityv1.AdminFirstRechargeRewardServiceClient + sevenDayCheckInClient activityv1.AdminSevenDayCheckInServiceClient + luckyGiftClient activityv1.AdminLuckyGiftServiceClient + broadcastClient activityv1.BroadcastServiceClient + growthClient activityv1.AdminGrowthLevelServiceClient } func NewGRPC(conn grpc.ClientConnInterface) *GRPCClient { return &GRPCClient{ - taskClient: activityv1.NewAdminTaskServiceClient(conn), - achievementClient: activityv1.NewAdminAchievementServiceClient(conn), - registrationRewardClient: activityv1.NewAdminRegistrationRewardServiceClient(conn), - sevenDayCheckInClient: activityv1.NewAdminSevenDayCheckInServiceClient(conn), - luckyGiftClient: activityv1.NewAdminLuckyGiftServiceClient(conn), - broadcastClient: activityv1.NewBroadcastServiceClient(conn), - growthClient: activityv1.NewAdminGrowthLevelServiceClient(conn), + taskClient: activityv1.NewAdminTaskServiceClient(conn), + achievementClient: activityv1.NewAdminAchievementServiceClient(conn), + registrationRewardClient: activityv1.NewAdminRegistrationRewardServiceClient(conn), + firstRechargeRewardClient: activityv1.NewAdminFirstRechargeRewardServiceClient(conn), + sevenDayCheckInClient: activityv1.NewAdminSevenDayCheckInServiceClient(conn), + luckyGiftClient: activityv1.NewAdminLuckyGiftServiceClient(conn), + broadcastClient: activityv1.NewBroadcastServiceClient(conn), + growthClient: activityv1.NewAdminGrowthLevelServiceClient(conn), } } @@ -86,6 +91,18 @@ func (c *GRPCClient) ListRegistrationRewardClaims(ctx context.Context, req *acti return c.registrationRewardClient.ListRegistrationRewardClaims(ctx, req) } +func (c *GRPCClient) GetFirstRechargeRewardConfig(ctx context.Context, req *activityv1.GetFirstRechargeRewardConfigRequest) (*activityv1.GetFirstRechargeRewardConfigResponse, error) { + return c.firstRechargeRewardClient.GetFirstRechargeRewardConfig(ctx, req) +} + +func (c *GRPCClient) UpdateFirstRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateFirstRechargeRewardConfigRequest) (*activityv1.UpdateFirstRechargeRewardConfigResponse, error) { + return c.firstRechargeRewardClient.UpdateFirstRechargeRewardConfig(ctx, req) +} + +func (c *GRPCClient) ListFirstRechargeRewardClaims(ctx context.Context, req *activityv1.ListFirstRechargeRewardClaimsRequest) (*activityv1.ListFirstRechargeRewardClaimsResponse, error) { + return c.firstRechargeRewardClient.ListFirstRechargeRewardClaims(ctx, req) +} + func (c *GRPCClient) GetSevenDayCheckInConfig(ctx context.Context, req *activityv1.GetSevenDayCheckInConfigRequest) (*activityv1.GetSevenDayCheckInConfigResponse, error) { return c.sevenDayCheckInClient.GetSevenDayCheckInConfig(ctx, req) } diff --git a/server/admin/internal/modules/firstrechargereward/handler.go b/server/admin/internal/modules/firstrechargereward/handler.go new file mode 100644 index 00000000..1436aa13 --- /dev/null +++ b/server/admin/internal/modules/firstrechargereward/handler.go @@ -0,0 +1,348 @@ +package firstrechargereward + +import ( + "context" + "database/sql" + "strings" + "time" + + "hyapp-admin-server/internal/appctx" + "hyapp-admin-server/internal/integration/activityclient" + "hyapp-admin-server/internal/middleware" + "hyapp-admin-server/internal/modules/shared" + "hyapp-admin-server/internal/response" + activityv1 "hyapp.local/api/proto/activity/v1" + + "github.com/gin-gonic/gin" +) + +type Handler struct { + activity activityclient.Client + userDB *sql.DB + audit shared.OperationLogger +} + +func New(activity activityclient.Client, userDB *sql.DB, audit shared.OperationLogger) *Handler { + return &Handler{activity: activity, userDB: userDB, audit: audit} +} + +type configRequest struct { + Enabled bool `json:"enabled"` + Tiers []tierDTO `json:"tiers"` +} + +type configDTO struct { + AppCode string `json:"app_code"` + Enabled bool `json:"enabled"` + Tiers []tierDTO `json:"tiers"` + UpdatedByAdminID int64 `json:"updated_by_admin_id"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type tierDTO struct { + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + TierName string `json:"tier_name"` + MinCoinAmount int64 `json:"min_coin_amount"` + MaxCoinAmount int64 `json:"max_coin_amount"` + ResourceGroupID int64 `json:"resource_group_id"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type claimDTO struct { + ClaimID string `json:"claim_id"` + EventID string `json:"event_id"` + TransactionID string `json:"transaction_id"` + CommandID string `json:"command_id"` + UserID int64 `json:"user_id"` + User *userDTO `json:"user,omitempty"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ResourceGroupID int64 `json:"resource_group_id"` + RechargeCoinAmount int64 `json:"recharge_coin_amount"` + RechargeSequence int64 `json:"recharge_sequence"` + RechargeType string `json:"recharge_type"` + Status string `json:"status"` + WalletCommandID string `json:"wallet_command_id"` + WalletGrantID string `json:"wallet_grant_id"` + FailureReason string `json:"failure_reason"` + RechargedAtMS int64 `json:"recharged_at_ms"` + GrantedAtMS int64 `json:"granted_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type userDTO struct { + UserID int64 `json:"user_id"` + DisplayUserID string `json:"display_user_id"` + Username string `json:"username"` + Avatar string `json:"avatar"` +} + +func (h *Handler) GetConfig(c *gin.Context) { + resp, err := h.activity.GetFirstRechargeRewardConfig(c.Request.Context(), &activityv1.GetFirstRechargeRewardConfigRequest{Meta: h.meta(c)}) + if err != nil { + response.ServerError(c, "获取首冲奖励配置失败") + return + } + response.OK(c, configFromProto(resp.GetConfig())) +} + +func (h *Handler) UpdateConfig(c *gin.Context) { + var req configRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "首冲奖励配置参数不正确") + return + } + tiers := make([]*activityv1.FirstRechargeRewardTier, 0, len(req.Tiers)) + for _, tier := range req.Tiers { + tiers = append(tiers, &activityv1.FirstRechargeRewardTier{ + TierId: tier.TierID, + TierCode: strings.TrimSpace(tier.TierCode), + TierName: strings.TrimSpace(tier.TierName), + MinCoinAmount: tier.MinCoinAmount, + MaxCoinAmount: tier.MaxCoinAmount, + ResourceGroupId: tier.ResourceGroupID, + Status: strings.TrimSpace(tier.Status), + SortOrder: tier.SortOrder, + }) + } + resp, err := h.activity.UpdateFirstRechargeRewardConfig(c.Request.Context(), &activityv1.UpdateFirstRechargeRewardConfigRequest{ + Meta: h.meta(c), + Enabled: req.Enabled, + Tiers: tiers, + OperatorAdminId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + item := configFromProto(resp.GetConfig()) + shared.OperationLogWithResourceID(c, h.audit, "update-first-recharge-reward", "first_recharge_reward_configs", item.AppCode, "success", "") + response.OK(c, item) +} + +func (h *Handler) ListClaims(c *gin.Context) { + options := shared.ListOptions(c) + userID, matched, ok := h.resolveClaimUserID(c.Request.Context(), strings.TrimSpace(options.Keyword)) + if !ok { + response.ServerError(c, "查询用户信息失败") + return + } + if options.Keyword != "" && !matched { + response.OK(c, response.Page{Items: []claimDTO{}, Page: options.Page, PageSize: options.PageSize, Total: 0}) + return + } + resp, err := h.activity.ListFirstRechargeRewardClaims(c.Request.Context(), &activityv1.ListFirstRechargeRewardClaimsRequest{ + Meta: h.meta(c), + Status: strings.TrimSpace(options.Status), + UserId: userID, + Page: int32(options.Page), + PageSize: int32(options.PageSize), + }) + if err != nil { + response.ServerError(c, "获取首冲奖励发放记录失败") + return + } + items := make([]claimDTO, 0, len(resp.GetClaims())) + for _, claim := range resp.GetClaims() { + items = append(items, claimFromProto(claim)) + } + if err := h.fillClaimUsers(c.Request.Context(), items); err != nil { + response.ServerError(c, "补全用户信息失败") + return + } + response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) +} + +func (h *Handler) meta(c *gin.Context) *activityv1.RequestMeta { + return &activityv1.RequestMeta{ + RequestId: middleware.CurrentRequestID(c), + Caller: "admin-server", + AppCode: appctx.FromContext(c.Request.Context()), + SentAtMs: time.Now().UnixMilli(), + } +} + +func (h *Handler) resolveClaimUserID(ctx context.Context, keyword string) (int64, bool, bool) { + if keyword == "" { + return 0, false, true + } + if h.userDB == nil { + return 0, false, true + } + appCode := appctx.FromContext(ctx) + rows, err := h.userDB.QueryContext(ctx, ` + SELECT user_id + FROM users + WHERE app_code = ? + AND ( + CAST(user_id AS CHAR) = ? + OR current_display_user_id = ? + OR username LIKE ? + ) + ORDER BY + CASE + WHEN CAST(user_id AS CHAR) = ? THEN 0 + WHEN current_display_user_id = ? THEN 1 + ELSE 2 + END, + user_id DESC + LIMIT 1`, + appCode, keyword, keyword, "%"+keyword+"%", keyword, keyword, + ) + if err != nil { + return 0, false, false + } + defer rows.Close() + if !rows.Next() { + return 0, false, rows.Err() == nil + } + var userID int64 + if err := rows.Scan(&userID); err != nil { + return 0, false, false + } + return userID, true, rows.Err() == nil +} + +func (h *Handler) fillClaimUsers(ctx context.Context, claims []claimDTO) error { + if h.userDB == nil || len(claims) == 0 { + return nil + } + ids := collectClaimUserIDs(claims) + if len(ids) == 0 { + return nil + } + args := append([]any{appctx.FromContext(ctx)}, int64Args(ids)...) + rows, err := h.userDB.QueryContext(ctx, ` + SELECT user_id, current_display_user_id, COALESCE(username, ''), COALESCE(avatar, '') + FROM users + WHERE app_code = ? AND user_id IN (`+placeholders(len(ids))+`)`, + args..., + ) + if err != nil { + return err + } + defer rows.Close() + users := make(map[int64]userDTO, len(ids)) + for rows.Next() { + var user userDTO + if err := rows.Scan(&user.UserID, &user.DisplayUserID, &user.Username, &user.Avatar); err != nil { + return err + } + users[user.UserID] = user + } + if err := rows.Err(); err != nil { + return err + } + for index := range claims { + if user, ok := users[claims[index].UserID]; ok { + claims[index].User = &user + continue + } + claims[index].User = &userDTO{UserID: claims[index].UserID} + } + return nil +} + +func configFromProto(config *activityv1.FirstRechargeRewardConfig) configDTO { + if config == nil { + return configDTO{Tiers: []tierDTO{}} + } + tiers := make([]tierDTO, 0, len(config.GetTiers())) + for _, tier := range config.GetTiers() { + tiers = append(tiers, tierFromProto(tier)) + } + return configDTO{ + AppCode: config.GetAppCode(), + Enabled: config.GetEnabled(), + Tiers: tiers, + UpdatedByAdminID: config.GetUpdatedByAdminId(), + CreatedAtMS: config.GetCreatedAtMs(), + UpdatedAtMS: config.GetUpdatedAtMs(), + } +} + +func tierFromProto(tier *activityv1.FirstRechargeRewardTier) tierDTO { + if tier == nil { + return tierDTO{} + } + return tierDTO{ + TierID: tier.GetTierId(), + TierCode: tier.GetTierCode(), + TierName: tier.GetTierName(), + MinCoinAmount: tier.GetMinCoinAmount(), + MaxCoinAmount: tier.GetMaxCoinAmount(), + ResourceGroupID: tier.GetResourceGroupId(), + Status: tier.GetStatus(), + SortOrder: tier.GetSortOrder(), + CreatedAtMS: tier.GetCreatedAtMs(), + UpdatedAtMS: tier.GetUpdatedAtMs(), + } +} + +func claimFromProto(claim *activityv1.FirstRechargeRewardClaim) claimDTO { + if claim == nil { + return claimDTO{} + } + return claimDTO{ + ClaimID: claim.GetClaimId(), + EventID: claim.GetEventId(), + TransactionID: claim.GetTransactionId(), + CommandID: claim.GetCommandId(), + UserID: claim.GetUserId(), + TierID: claim.GetTierId(), + TierCode: claim.GetTierCode(), + ResourceGroupID: claim.GetResourceGroupId(), + RechargeCoinAmount: claim.GetRechargeCoinAmount(), + RechargeSequence: claim.GetRechargeSequence(), + RechargeType: claim.GetRechargeType(), + Status: claim.GetStatus(), + WalletCommandID: claim.GetWalletCommandId(), + WalletGrantID: claim.GetWalletGrantId(), + FailureReason: claim.GetFailureReason(), + RechargedAtMS: claim.GetRechargedAtMs(), + GrantedAtMS: claim.GetGrantedAtMs(), + CreatedAtMS: claim.GetCreatedAtMs(), + UpdatedAtMS: claim.GetUpdatedAtMs(), + } +} + +func collectClaimUserIDs(claims []claimDTO) []int64 { + seen := make(map[int64]struct{}, len(claims)) + ids := make([]int64, 0, len(claims)) + for _, claim := range claims { + if claim.UserID <= 0 { + continue + } + if _, ok := seen[claim.UserID]; ok { + continue + } + seen[claim.UserID] = struct{}{} + ids = append(ids, claim.UserID) + } + return ids +} + +func int64Args(ids []int64) []any { + args := make([]any, 0, len(ids)) + for _, id := range ids { + args = append(args, id) + } + return args +} + +func placeholders(count int) string { + if count <= 0 { + return "" + } + parts := make([]string, count) + for i := range parts { + parts[i] = "?" + } + return strings.Join(parts, ",") +} diff --git a/server/admin/internal/modules/firstrechargereward/routes.go b/server/admin/internal/modules/firstrechargereward/routes.go new file mode 100644 index 00000000..7e4a5ad7 --- /dev/null +++ b/server/admin/internal/modules/firstrechargereward/routes.go @@ -0,0 +1,16 @@ +package firstrechargereward + +import ( + "hyapp-admin-server/internal/middleware" + + "github.com/gin-gonic/gin" +) + +func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { + if h == nil { + return + } + protected.GET("/admin/activity/first-recharge-reward/config", middleware.RequirePermission("first-recharge-reward:view"), h.GetConfig) + protected.PUT("/admin/activity/first-recharge-reward/config", middleware.RequirePermission("first-recharge-reward:update"), h.UpdateConfig) + protected.GET("/admin/activity/first-recharge-reward/claims", middleware.RequirePermission("first-recharge-reward:view"), h.ListClaims) +} diff --git a/server/admin/internal/router/router.go b/server/admin/internal/router/router.go index 18f62ad9..f7ee5562 100644 --- a/server/admin/internal/router/router.go +++ b/server/admin/internal/router/router.go @@ -14,6 +14,7 @@ import ( "hyapp-admin-server/internal/modules/countryregion" "hyapp-admin-server/internal/modules/dailytask" "hyapp-admin-server/internal/modules/dashboard" + "hyapp-admin-server/internal/modules/firstrechargereward" gamemanagement "hyapp-admin-server/internal/modules/gamemanagement" "hyapp-admin-server/internal/modules/health" "hyapp-admin-server/internal/modules/hostorg" @@ -39,35 +40,36 @@ import ( ) type Handlers struct { - AdminUser *adminuser.Handler - AchievementConfig *achievementconfig.Handler - AppConfig *appconfig.Handler - AppRegistry *appregistry.Handler - AppUser *appuser.Handler - Audit *audit.Handler - Auth *authroutes.Handler - CoinLedger *coinledger.Handler - CountryRegion *countryregion.Handler - DailyTask *dailytask.Handler - Dashboard *dashboard.Handler - Game *gamemanagement.Handler - Health *health.Handler - HostOrg *hostorg.Handler - Job *job.Handler - LevelConfig *levelconfig.Handler - LuckyGift *luckygift.Handler - Menu *menu.Handler - Payment *payment.Handler - RBAC *rbac.Handler - RegistrationReward *registrationreward.Handler - RegionBlock *regionblock.Handler - Resource *resourcemodule.Handler - RoomAdmin *roomadmin.Handler - RoomTreasure *roomtreasure.Handler - Search *search.Handler - SevenDayCheckIn *sevendaycheckin.Handler - Upload *upload.Handler - UserLeaderboard *userleaderboard.Handler + AdminUser *adminuser.Handler + AchievementConfig *achievementconfig.Handler + AppConfig *appconfig.Handler + AppRegistry *appregistry.Handler + AppUser *appuser.Handler + Audit *audit.Handler + Auth *authroutes.Handler + CoinLedger *coinledger.Handler + CountryRegion *countryregion.Handler + DailyTask *dailytask.Handler + Dashboard *dashboard.Handler + FirstRechargeReward *firstrechargereward.Handler + Game *gamemanagement.Handler + Health *health.Handler + HostOrg *hostorg.Handler + Job *job.Handler + LevelConfig *levelconfig.Handler + LuckyGift *luckygift.Handler + Menu *menu.Handler + Payment *payment.Handler + RBAC *rbac.Handler + RegistrationReward *registrationreward.Handler + RegionBlock *regionblock.Handler + Resource *resourcemodule.Handler + RoomAdmin *roomadmin.Handler + RoomTreasure *roomtreasure.Handler + Search *search.Handler + SevenDayCheckIn *sevendaycheckin.Handler + Upload *upload.Handler + UserLeaderboard *userleaderboard.Handler } func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { @@ -93,6 +95,7 @@ func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { appconfig.RegisterRoutes(protected, h.AppConfig) countryregion.RegisterRoutes(protected, h.CountryRegion) dailytask.RegisterRoutes(protected, h.DailyTask) + firstrechargereward.RegisterRoutes(protected, h.FirstRechargeReward) registrationreward.RegisterRoutes(protected, h.RegistrationReward) regionblock.RegisterRoutes(protected, h.RegionBlock) gamemanagement.RegisterRoutes(protected, h.Game) diff --git a/server/admin/migrations/020_first_recharge_reward_navigation.sql b/server/admin/migrations/020_first_recharge_reward_navigation.sql new file mode 100644 index 00000000..9a5ddf6a --- /dev/null +++ b/server/admin/migrations/020_first_recharge_reward_navigation.sql @@ -0,0 +1,59 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 首冲奖励事实归 activity-service 所有,后台只维护开关、金额档位和资源组映射。 +SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +INSERT INTO admin_permissions (name, code, kind, description, created_at_ms, updated_at_ms) VALUES + ('首冲奖励查看', 'first-recharge-reward:view', 'menu', '', @now_ms, @now_ms), + ('首冲奖励更新', 'first-recharge-reward:update', 'button', '', @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + name = VALUES(name), + kind = VALUES(kind), + description = VALUES(description), + updated_at_ms = @now_ms; + +INSERT INTO admin_menus (parent_id, title, code, path, icon, permission_code, sort, visible, created_at_ms, updated_at_ms) VALUES + (NULL, '活动管理', 'activities', '', 'campaign', '', 70, TRUE, @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + title = VALUES(title), + path = VALUES(path), + icon = VALUES(icon), + permission_code = VALUES(permission_code), + sort = VALUES(sort), + visible = VALUES(visible), + updated_at_ms = @now_ms; + +INSERT INTO admin_menus (parent_id, title, code, path, icon, permission_code, sort, visible, created_at_ms, updated_at_ms) +SELECT parent.id, '首冲奖励', 'first-recharge-reward', '/activities/first-recharge-reward', 'workspace_premium', 'first-recharge-reward:view', 73, TRUE, @now_ms, @now_ms +FROM admin_menus parent +WHERE parent.code = 'activities' +ON DUPLICATE KEY UPDATE + parent_id = VALUES(parent_id), + title = VALUES(title), + path = VALUES(path), + icon = VALUES(icon), + permission_code = VALUES(permission_code), + sort = VALUES(sort), + visible = VALUES(visible), + updated_at_ms = @now_ms; + +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT admin_role.id, admin_permission.id +FROM admin_roles admin_role +JOIN admin_permissions admin_permission +WHERE admin_role.code = 'platform-admin' + AND admin_permission.code IN ('first-recharge-reward:view', 'first-recharge-reward:update'); + +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT admin_role.id, admin_permission.id +FROM admin_roles admin_role +JOIN admin_permissions admin_permission +WHERE admin_role.code = 'ops-admin' + AND admin_permission.code IN ('first-recharge-reward:view', 'first-recharge-reward:update'); + +INSERT IGNORE INTO admin_role_permissions (role_id, permission_id) +SELECT admin_role.id, admin_permission.id +FROM admin_roles admin_role +JOIN admin_permissions admin_permission +WHERE admin_role.code IN ('auditor', 'readonly') + AND admin_permission.code = 'first-recharge-reward:view'; diff --git a/services/activity-service/configs/config.docker.yaml b/services/activity-service/configs/config.docker.yaml index b2e47484..11c90d8c 100644 --- a/services/activity-service/configs/config.docker.yaml +++ b/services/activity-service/configs/config.docker.yaml @@ -13,6 +13,11 @@ mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_activity?parseTime=true&charset=ut user_service_addr: "user-service:13005" wallet_service_addr: "wallet-service:13004" mysql_auto_migrate: false +first_recharge_reward_worker: + enabled: false + wallet_mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC" + poll_interval_sec: 5 + batch_size: 100 tencent_im: # Docker 本地联调全局/区域播报群;必须与 gateway/room-service 使用同一组腾讯 IM 应用配置。 enabled: true diff --git a/services/activity-service/configs/config.tencent.example.yaml b/services/activity-service/configs/config.tencent.example.yaml index 04649fff..ee5dc474 100644 --- a/services/activity-service/configs/config.tencent.example.yaml +++ b/services/activity-service/configs/config.tencent.example.yaml @@ -13,6 +13,11 @@ mysql_dsn: "USER:PASSWORD@tcp(TENCENT_CDB_HOST:3306)/hyapp_activity?parseTime=tr user_service_addr: "user-service.internal:13005" wallet_service_addr: "wallet-service.internal:13004" mysql_auto_migrate: false +first_recharge_reward_worker: + enabled: true + wallet_mysql_dsn: "USER:PASSWORD@tcp(TENCENT_CDB_HOST:3306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC&tls=false" + poll_interval_sec: 5 + batch_size: 100 tencent_im: # 腾讯云 IM 应用配置;必须和 gateway 的 UserSig、room-service 房间群配置属于同一个 SDKAppID。 enabled: true diff --git a/services/activity-service/configs/config.yaml b/services/activity-service/configs/config.yaml index e439c60d..944231da 100644 --- a/services/activity-service/configs/config.yaml +++ b/services/activity-service/configs/config.yaml @@ -13,6 +13,11 @@ mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&chars user_service_addr: "127.0.0.1:13005" wallet_service_addr: "127.0.0.1:13004" mysql_auto_migrate: false +first_recharge_reward_worker: + enabled: false + wallet_mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC" + poll_interval_sec: 5 + batch_size: 100 tencent_im: # activity-service 只负责全局/区域播报群;必须与 gateway/room-service 使用同一组腾讯 IM 应用配置。 enabled: true diff --git a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql index bd2b77b7..20f078f8 100644 --- a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql +++ b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql @@ -367,6 +367,60 @@ CREATE TABLE IF NOT EXISTS registration_reward_daily_counters ( PRIMARY KEY (app_code, reward_day) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='注册奖励每日计数表'; +CREATE TABLE IF NOT EXISTS first_recharge_reward_configs ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用', + updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员 ID', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励配置表'; + +CREATE TABLE IF NOT EXISTS first_recharge_reward_tiers ( + tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '首冲奖励档位 ID', + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + tier_code VARCHAR(64) NOT NULL COMMENT '档位编码', + tier_name VARCHAR(96) NOT NULL COMMENT '档位名称', + min_coin_amount BIGINT NOT NULL COMMENT '最小充值金币数量', + max_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '最大充值金币数量,0 表示无上限', + resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID', + status VARCHAR(32) NOT NULL COMMENT '业务状态', + sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + UNIQUE KEY uk_first_recharge_reward_tier_code (app_code, tier_code), + KEY idx_first_recharge_reward_tier_active (app_code, status, sort_order, min_coin_amount) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励档位表'; + +CREATE TABLE IF NOT EXISTS first_recharge_reward_claims ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + claim_id VARCHAR(96) NOT NULL COMMENT '领取 ID', + event_id VARCHAR(128) NOT NULL COMMENT 'wallet_outbox 事件 ID', + transaction_id VARCHAR(96) NOT NULL COMMENT '充值交易 ID', + command_id VARCHAR(128) NOT NULL COMMENT '充值命令 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + tier_id BIGINT NOT NULL COMMENT '命中奖励档位 ID', + tier_code VARCHAR(64) NOT NULL COMMENT '命中奖励档位编码', + resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID', + recharge_coin_amount BIGINT NOT NULL COMMENT '充值金币数量', + recharge_sequence BIGINT NOT NULL COMMENT '该用户充值序号', + recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源类型', + status VARCHAR(32) NOT NULL COMMENT '业务状态', + wallet_command_id VARCHAR(128) NOT NULL COMMENT '钱包发奖命令 ID', + wallet_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包资源发放 ID', + failure_reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '失败原因', + recharged_at_ms BIGINT NOT NULL COMMENT '充值发生时间,UTC epoch ms', + granted_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '发放时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, claim_id), + UNIQUE KEY uk_first_recharge_reward_event (app_code, event_id), + UNIQUE KEY uk_first_recharge_reward_transaction (app_code, transaction_id), + UNIQUE KEY uk_first_recharge_reward_user_once (app_code, user_id), + KEY idx_first_recharge_reward_list (app_code, created_at_ms, claim_id), + KEY idx_first_recharge_reward_status (app_code, status, updated_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='首冲奖励领取表'; + CREATE TABLE IF NOT EXISTS seven_day_checkin_configs ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '启用', diff --git a/services/activity-service/internal/app/app.go b/services/activity-service/internal/app/app.go index 0161dad2..d8748c34 100644 --- a/services/activity-service/internal/app/app.go +++ b/services/activity-service/internal/app/app.go @@ -2,6 +2,7 @@ package app import ( "context" + "database/sql" "errors" "log/slog" "net" @@ -26,6 +27,7 @@ import ( achievementservice "hyapp/services/activity-service/internal/service/achievement" activityservice "hyapp/services/activity-service/internal/service/activity" broadcastservice "hyapp/services/activity-service/internal/service/broadcast" + firstrechargeservice "hyapp/services/activity-service/internal/service/firstrecharge" growthservice "hyapp/services/activity-service/internal/service/growth" luckygiftservice "hyapp/services/activity-service/internal/service/luckygift" messageservice "hyapp/services/activity-service/internal/service/message" @@ -43,8 +45,12 @@ type App struct { health *grpchealth.ServingChecker healthHTTP *healthhttp.Server mysqlRepo *mysqlstorage.Repository + walletOutboxDB *sql.DB broadcast *broadcastservice.Service + firstRechargeReward *firstrechargeservice.Service broadcastWorkerEnabled bool + firstRechargeWorkerCfg config.FirstRechargeRewardWorkerConfig + workerNodeID string mqConsumers []*rocketmqx.Consumer userConn *grpc.ClientConn walletConn *grpc.ClientConn @@ -139,10 +145,37 @@ func New(cfg config.Config) (*App, error) { broadcastServer := grpcserver.NewBroadcastServer(broadcastSvc, growthSvc) activityv1.RegisterBroadcastServiceServer(server, broadcastServer) activityv1.RegisterRoomEventConsumerServiceServer(server, broadcastServer) + var walletOutboxDB *sql.DB + var firstRechargeReader firstrechargeservice.WalletOutboxReader + if cfg.FirstRechargeRewardWorker.Enabled { + walletOutboxDB, err = sql.Open("mysql", cfg.FirstRechargeRewardWorker.WalletMySQLDSN) + if err != nil { + _ = walletConn.Close() + _ = userConn.Close() + _ = listener.Close() + _ = repository.Close() + return nil, err + } + if err := walletOutboxDB.PingContext(startupCtx); err != nil { + _ = walletOutboxDB.Close() + _ = walletConn.Close() + _ = userConn.Close() + _ = listener.Close() + _ = repository.Close() + return nil, err + } + firstRechargeReader = mysqlstorage.NewWalletRechargeOutboxReader(walletOutboxDB) + } + firstRechargeRewardSvc := firstrechargeservice.New(repository, walletv1.NewWalletServiceClient(walletConn), firstRechargeReader) + activityv1.RegisterFirstRechargeRewardServiceServer(server, grpcserver.NewFirstRechargeRewardServer(firstRechargeRewardSvc)) + activityv1.RegisterAdminFirstRechargeRewardServiceServer(server, grpcserver.NewAdminFirstRechargeRewardServer(firstRechargeRewardSvc)) mqConsumers := make([]*rocketmqx.Consumer, 0, 1) if cfg.RocketMQ.RoomOutbox.Enabled { consumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ)) if err != nil { + if walletOutboxDB != nil { + _ = walletOutboxDB.Close() + } _ = walletConn.Close() _ = userConn.Close() _ = listener.Close() @@ -161,6 +194,9 @@ func New(cfg config.Config) (*App, error) { _, err = growthSvc.HandleRoomEvent(eventCtx, envelope) return err }); err != nil { + if walletOutboxDB != nil { + _ = walletOutboxDB.Close() + } _ = walletConn.Close() _ = userConn.Close() _ = listener.Close() @@ -169,13 +205,23 @@ func New(cfg config.Config) (*App, error) { } mqConsumers = append(mqConsumers, consumer) } - health := grpchealth.NewServingChecker("activity-service", grpchealth.Dependency{ + healthDependencies := []grpchealth.Dependency{{ Name: "mysql", Check: repository.Ping, - }) + }} + if walletOutboxDB != nil { + healthDependencies = append(healthDependencies, grpchealth.Dependency{ + Name: "wallet_mysql", + Check: walletOutboxDB.PingContext, + }) + } + health := grpchealth.NewServingChecker("activity-service", healthDependencies...) healthgrpc.RegisterHealthServer(server, grpchealth.NewServer(health)) healthHTTP, err := healthhttp.New(cfg.HealthHTTPAddr, cfg.NodeID, health) if err != nil { + if walletOutboxDB != nil { + _ = walletOutboxDB.Close() + } _ = walletConn.Close() _ = userConn.Close() _ = listener.Close() @@ -190,8 +236,12 @@ func New(cfg config.Config) (*App, error) { health: health, healthHTTP: healthHTTP, mysqlRepo: repository, + walletOutboxDB: walletOutboxDB, broadcast: broadcastSvc, + firstRechargeReward: firstRechargeRewardSvc, broadcastWorkerEnabled: cfg.Broadcast.Enabled, + firstRechargeWorkerCfg: cfg.FirstRechargeRewardWorker, + workerNodeID: cfg.NodeID, mqConsumers: mqConsumers, userConn: userConn, walletConn: walletConn, @@ -213,6 +263,15 @@ func (a *App) Run() error { a.broadcast.RunWorker(a.workerCtx, broadcastservice.WorkerOptions{}) }) } + if a.firstRechargeWorkerCfg.Enabled && a.firstRechargeReward != nil && a.workerCtx != nil { + a.workerWG.Go(func() { + a.firstRechargeReward.RunWalletRechargeWorker(a.workerCtx, firstrechargeservice.WorkerOptions{ + WorkerID: a.workerNodeID, + PollInterval: time.Duration(a.firstRechargeWorkerCfg.PollIntervalSec) * time.Second, + BatchSize: a.firstRechargeWorkerCfg.BatchSize, + }) + }) + } err := a.server.Serve(a.listener) if a.workerStop != nil { a.workerStop() @@ -244,6 +303,9 @@ func (a *App) Close() { if a.walletConn != nil { _ = a.walletConn.Close() } + if a.walletOutboxDB != nil { + _ = a.walletOutboxDB.Close() + } if a.mysqlRepo != nil { // MySQL 连接池最后关闭,保证 drain 中的查询或消费提交能完成。 _ = a.mysqlRepo.Close() diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index 6aa6c263..75d47ecb 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -25,6 +25,8 @@ type Config struct { UserServiceAddr string `yaml:"user_service_addr"` // WalletServiceAddr 是任务奖励入账依赖;activity 只发命令,不直接写余额。 WalletServiceAddr string `yaml:"wallet_service_addr"` + // FirstRechargeRewardWorker 控制首冲奖励对 wallet_outbox 充值事实的本地消费。 + FirstRechargeRewardWorker FirstRechargeRewardWorkerConfig `yaml:"first_recharge_reward_worker"` // TencentIM 是 activity-service 发送全局/区域播报群消息的 REST 配置。 TencentIM TencentIMConfig `yaml:"tencent_im"` // Broadcast 控制 IM 播报群 reconciler、outbox worker 和贵重礼物阈值。 @@ -49,6 +51,18 @@ type MessageInboxConfig struct { UnreadCacheTTL string `yaml:"unread_cache_ttl"` } +// FirstRechargeRewardWorkerConfig 保存钱包充值事实消费策略。 +type FirstRechargeRewardWorkerConfig struct { + // Enabled 控制是否启动 wallet_outbox 轮询;关闭后仍可通过 gRPC 消费入口补偿。 + Enabled bool `yaml:"enabled"` + // WalletMySQLDSN 是 wallet-service outbox 只读连接串。 + WalletMySQLDSN string `yaml:"wallet_mysql_dsn"` + // PollIntervalSec 是没有积压时两轮扫描间隔秒数。 + PollIntervalSec int64 `yaml:"poll_interval_sec"` + // BatchSize 是单轮最多消费的 WalletRechargeRecorded 事件数。 + BatchSize int `yaml:"batch_size"` +} + // TencentIMConfig 描述 activity-service 调用腾讯云 IM REST API 的配置。 type TencentIMConfig struct { Enabled bool `yaml:"enabled"` @@ -121,6 +135,12 @@ func Default() Config { MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC", UserServiceAddr: "127.0.0.1:13005", WalletServiceAddr: "127.0.0.1:13004", + FirstRechargeRewardWorker: FirstRechargeRewardWorkerConfig{ + Enabled: false, + WalletMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC", + PollIntervalSec: 5, + BatchSize: 100, + }, TencentIM: TencentIMConfig{ Enabled: false, AdminIdentifier: "administrator", @@ -183,6 +203,16 @@ func Load(path string) (Config, error) { if strings.TrimSpace(cfg.WalletServiceAddr) == "" { cfg.WalletServiceAddr = Default().WalletServiceAddr } + cfg.FirstRechargeRewardWorker.WalletMySQLDSN = strings.TrimSpace(cfg.FirstRechargeRewardWorker.WalletMySQLDSN) + if cfg.FirstRechargeRewardWorker.WalletMySQLDSN == "" { + cfg.FirstRechargeRewardWorker.WalletMySQLDSN = Default().FirstRechargeRewardWorker.WalletMySQLDSN + } + if cfg.FirstRechargeRewardWorker.PollIntervalSec <= 0 { + cfg.FirstRechargeRewardWorker.PollIntervalSec = Default().FirstRechargeRewardWorker.PollIntervalSec + } + if cfg.FirstRechargeRewardWorker.BatchSize <= 0 { + cfg.FirstRechargeRewardWorker.BatchSize = Default().FirstRechargeRewardWorker.BatchSize + } cfg.ServiceName = strings.TrimSpace(cfg.ServiceName) if cfg.ServiceName == "" { cfg.ServiceName = "activity-service" diff --git a/services/activity-service/internal/domain/firstrecharge/first_recharge.go b/services/activity-service/internal/domain/firstrecharge/first_recharge.go new file mode 100644 index 00000000..aedda6a4 --- /dev/null +++ b/services/activity-service/internal/domain/firstrecharge/first_recharge.go @@ -0,0 +1,115 @@ +package firstrecharge + +const ( + TierStatusActive = "active" + TierStatusInactive = "inactive" + + StatusPending = "pending" + StatusGranted = "granted" + StatusFailed = "failed" + + ReasonEligible = "eligible" + ReasonNotConfigured = "not_configured" + ReasonDisabled = "disabled" + ReasonInvalidConfig = "invalid_config" + ReasonNotFirst = "not_first_recharge" + ReasonTierNotMatched = "tier_not_matched" + ReasonAlreadyGranted = "already_granted" + ReasonPendingReward = "pending_reward" + + RechargeEventWalletRecorded = "WalletRechargeRecorded" + RechargeTypeCoinSeller = "coin_seller_transfer" +) + +// Tier 是首冲奖励的金额档位,max_coin_amount=0 表达无上限。 +type Tier struct { + TierID int64 + TierCode string + TierName string + MinCoinAmount int64 + MaxCoinAmount int64 + ResourceGroupID int64 + Status string + SortOrder int32 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Config 是首冲奖励当前配置;档位快照由 activity-service 持有。 +type Config struct { + AppCode string + Enabled bool + Tiers []Tier + UpdatedByAdminID int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Claim 是首笔充值触发后的发奖事实;app_code + user_id 唯一。 +type Claim struct { + ClaimID string + EventID string + TransactionID string + CommandID string + UserID int64 + TierID int64 + TierCode string + ResourceGroupID int64 + RechargeCoinAmount int64 + RechargeSequence int64 + RechargeType string + Status string + WalletCommandID string + WalletGrantID string + FailureReason string + RechargedAtMS int64 + GrantedAtMS int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// StatusResult 是 App 首冲奖励面板读取的稳定投影。 +type StatusResult struct { + Enabled bool + Tiers []Tier + Rewarded bool + Claim Claim + ServerTimeMS int64 +} + +// RechargeEvent 是 wallet_outbox 中的成功充值事实。 +type RechargeEvent struct { + AppCode string + EventID string + EventType string + TransactionID string + CommandID string + UserID int64 + RechargeCoinAmount int64 + RechargeSequence int64 + RechargeType string + PayloadJSON string + OccurredAtMS int64 +} + +// PrepareResult 表达 activity 事务是否已经创建或复用 pending claim。 +type PrepareResult struct { + Claim Claim + Prepared bool + AlreadyGranted bool + Reason string +} + +// ClaimQuery 是后台发放记录分页查询条件。 +type ClaimQuery struct { + Status string + UserID int64 + Page int32 + PageSize int32 +} + +// WalletRechargeCursor 让 worker 按 wallet_outbox 创建顺序稳定扫描。 +type WalletRechargeCursor struct { + CreatedAtMS int64 + EventID string +} diff --git a/services/activity-service/internal/service/firstrecharge/service.go b/services/activity-service/internal/service/firstrecharge/service.go new file mode 100644 index 00000000..25b45826 --- /dev/null +++ b/services/activity-service/internal/service/firstrecharge/service.go @@ -0,0 +1,366 @@ +package firstrecharge + +import ( + "context" + "log/slog" + "sort" + "strings" + "time" + + "google.golang.org/grpc" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/logx" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/firstrecharge" +) + +const ( + grantSource = "first_recharge_reward" + grantReason = "first_recharge_reward" +) + +// Repository 是首冲奖励配置、claim 幂等和发放事实的唯一持久化边界。 +type Repository interface { + GetFirstRechargeRewardConfig(ctx context.Context) (domain.Config, bool, error) + UpdateFirstRechargeRewardConfig(ctx context.Context, config domain.Config, nowMS int64) (domain.Config, error) + GetFirstRechargeRewardClaimByUser(ctx context.Context, userID int64) (domain.Claim, bool, error) + PrepareFirstRechargeRewardClaim(ctx context.Context, event domain.RechargeEvent, nowMS int64) (domain.PrepareResult, error) + MarkFirstRechargeRewardClaimGranted(ctx context.Context, claimID string, walletGrantID string, grantedAtMS int64) (domain.Claim, error) + MarkFirstRechargeRewardClaimFailed(ctx context.Context, claimID string, failureReason string, nowMS int64) error + ListFirstRechargeRewardClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, error) +} + +// WalletClient 是首冲奖励唯一外部副作用;资源组展开由 wallet-service 原子完成。 +type WalletClient interface { + GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) +} + +// WalletOutboxReader 扫描 wallet-service 的充值事实;activity 不修改 wallet_outbox 状态。 +type WalletOutboxReader interface { + ListRechargeEventsAfter(ctx context.Context, cursor domain.WalletRechargeCursor, batchSize int) ([]domain.RechargeEvent, error) +} + +// WorkerOptions 控制本地 wallet_outbox 轮询。 +type WorkerOptions struct { + WorkerID string + PollInterval time.Duration + BatchSize int +} + +// Service 承载首冲奖励 App 查询、后台配置和充值事实消费用例。 +type Service struct { + repository Repository + wallet WalletClient + reader WalletOutboxReader + now func() time.Time +} + +func New(repository Repository, wallet WalletClient, reader WalletOutboxReader) *Service { + return &Service{repository: repository, wallet: wallet, reader: reader, now: time.Now} +} + +func (s *Service) SetClock(now func() time.Time) { + if now != nil { + s.now = now + } +} + +// GetStatus 返回 App 可展示的当前配置和用户发放状态;未配置时不是错误。 +func (s *Service) GetStatus(ctx context.Context, userID int64) (domain.StatusResult, error) { + if err := s.requireRepository(); err != nil { + return domain.StatusResult{}, err + } + if userID <= 0 { + return domain.StatusResult{}, xerr.New(xerr.InvalidArgument, "user_id is required") + } + nowMS := s.now().UnixMilli() + result := domain.StatusResult{ServerTimeMS: nowMS} + config, exists, err := s.repository.GetFirstRechargeRewardConfig(ctx) + if err != nil { + return domain.StatusResult{}, err + } + if exists { + result.Enabled = config.Enabled + result.Tiers = activeTiers(config.Tiers) + } + claim, claimed, err := s.repository.GetFirstRechargeRewardClaimByUser(ctx, userID) + if err != nil { + return domain.StatusResult{}, err + } + if claimed { + result.Claim = claim + result.Rewarded = claim.Status == domain.StatusGranted + } + return result, nil +} + +func (s *Service) GetConfig(ctx context.Context) (domain.Config, error) { + if err := s.requireRepository(); err != nil { + return domain.Config{}, err + } + config, exists, err := s.repository.GetFirstRechargeRewardConfig(ctx) + if err != nil { + return domain.Config{}, err + } + if !exists { + return domain.Config{AppCode: appcode.FromContext(ctx)}, nil + } + return config, nil +} + +func (s *Service) UpdateConfig(ctx context.Context, config domain.Config) (domain.Config, error) { + if err := s.requireRepository(); err != nil { + return domain.Config{}, err + } + config.AppCode = appcode.FromContext(ctx) + config.Tiers = normalizeTiers(config.Tiers) + if err := validateConfig(config); err != nil { + return domain.Config{}, err + } + return s.repository.UpdateFirstRechargeRewardConfig(ctx, config, s.now().UnixMilli()) +} + +// Consume 处理 wallet 成功充值事实;只有 recharge_sequence=1 且命中启用档位才发奖。 +func (s *Service) Consume(ctx context.Context, event domain.RechargeEvent) (domain.Claim, bool, string, error) { + if err := s.requireRepository(); err != nil { + return domain.Claim{}, false, "", err + } + event = normalizeRechargeEvent(event) + if err := validateRechargeEvent(event); err != nil { + return domain.Claim{}, false, "", err + } + if event.RechargeSequence != 1 { + return domain.Claim{}, false, domain.ReasonNotFirst, nil + } + prepared, err := s.repository.PrepareFirstRechargeRewardClaim(ctx, event, s.now().UnixMilli()) + if err != nil { + return domain.Claim{}, false, "", err + } + if prepared.AlreadyGranted { + return prepared.Claim, true, prepared.Reason, nil + } + if !prepared.Prepared { + return prepared.Claim, false, prepared.Reason, nil + } + if s.wallet == nil { + return domain.Claim{}, false, "", xerr.New(xerr.Unavailable, "wallet client is not configured") + } + + claim := prepared.Claim + resp, err := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ + CommandId: claim.WalletCommandID, + AppCode: appcode.FromContext(ctx), + TargetUserId: claim.UserID, + GroupId: claim.ResourceGroupID, + Reason: grantReason, + OperatorUserId: claim.UserID, + GrantSource: grantSource, + }) + if err != nil { + _ = s.repository.MarkFirstRechargeRewardClaimFailed(ctx, claim.ClaimID, xerr.MessageOf(err), s.now().UnixMilli()) + return domain.Claim{}, false, "", err + } + walletGrantID := "" + if resp.GetGrant() != nil { + walletGrantID = resp.GetGrant().GetGrantId() + } + claim, err = s.repository.MarkFirstRechargeRewardClaimGranted(ctx, claim.ClaimID, walletGrantID, s.now().UnixMilli()) + if err != nil { + return domain.Claim{}, false, "", err + } + return claim, true, domain.ReasonEligible, nil +} + +func (s *Service) ListClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, error) { + if err := s.requireRepository(); err != nil { + return nil, 0, err + } + query.Status = strings.TrimSpace(query.Status) + if query.Page <= 0 { + query.Page = 1 + } + if query.PageSize <= 0 { + query.PageSize = 20 + } + if query.PageSize > 100 { + query.PageSize = 100 + } + return s.repository.ListFirstRechargeRewardClaims(ctx, query) +} + +// RunWalletRechargeWorker 轮询 wallet_outbox 的充值事实;游标只在内存保存,claim 表唯一键保证重复扫描安全。 +func (s *Service) RunWalletRechargeWorker(ctx context.Context, options WorkerOptions) { + if s == nil || s.repository == nil || s.reader == nil { + logx.Warn(ctx, "worker_disabled", slog.String("worker", "first_recharge_reward"), slog.String("reason", "missing_dependency")) + return + } + if options.PollInterval <= 0 { + options.PollInterval = 5 * time.Second + } + if options.BatchSize <= 0 { + options.BatchSize = 100 + } + var cursor domain.WalletRechargeCursor + for { + processed, err := s.processBatch(ctx, &cursor, options.BatchSize) + if err != nil { + logx.Error(ctx, "worker_batch_failed", err, slog.String("worker", "first_recharge_reward"), slog.String("worker_id", options.WorkerID), slog.Int("batch_size", options.BatchSize)) + } + if ctx.Err() != nil { + return + } + if processed >= options.BatchSize { + continue + } + select { + case <-ctx.Done(): + return + case <-time.After(options.PollInterval): + } + } +} + +func (s *Service) processBatch(ctx context.Context, cursor *domain.WalletRechargeCursor, batchSize int) (int, error) { + events, err := s.reader.ListRechargeEventsAfter(ctx, *cursor, batchSize) + if err != nil { + return 0, err + } + for _, event := range events { + eventCtx := appcode.WithContext(ctx, event.AppCode) + if _, _, _, err := s.Consume(eventCtx, event); err != nil { + return 0, err + } + cursor.CreatedAtMS = event.OccurredAtMS + cursor.EventID = event.EventID + } + return len(events), nil +} + +func (s *Service) requireRepository() error { + if s == nil || s.repository == nil { + return xerr.New(xerr.Unavailable, "first recharge reward repository is not configured") + } + return nil +} + +func normalizeTiers(tiers []domain.Tier) []domain.Tier { + items := make([]domain.Tier, 0, len(tiers)) + for _, tier := range tiers { + status := strings.ToLower(strings.TrimSpace(tier.Status)) + if status == "" { + status = domain.TierStatusActive + } + items = append(items, domain.Tier{ + TierID: tier.TierID, + TierCode: strings.TrimSpace(tier.TierCode), + TierName: strings.TrimSpace(tier.TierName), + MinCoinAmount: tier.MinCoinAmount, + MaxCoinAmount: tier.MaxCoinAmount, + ResourceGroupID: tier.ResourceGroupID, + Status: status, + SortOrder: tier.SortOrder, + }) + } + sort.SliceStable(items, func(i, j int) bool { + if items[i].SortOrder == items[j].SortOrder { + return items[i].MinCoinAmount < items[j].MinCoinAmount + } + return items[i].SortOrder < items[j].SortOrder + }) + return items +} + +func validateConfig(config domain.Config) error { + if config.UpdatedByAdminID <= 0 { + return xerr.New(xerr.InvalidArgument, "operator_admin_id is required") + } + seen := make(map[string]struct{}, len(config.Tiers)) + active := make([]domain.Tier, 0, len(config.Tiers)) + for _, tier := range config.Tiers { + if tier.TierCode == "" { + return xerr.New(xerr.InvalidArgument, "tier_code is required") + } + if _, exists := seen[tier.TierCode]; exists { + return xerr.New(xerr.InvalidArgument, "tier_code is duplicated") + } + seen[tier.TierCode] = struct{}{} + if tier.TierName == "" { + return xerr.New(xerr.InvalidArgument, "tier_name is required") + } + if tier.MinCoinAmount <= 0 { + return xerr.New(xerr.InvalidArgument, "min_coin_amount must be greater than zero") + } + if tier.MaxCoinAmount > 0 && tier.MaxCoinAmount < tier.MinCoinAmount { + return xerr.New(xerr.InvalidArgument, "max_coin_amount must be greater than min_coin_amount") + } + if tier.ResourceGroupID <= 0 { + return xerr.New(xerr.InvalidArgument, "resource_group_id is required") + } + switch tier.Status { + case domain.TierStatusActive: + active = append(active, tier) + case domain.TierStatusInactive: + default: + return xerr.New(xerr.InvalidArgument, "tier status is invalid") + } + } + if config.Enabled && len(active) == 0 { + return xerr.New(xerr.InvalidArgument, "enabled config requires at least one active tier") + } + if hasOverlappedTiers(active) { + return xerr.New(xerr.InvalidArgument, "active tiers overlap") + } + return nil +} + +func hasOverlappedTiers(tiers []domain.Tier) bool { + sort.SliceStable(tiers, func(i, j int) bool { return tiers[i].MinCoinAmount < tiers[j].MinCoinAmount }) + var previousMax int64 + for i, tier := range tiers { + if i > 0 && (previousMax == 0 || tier.MinCoinAmount <= previousMax) { + return true + } + previousMax = tier.MaxCoinAmount + } + return false +} + +func activeTiers(tiers []domain.Tier) []domain.Tier { + items := make([]domain.Tier, 0, len(tiers)) + for _, tier := range tiers { + if tier.Status == domain.TierStatusActive { + items = append(items, tier) + } + } + return items +} + +func normalizeRechargeEvent(event domain.RechargeEvent) domain.RechargeEvent { + event.AppCode = appcode.Normalize(event.AppCode) + event.EventID = strings.TrimSpace(event.EventID) + event.EventType = strings.TrimSpace(event.EventType) + event.TransactionID = strings.TrimSpace(event.TransactionID) + event.CommandID = strings.TrimSpace(event.CommandID) + event.RechargeType = strings.TrimSpace(event.RechargeType) + if event.RechargeType == "" { + event.RechargeType = domain.RechargeTypeCoinSeller + } + return event +} + +func validateRechargeEvent(event domain.RechargeEvent) error { + if event.EventID == "" || event.TransactionID == "" || event.CommandID == "" || event.UserID <= 0 { + return xerr.New(xerr.InvalidArgument, "first recharge event is incomplete") + } + if event.EventType != "" && event.EventType != domain.RechargeEventWalletRecorded { + return xerr.New(xerr.InvalidArgument, "first recharge event type is invalid") + } + if event.RechargeCoinAmount <= 0 { + return xerr.New(xerr.InvalidArgument, "recharge_coin_amount must be greater than zero") + } + if event.OccurredAtMS <= 0 { + return xerr.New(xerr.InvalidArgument, "occurred_at_ms is required") + } + return nil +} diff --git a/services/activity-service/internal/service/firstrecharge/service_test.go b/services/activity-service/internal/service/firstrecharge/service_test.go new file mode 100644 index 00000000..4d8a6c4b --- /dev/null +++ b/services/activity-service/internal/service/firstrecharge/service_test.go @@ -0,0 +1,105 @@ +package firstrecharge + +import ( + "context" + "testing" + + "google.golang.org/grpc" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + domain "hyapp/services/activity-service/internal/domain/firstrecharge" + "hyapp/services/activity-service/internal/testutil/mysqltest" +) + +func TestFirstRechargeRewardConsumesRechargeFactWithMySQL(t *testing.T) { + repository := mysqltest.NewRepository(t) + wallet := &fakeWallet{} + svc := New(repository, wallet, nil) + ctx := appcode.WithContext(context.Background(), "lalu") + + config, err := svc.UpdateConfig(ctx, domain.Config{ + Enabled: true, + UpdatedByAdminID: 90001, + Tiers: []domain.Tier{{ + TierCode: "first_100", + TierName: "首冲 100+", + MinCoinAmount: 100, + MaxCoinAmount: 0, + ResourceGroupID: 88001, + Status: domain.TierStatusActive, + }}, + }) + if err != nil { + t.Fatalf("UpdateConfig failed: %v", err) + } + if len(config.Tiers) != 1 || config.Tiers[0].TierID <= 0 { + t.Fatalf("tier id was not generated: %+v", config.Tiers) + } + + event := domain.RechargeEvent{ + AppCode: "lalu", + EventID: "evt-recharge-1", + EventType: domain.RechargeEventWalletRecorded, + TransactionID: "wtx-recharge-1", + CommandID: "seller-transfer-1", + UserID: 42001, + RechargeCoinAmount: 500, + RechargeSequence: 1, + RechargeType: domain.RechargeTypeCoinSeller, + OccurredAtMS: 1710000000000, + } + claim, consumed, reason, err := svc.Consume(ctx, event) + if err != nil { + t.Fatalf("Consume failed: %v", err) + } + if !consumed || reason != domain.ReasonEligible || claim.Status != domain.StatusGranted || claim.ResourceGroupID != 88001 { + t.Fatalf("consume result mismatch: claim=%+v consumed=%v reason=%s", claim, consumed, reason) + } + if len(wallet.grants) != 1 || wallet.grants[0].GroupId != 88001 || wallet.grants[0].TargetUserId != 42001 { + t.Fatalf("wallet grant mismatch: %+v", wallet.grants) + } + + status, err := svc.GetStatus(ctx, 42001) + if err != nil { + t.Fatalf("GetStatus failed: %v", err) + } + if !status.Rewarded || status.Claim.ClaimID != claim.ClaimID { + t.Fatalf("status should include granted claim: %+v", status) + } + + _, consumed, reason, err = svc.Consume(ctx, event) + if err != nil { + t.Fatalf("retry Consume failed: %v", err) + } + if !consumed || reason != domain.ReasonAlreadyGranted || len(wallet.grants) != 1 { + t.Fatalf("retry should be idempotent: consumed=%v reason=%s grants=%d", consumed, reason, len(wallet.grants)) + } + + event.EventID = "evt-recharge-2" + event.TransactionID = "wtx-recharge-2" + event.CommandID = "seller-transfer-2" + event.RechargeSequence = 2 + _, consumed, reason, err = svc.Consume(ctx, event) + if err != nil { + t.Fatalf("second recharge Consume failed: %v", err) + } + if consumed || reason != domain.ReasonNotFirst || len(wallet.grants) != 1 { + t.Fatalf("second recharge should be ignored: consumed=%v reason=%s grants=%d", consumed, reason, len(wallet.grants)) + } +} + +type fakeWallet struct { + grants []*walletv1.GrantResourceGroupRequest +} + +func (f *fakeWallet) GrantResourceGroup(_ context.Context, req *walletv1.GrantResourceGroupRequest, _ ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) { + f.grants = append(f.grants, req) + return &walletv1.ResourceGrantResponse{Grant: &walletv1.ResourceGrant{ + AppCode: req.GetAppCode(), + GrantId: "grant-first-recharge", + CommandId: req.GetCommandId(), + TargetUserId: req.GetTargetUserId(), + GrantSource: req.GetGrantSource(), + Status: "granted", + }}, nil +} diff --git a/services/activity-service/internal/storage/mysql/first_recharge_repository.go b/services/activity-service/internal/storage/mysql/first_recharge_repository.go new file mode 100644 index 00000000..670cb7f0 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/first_recharge_repository.go @@ -0,0 +1,557 @@ +package mysql + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/firstrecharge" +) + +// GetFirstRechargeRewardConfig 读取首冲奖励当前配置;未配置是后台首屏正常状态。 +func (r *Repository) GetFirstRechargeRewardConfig(ctx context.Context) (domain.Config, bool, error) { + if r == nil || r.db == nil { + return domain.Config{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, firstRechargeRewardConfigSelectSQL()+` + WHERE app_code = ?`, + appcode.FromContext(ctx), + ) + config, err := scanFirstRechargeRewardConfig(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Config{}, false, nil + } + if err != nil { + return domain.Config{}, false, err + } + tiers, err := r.listFirstRechargeRewardTiers(ctx, nil) + if err != nil { + return domain.Config{}, false, err + } + config.Tiers = tiers + return config, true, nil +} + +// UpdateFirstRechargeRewardConfig 原子替换配置档位;claim 保留命中档位快照,不受后续配置变更影响。 +func (r *Repository) UpdateFirstRechargeRewardConfig(ctx context.Context, config domain.Config, nowMS int64) (domain.Config, error) { + if r == nil || r.db == nil { + return domain.Config{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.Config{}, err + } + defer func() { _ = tx.Rollback() }() + + _, err = tx.ExecContext(ctx, ` + INSERT INTO first_recharge_reward_configs ( + app_code, enabled, updated_by_admin_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + enabled = VALUES(enabled), + updated_by_admin_id = VALUES(updated_by_admin_id), + updated_at_ms = VALUES(updated_at_ms)`, + appcode.FromContext(ctx), config.Enabled, config.UpdatedByAdminID, nowMS, nowMS, + ) + if err != nil { + return domain.Config{}, err + } + if _, err := tx.ExecContext(ctx, ` + DELETE FROM first_recharge_reward_tiers + WHERE app_code = ?`, + appcode.FromContext(ctx), + ); err != nil { + return domain.Config{}, err + } + for i := range config.Tiers { + tier := config.Tiers[i] + tier.CreatedAtMS = nowMS + tier.UpdatedAtMS = nowMS + if tier.TierID > 0 { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO first_recharge_reward_tiers ( + tier_id, app_code, tier_code, tier_name, min_coin_amount, max_coin_amount, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + tier.TierID, appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.MinCoinAmount, + tier.MaxCoinAmount, tier.ResourceGroupID, tier.Status, tier.SortOrder, tier.CreatedAtMS, tier.UpdatedAtMS, + ); err != nil { + return domain.Config{}, err + } + continue + } + result, err := tx.ExecContext(ctx, ` + INSERT INTO first_recharge_reward_tiers ( + app_code, tier_code, tier_name, min_coin_amount, max_coin_amount, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.MinCoinAmount, tier.MaxCoinAmount, + tier.ResourceGroupID, tier.Status, tier.SortOrder, tier.CreatedAtMS, tier.UpdatedAtMS, + ) + if err != nil { + return domain.Config{}, err + } + tierID, err := result.LastInsertId() + if err != nil { + return domain.Config{}, err + } + config.Tiers[i].TierID = tierID + } + if err := tx.Commit(); err != nil { + return domain.Config{}, err + } + updated, exists, err := r.GetFirstRechargeRewardConfig(ctx) + if err != nil { + return domain.Config{}, err + } + if !exists { + return domain.Config{}, xerr.New(xerr.NotFound, "first recharge reward config not found") + } + return updated, nil +} + +// GetFirstRechargeRewardClaimByUser 返回 App 查询需要的用户首冲奖励事实。 +func (r *Repository) GetFirstRechargeRewardClaimByUser(ctx context.Context, userID int64) (domain.Claim, bool, error) { + if r == nil || r.db == nil { + return domain.Claim{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, firstRechargeRewardClaimSelectSQL()+` + WHERE app_code = ? AND user_id = ?`, + appcode.FromContext(ctx), userID, + ) + claim, err := scanFirstRechargeRewardClaim(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Claim{}, false, nil + } + return claim, err == nil, err +} + +// PrepareFirstRechargeRewardClaim 在 activity 事务内完成配置匹配、幂等判断和 pending claim 写入。 +func (r *Repository) PrepareFirstRechargeRewardClaim(ctx context.Context, event domain.RechargeEvent, nowMS int64) (domain.PrepareResult, error) { + if r == nil || r.db == nil { + return domain.PrepareResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.PrepareResult{}, err + } + defer func() { _ = tx.Rollback() }() + + if event.RechargeSequence != 1 { + return domain.PrepareResult{Reason: domain.ReasonNotFirst}, tx.Commit() + } + config, exists, err := r.getFirstRechargeRewardConfigForUpdate(ctx, tx) + if err != nil { + return domain.PrepareResult{}, err + } + if !exists { + return domain.PrepareResult{Reason: domain.ReasonNotConfigured}, tx.Commit() + } + if !config.Enabled { + return domain.PrepareResult{Reason: domain.ReasonDisabled}, tx.Commit() + } + tiers, err := r.listFirstRechargeRewardTiersForUpdate(ctx, tx) + if err != nil { + return domain.PrepareResult{}, err + } + tier, matched := matchFirstRechargeRewardTier(tiers, event.RechargeCoinAmount) + if !matched { + return domain.PrepareResult{Reason: domain.ReasonTierNotMatched}, tx.Commit() + } + + existing, exists, err := r.getFirstRechargeRewardClaimByEventForUpdate(ctx, tx, event.EventID) + if err != nil || exists { + return r.prepareExistingFirstRechargeRewardClaim(ctx, tx, existing, exists, err, event, nowMS) + } + existing, exists, err = r.getFirstRechargeRewardClaimByTransactionForUpdate(ctx, tx, event.TransactionID) + if err != nil || exists { + return r.prepareExistingFirstRechargeRewardClaim(ctx, tx, existing, exists, err, event, nowMS) + } + existing, exists, err = r.getFirstRechargeRewardClaimByUserForUpdate(ctx, tx, event.UserID) + if err != nil || exists { + return r.prepareExistingFirstRechargeRewardClaim(ctx, tx, existing, exists, err, event, nowMS) + } + + claim := domain.Claim{ + ClaimID: idgen.New("frclaim"), + EventID: event.EventID, + TransactionID: event.TransactionID, + CommandID: event.CommandID, + UserID: event.UserID, + TierID: tier.TierID, + TierCode: tier.TierCode, + ResourceGroupID: tier.ResourceGroupID, + RechargeCoinAmount: event.RechargeCoinAmount, + RechargeSequence: event.RechargeSequence, + RechargeType: event.RechargeType, + Status: domain.StatusPending, + RechargedAtMS: event.OccurredAtMS, + CreatedAtMS: nowMS, + UpdatedAtMS: nowMS, + } + claim.WalletCommandID = walletFirstRechargeRewardCommandID(claim.ClaimID) + if err := r.insertFirstRechargeRewardClaim(ctx, tx, claim); err != nil { + return domain.PrepareResult{}, err + } + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + return domain.PrepareResult{Claim: claim, Prepared: true, Reason: domain.ReasonEligible}, nil +} + +func (r *Repository) prepareExistingFirstRechargeRewardClaim(ctx context.Context, tx *sql.Tx, claim domain.Claim, exists bool, sourceErr error, event domain.RechargeEvent, nowMS int64) (domain.PrepareResult, error) { + if sourceErr != nil { + return domain.PrepareResult{}, sourceErr + } + if !exists { + return domain.PrepareResult{}, nil + } + if claim.UserID != event.UserID { + return domain.PrepareResult{}, xerr.New(xerr.RequestConflict, "first recharge reward event payload conflicts") + } + if claim.Status == domain.StatusGranted { + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + return domain.PrepareResult{Claim: claim, AlreadyGranted: true, Reason: domain.ReasonAlreadyGranted}, nil + } + if claim.Status == domain.StatusFailed { + if err := r.updateFirstRechargeRewardClaimPending(ctx, tx, claim.ClaimID, nowMS); err != nil { + return domain.PrepareResult{}, err + } + claim.Status = domain.StatusPending + claim.FailureReason = "" + claim.UpdatedAtMS = nowMS + } + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + return domain.PrepareResult{Claim: claim, Prepared: true, Reason: domain.ReasonPendingReward}, nil +} + +// MarkFirstRechargeRewardClaimGranted 写回 wallet-service 资源组发放回执。 +func (r *Repository) MarkFirstRechargeRewardClaimGranted(ctx context.Context, claimID string, walletGrantID string, grantedAtMS int64) (domain.Claim, error) { + if r == nil || r.db == nil { + return domain.Claim{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + _, err := r.db.ExecContext(ctx, ` + UPDATE first_recharge_reward_claims + SET status = 'granted', + wallet_grant_id = ?, + failure_reason = '', + granted_at_ms = ?, + updated_at_ms = ? + WHERE app_code = ? AND claim_id = ? AND status <> 'granted'`, + walletGrantID, grantedAtMS, grantedAtMS, appcode.FromContext(ctx), claimID, + ) + if err != nil { + return domain.Claim{}, err + } + claim, exists, err := r.getFirstRechargeRewardClaimByID(ctx, claimID) + if err != nil { + return domain.Claim{}, err + } + if !exists { + return domain.Claim{}, xerr.New(xerr.NotFound, "first recharge reward claim not found") + } + return claim, nil +} + +// MarkFirstRechargeRewardClaimFailed 保留 claim,后续同一 wallet 事实重试会复用原钱包命令。 +func (r *Repository) MarkFirstRechargeRewardClaimFailed(ctx context.Context, claimID string, failureReason string, nowMS int64) error { + if r == nil || r.db == nil { + return xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + _, err := r.db.ExecContext(ctx, ` + UPDATE first_recharge_reward_claims + SET status = 'failed', failure_reason = ?, updated_at_ms = ? + WHERE app_code = ? AND claim_id = ? AND status <> 'granted'`, + truncateTaskFailure(failureReason), nowMS, appcode.FromContext(ctx), claimID, + ) + return err +} + +// ListFirstRechargeRewardClaims 返回后台发放记录,按创建时间倒序。 +func (r *Repository) ListFirstRechargeRewardClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, error) { + if r == nil || r.db == nil { + return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + where, args := firstRechargeRewardClaimWhere(ctx, query) + var total int64 + if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM first_recharge_reward_claims `+where, args...).Scan(&total); err != nil { + return nil, 0, err + } + pageSize := normalizePageSize(query.PageSize) + page := query.Page + if page <= 0 { + page = 1 + } + args = append(args, pageSize, (page-1)*pageSize) + rows, err := r.db.QueryContext(ctx, firstRechargeRewardClaimSelectSQL()+` + `+where+` + ORDER BY created_at_ms DESC, claim_id DESC + LIMIT ? OFFSET ?`, args...) + if err != nil { + return nil, 0, err + } + defer rows.Close() + return scanFirstRechargeRewardClaims(rows, total) +} + +func (r *Repository) getFirstRechargeRewardConfigForUpdate(ctx context.Context, tx *sql.Tx) (domain.Config, bool, error) { + row := tx.QueryRowContext(ctx, firstRechargeRewardConfigSelectSQL()+` + WHERE app_code = ? + FOR UPDATE`, + appcode.FromContext(ctx), + ) + config, err := scanFirstRechargeRewardConfig(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Config{}, false, nil + } + return config, err == nil, err +} + +func (r *Repository) listFirstRechargeRewardTiers(ctx context.Context, tx *sql.Tx) ([]domain.Tier, error) { + var rows *sql.Rows + var err error + if tx != nil { + rows, err = tx.QueryContext(ctx, firstRechargeRewardTierSelectSQL()+` + WHERE app_code = ? + ORDER BY sort_order ASC, min_coin_amount ASC, tier_id ASC`, + appcode.FromContext(ctx), + ) + } else { + rows, err = r.db.QueryContext(ctx, firstRechargeRewardTierSelectSQL()+` + WHERE app_code = ? + ORDER BY sort_order ASC, min_coin_amount ASC, tier_id ASC`, + appcode.FromContext(ctx), + ) + } + if err != nil { + return nil, err + } + defer rows.Close() + return scanFirstRechargeRewardTiers(rows) +} + +func (r *Repository) listFirstRechargeRewardTiersForUpdate(ctx context.Context, tx *sql.Tx) ([]domain.Tier, error) { + rows, err := tx.QueryContext(ctx, firstRechargeRewardTierSelectSQL()+` + WHERE app_code = ? + ORDER BY sort_order ASC, min_coin_amount ASC, tier_id ASC + FOR UPDATE`, + appcode.FromContext(ctx), + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanFirstRechargeRewardTiers(rows) +} + +func (r *Repository) getFirstRechargeRewardClaimByEventForUpdate(ctx context.Context, tx *sql.Tx, eventID string) (domain.Claim, bool, error) { + row := tx.QueryRowContext(ctx, firstRechargeRewardClaimSelectSQL()+` + WHERE app_code = ? AND event_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), eventID, + ) + claim, err := scanFirstRechargeRewardClaim(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Claim{}, false, nil + } + return claim, err == nil, err +} + +func (r *Repository) getFirstRechargeRewardClaimByTransactionForUpdate(ctx context.Context, tx *sql.Tx, transactionID string) (domain.Claim, bool, error) { + row := tx.QueryRowContext(ctx, firstRechargeRewardClaimSelectSQL()+` + WHERE app_code = ? AND transaction_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), transactionID, + ) + claim, err := scanFirstRechargeRewardClaim(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Claim{}, false, nil + } + return claim, err == nil, err +} + +func (r *Repository) getFirstRechargeRewardClaimByUserForUpdate(ctx context.Context, tx *sql.Tx, userID int64) (domain.Claim, bool, error) { + row := tx.QueryRowContext(ctx, firstRechargeRewardClaimSelectSQL()+` + WHERE app_code = ? AND user_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), userID, + ) + claim, err := scanFirstRechargeRewardClaim(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Claim{}, false, nil + } + return claim, err == nil, err +} + +func (r *Repository) getFirstRechargeRewardClaimByID(ctx context.Context, claimID string) (domain.Claim, bool, error) { + row := r.db.QueryRowContext(ctx, firstRechargeRewardClaimSelectSQL()+` + WHERE app_code = ? AND claim_id = ?`, + appcode.FromContext(ctx), claimID, + ) + claim, err := scanFirstRechargeRewardClaim(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Claim{}, false, nil + } + return claim, err == nil, err +} + +func (r *Repository) insertFirstRechargeRewardClaim(ctx context.Context, tx *sql.Tx, claim domain.Claim) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO first_recharge_reward_claims ( + app_code, claim_id, event_id, transaction_id, command_id, user_id, + tier_id, tier_code, resource_group_id, recharge_coin_amount, recharge_sequence, + recharge_type, status, wallet_command_id, wallet_grant_id, failure_reason, + recharged_at_ms, granted_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', '', ?, 0, ?, ?)`, + appcode.FromContext(ctx), claim.ClaimID, claim.EventID, claim.TransactionID, claim.CommandID, claim.UserID, + claim.TierID, claim.TierCode, claim.ResourceGroupID, claim.RechargeCoinAmount, claim.RechargeSequence, + claim.RechargeType, claim.Status, claim.WalletCommandID, claim.RechargedAtMS, claim.CreatedAtMS, claim.UpdatedAtMS, + ) + return err +} + +func (r *Repository) updateFirstRechargeRewardClaimPending(ctx context.Context, tx *sql.Tx, claimID string, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + UPDATE first_recharge_reward_claims + SET status = 'pending', + wallet_grant_id = '', + failure_reason = '', + granted_at_ms = 0, + updated_at_ms = ? + WHERE app_code = ? AND claim_id = ? AND status = 'failed'`, + nowMS, appcode.FromContext(ctx), claimID, + ) + return err +} + +func scanFirstRechargeRewardConfig(row rowScanner) (domain.Config, error) { + var config domain.Config + err := row.Scan(&config.AppCode, &config.Enabled, &config.UpdatedByAdminID, &config.CreatedAtMS, &config.UpdatedAtMS) + return config, err +} + +func scanFirstRechargeRewardTiers(rows *sql.Rows) ([]domain.Tier, error) { + items := make([]domain.Tier, 0) + for rows.Next() { + var item domain.Tier + if err := rows.Scan( + &item.TierID, + &item.TierCode, + &item.TierName, + &item.MinCoinAmount, + &item.MaxCoinAmount, + &item.ResourceGroupID, + &item.Status, + &item.SortOrder, + &item.CreatedAtMS, + &item.UpdatedAtMS, + ); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +func scanFirstRechargeRewardClaims(rows *sql.Rows, total int64) ([]domain.Claim, int64, error) { + items := make([]domain.Claim, 0) + for rows.Next() { + item, err := scanFirstRechargeRewardClaim(rows) + if err != nil { + return nil, 0, err + } + items = append(items, item) + } + if err := rows.Err(); err != nil { + return nil, 0, err + } + return items, total, nil +} + +func scanFirstRechargeRewardClaim(row rowScanner) (domain.Claim, error) { + var claim domain.Claim + err := row.Scan( + &claim.ClaimID, + &claim.EventID, + &claim.TransactionID, + &claim.CommandID, + &claim.UserID, + &claim.TierID, + &claim.TierCode, + &claim.ResourceGroupID, + &claim.RechargeCoinAmount, + &claim.RechargeSequence, + &claim.RechargeType, + &claim.Status, + &claim.WalletCommandID, + &claim.WalletGrantID, + &claim.FailureReason, + &claim.RechargedAtMS, + &claim.GrantedAtMS, + &claim.CreatedAtMS, + &claim.UpdatedAtMS, + ) + return claim, err +} + +func firstRechargeRewardConfigSelectSQL() string { + return `SELECT app_code, enabled, updated_by_admin_id, created_at_ms, updated_at_ms + FROM first_recharge_reward_configs ` +} + +func firstRechargeRewardTierSelectSQL() string { + return `SELECT tier_id, tier_code, tier_name, min_coin_amount, max_coin_amount, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + FROM first_recharge_reward_tiers ` +} + +func firstRechargeRewardClaimSelectSQL() string { + return `SELECT claim_id, event_id, transaction_id, command_id, user_id, tier_id, tier_code, + resource_group_id, recharge_coin_amount, recharge_sequence, recharge_type, + status, wallet_command_id, wallet_grant_id, failure_reason, recharged_at_ms, + granted_at_ms, created_at_ms, updated_at_ms + FROM first_recharge_reward_claims ` +} + +func firstRechargeRewardClaimWhere(ctx context.Context, query domain.ClaimQuery) (string, []any) { + conditions := []string{"app_code = ?"} + args := []any{appcode.FromContext(ctx)} + if query.Status != "" { + conditions = append(conditions, "status = ?") + args = append(args, query.Status) + } + if query.UserID > 0 { + conditions = append(conditions, "user_id = ?") + args = append(args, query.UserID) + } + return "WHERE " + strings.Join(conditions, " AND "), args +} + +func matchFirstRechargeRewardTier(tiers []domain.Tier, coinAmount int64) (domain.Tier, bool) { + for _, tier := range tiers { + if tier.Status != domain.TierStatusActive || tier.ResourceGroupID <= 0 || tier.MinCoinAmount <= 0 { + continue + } + if coinAmount < tier.MinCoinAmount { + continue + } + if tier.MaxCoinAmount > 0 && coinAmount > tier.MaxCoinAmount { + continue + } + return tier, true + } + return domain.Tier{}, false +} + +func walletFirstRechargeRewardCommandID(claimID string) string { + return fmt.Sprintf("wfr_%s", claimID) +} diff --git a/services/activity-service/internal/storage/mysql/first_recharge_wallet_outbox_reader.go b/services/activity-service/internal/storage/mysql/first_recharge_wallet_outbox_reader.go new file mode 100644 index 00000000..47173b5f --- /dev/null +++ b/services/activity-service/internal/storage/mysql/first_recharge_wallet_outbox_reader.go @@ -0,0 +1,88 @@ +package mysql + +import ( + "context" + "database/sql" + "encoding/json" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/firstrecharge" +) + +// WalletRechargeOutboxReader 只读 wallet-service outbox,不反向修改钱包事实状态。 +type WalletRechargeOutboxReader struct { + db *sql.DB +} + +func NewWalletRechargeOutboxReader(db *sql.DB) *WalletRechargeOutboxReader { + return &WalletRechargeOutboxReader{db: db} +} + +// ListRechargeEventsAfter 按创建时间和 event_id 稳定读取成功充值事实。 +func (r *WalletRechargeOutboxReader) ListRechargeEventsAfter(ctx context.Context, cursor domain.WalletRechargeCursor, batchSize int) ([]domain.RechargeEvent, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "wallet outbox reader is not configured") + } + if batchSize <= 0 { + batchSize = 100 + } + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, event_id, event_type, transaction_id, command_id, user_id, + available_delta, COALESCE(CAST(payload AS CHAR), '{}'), created_at_ms + FROM wallet_outbox + WHERE event_type = ? + AND (created_at_ms > ? OR (created_at_ms = ? AND event_id > ?)) + ORDER BY created_at_ms ASC, event_id ASC + LIMIT ?`, + domain.RechargeEventWalletRecorded, cursor.CreatedAtMS, cursor.CreatedAtMS, cursor.EventID, batchSize, + ) + if err != nil { + return nil, err + } + defer rows.Close() + + events := make([]domain.RechargeEvent, 0, batchSize) + for rows.Next() { + var event domain.RechargeEvent + if err := rows.Scan( + &event.AppCode, + &event.EventID, + &event.EventType, + &event.TransactionID, + &event.CommandID, + &event.UserID, + &event.RechargeCoinAmount, + &event.PayloadJSON, + &event.OccurredAtMS, + ); err != nil { + return nil, err + } + event.AppCode = appcode.Normalize(event.AppCode) + event.RechargeSequence, event.RechargeType = rechargeFactFromPayload(event.PayloadJSON) + events = append(events, event) + } + return events, rows.Err() +} + +func rechargeFactFromPayload(payload string) (int64, string) { + var decoded map[string]any + if err := json.Unmarshal([]byte(payload), &decoded); err != nil { + return 0, domain.RechargeTypeCoinSeller + } + sequence := int64(0) + switch value := decoded["recharge_sequence"].(type) { + case float64: + sequence = int64(value) + case int64: + sequence = value + case json.Number: + sequence, _ = value.Int64() + } + rechargeType := domain.RechargeTypeCoinSeller + if value, ok := decoded["recharge_type"].(string); ok && strings.TrimSpace(value) != "" { + rechargeType = strings.TrimSpace(value) + } + return sequence, rechargeType +} diff --git a/services/activity-service/internal/transport/grpc/first_recharge_server.go b/services/activity-service/internal/transport/grpc/first_recharge_server.go new file mode 100644 index 00000000..7fd7b67c --- /dev/null +++ b/services/activity-service/internal/transport/grpc/first_recharge_server.go @@ -0,0 +1,189 @@ +package grpc + +import ( + "context" + + activityv1 "hyapp.local/api/proto/activity/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/firstrecharge" + service "hyapp/services/activity-service/internal/service/firstrecharge" +) + +// FirstRechargeRewardServer 暴露 App 首冲奖励查询和内部充值事实消费入口。 +type FirstRechargeRewardServer struct { + activityv1.UnimplementedFirstRechargeRewardServiceServer + + svc *service.Service +} + +func NewFirstRechargeRewardServer(svc *service.Service) *FirstRechargeRewardServer { + return &FirstRechargeRewardServer{svc: svc} +} + +func (s *FirstRechargeRewardServer) GetFirstRechargeRewardStatus(ctx context.Context, req *activityv1.GetFirstRechargeRewardStatusRequest) (*activityv1.GetFirstRechargeRewardStatusResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + status, err := s.svc.GetStatus(ctx, req.GetUserId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetFirstRechargeRewardStatusResponse{Status: firstRechargeRewardStatusToProto(status)}, nil +} + +func (s *FirstRechargeRewardServer) ConsumeFirstRechargeReward(ctx context.Context, req *activityv1.ConsumeFirstRechargeRewardRequest) (*activityv1.ConsumeFirstRechargeRewardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + claim, consumed, reason, err := s.svc.Consume(ctx, domain.RechargeEvent{ + AppCode: req.GetMeta().GetAppCode(), + EventID: req.GetEventId(), + TransactionID: req.GetTransactionId(), + CommandID: req.GetCommandId(), + UserID: req.GetUserId(), + RechargeCoinAmount: req.GetRechargeCoinAmount(), + RechargeSequence: req.GetRechargeSequence(), + RechargeType: req.GetRechargeType(), + OccurredAtMS: req.GetOccurredAtMs(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.ConsumeFirstRechargeRewardResponse{ + Claim: firstRechargeRewardClaimToProto(claim), + Consumed: consumed, + Reason: reason, + }, nil +} + +// AdminFirstRechargeRewardServer 暴露后台配置和发放记录查询入口。 +type AdminFirstRechargeRewardServer struct { + activityv1.UnimplementedAdminFirstRechargeRewardServiceServer + + svc *service.Service +} + +func NewAdminFirstRechargeRewardServer(svc *service.Service) *AdminFirstRechargeRewardServer { + return &AdminFirstRechargeRewardServer{svc: svc} +} + +func (s *AdminFirstRechargeRewardServer) GetFirstRechargeRewardConfig(ctx context.Context, req *activityv1.GetFirstRechargeRewardConfigRequest) (*activityv1.GetFirstRechargeRewardConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + config, err := s.svc.GetConfig(ctx) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetFirstRechargeRewardConfigResponse{Config: firstRechargeRewardConfigToProto(config)}, nil +} + +func (s *AdminFirstRechargeRewardServer) UpdateFirstRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateFirstRechargeRewardConfigRequest) (*activityv1.UpdateFirstRechargeRewardConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + tiers := make([]domain.Tier, 0, len(req.GetTiers())) + for _, tier := range req.GetTiers() { + tiers = append(tiers, domain.Tier{ + TierID: tier.GetTierId(), + TierCode: tier.GetTierCode(), + TierName: tier.GetTierName(), + MinCoinAmount: tier.GetMinCoinAmount(), + MaxCoinAmount: tier.GetMaxCoinAmount(), + ResourceGroupID: tier.GetResourceGroupId(), + Status: tier.GetStatus(), + SortOrder: tier.GetSortOrder(), + }) + } + config, err := s.svc.UpdateConfig(ctx, domain.Config{ + Enabled: req.GetEnabled(), + Tiers: tiers, + UpdatedByAdminID: req.GetOperatorAdminId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.UpdateFirstRechargeRewardConfigResponse{Config: firstRechargeRewardConfigToProto(config)}, nil +} + +func (s *AdminFirstRechargeRewardServer) ListFirstRechargeRewardClaims(ctx context.Context, req *activityv1.ListFirstRechargeRewardClaimsRequest) (*activityv1.ListFirstRechargeRewardClaimsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + claims, total, err := s.svc.ListClaims(ctx, domain.ClaimQuery{ + Status: req.GetStatus(), + UserID: req.GetUserId(), + Page: req.GetPage(), + PageSize: req.GetPageSize(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListFirstRechargeRewardClaimsResponse{Claims: make([]*activityv1.FirstRechargeRewardClaim, 0, len(claims)), Total: total} + for _, claim := range claims { + resp.Claims = append(resp.Claims, firstRechargeRewardClaimToProto(claim)) + } + return resp, nil +} + +func firstRechargeRewardStatusToProto(status domain.StatusResult) *activityv1.FirstRechargeRewardStatus { + resp := &activityv1.FirstRechargeRewardStatus{ + Enabled: status.Enabled, + Tiers: make([]*activityv1.FirstRechargeRewardTier, 0, len(status.Tiers)), + Rewarded: status.Rewarded, + Claim: firstRechargeRewardClaimToProto(status.Claim), + ServerTimeMs: status.ServerTimeMS, + } + for _, tier := range status.Tiers { + resp.Tiers = append(resp.Tiers, firstRechargeRewardTierToProto(tier)) + } + return resp +} + +func firstRechargeRewardConfigToProto(config domain.Config) *activityv1.FirstRechargeRewardConfig { + resp := &activityv1.FirstRechargeRewardConfig{ + AppCode: config.AppCode, + Enabled: config.Enabled, + Tiers: make([]*activityv1.FirstRechargeRewardTier, 0, len(config.Tiers)), + UpdatedByAdminId: config.UpdatedByAdminID, + CreatedAtMs: config.CreatedAtMS, + UpdatedAtMs: config.UpdatedAtMS, + } + for _, tier := range config.Tiers { + resp.Tiers = append(resp.Tiers, firstRechargeRewardTierToProto(tier)) + } + return resp +} + +func firstRechargeRewardTierToProto(tier domain.Tier) *activityv1.FirstRechargeRewardTier { + return &activityv1.FirstRechargeRewardTier{ + TierId: tier.TierID, + TierCode: tier.TierCode, + TierName: tier.TierName, + MinCoinAmount: tier.MinCoinAmount, + MaxCoinAmount: tier.MaxCoinAmount, + ResourceGroupId: tier.ResourceGroupID, + Status: tier.Status, + SortOrder: tier.SortOrder, + CreatedAtMs: tier.CreatedAtMS, + UpdatedAtMs: tier.UpdatedAtMS, + } +} + +func firstRechargeRewardClaimToProto(claim domain.Claim) *activityv1.FirstRechargeRewardClaim { + if claim.ClaimID == "" { + return nil + } + return &activityv1.FirstRechargeRewardClaim{ + ClaimId: claim.ClaimID, + EventId: claim.EventID, + TransactionId: claim.TransactionID, + CommandId: claim.CommandID, + UserId: claim.UserID, + TierId: claim.TierID, + TierCode: claim.TierCode, + ResourceGroupId: claim.ResourceGroupID, + RechargeCoinAmount: claim.RechargeCoinAmount, + RechargeSequence: claim.RechargeSequence, + RechargeType: claim.RechargeType, + Status: claim.Status, + WalletCommandId: claim.WalletCommandID, + WalletGrantId: claim.WalletGrantID, + FailureReason: claim.FailureReason, + RechargedAtMs: claim.RechargedAtMS, + GrantedAtMs: claim.GrantedAtMS, + CreatedAtMs: claim.CreatedAtMS, + UpdatedAtMs: claim.UpdatedAtMS, + } +} diff --git a/services/game-service/internal/domain/game/game.go b/services/game-service/internal/domain/game/game.go index cd656e71..748581ab 100644 --- a/services/game-service/internal/domain/game/game.go +++ b/services/game-service/internal/domain/game/game.go @@ -13,6 +13,7 @@ const ( AdapterDemo = "demo" AdapterYomiV4 = "yomi_v4" AdapterLeaderCCV1 = "leadercc_v1" + AdapterZeeOneV1 = "zeeone_v1" OrderStatusWalletApplying = "wallet_applying" OrderStatusSucceeded = "succeeded" diff --git a/services/game-service/internal/service/game/app_token_session.go b/services/game-service/internal/service/game/app_token_session.go new file mode 100644 index 00000000..ab4b6ff5 --- /dev/null +++ b/services/game-service/internal/service/game/app_token_session.go @@ -0,0 +1,54 @@ +package game + +import ( + "strconv" + "strings" + + jwt "github.com/golang-jwt/jwt/v5" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + gamedomain "hyapp/services/game-service/internal/domain/game" +) + +func (s *Service) appSessionFromAccessToken(app string, token string) (gamedomain.LaunchSession, error) { + // ZeeOne/灵仙都直接把 App access token 作为厂商 sessionId/token;game-service 不持有 JWT secret, + // 这里只消费 token 内部用户快照并校验 exp/app_code,入口签名仍由厂商 AppSecret 负责。 + claims := jwt.MapClaims{} + _, _, err := new(jwt.Parser).ParseUnverified(strings.TrimSpace(token), claims) + if err != nil { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") + } + if typ := strings.TrimSpace(jwtStringClaim(claims, "typ")); typ != "" && typ != "access" { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") + } + expiresAt, err := claims.GetExpirationTime() + if err != nil || expiresAt == nil || !expiresAt.After(s.now()) { + return gamedomain.LaunchSession{}, xerr.New(xerr.SessionExpired, "token expired") + } + tokenApp := appcode.Normalize(jwtStringClaim(claims, "app_code")) + if tokenApp != "" && tokenApp != appcode.Normalize(app) { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") + } + userID, err := strconv.ParseInt(strings.TrimSpace(jwtStringClaim(claims, "user_id")), 10, 64) + if err != nil || userID <= 0 { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") + } + displayUserID := firstNonEmpty( + jwtStringClaim(claims, "display_user_id"), + jwtStringClaim(claims, "default_display_user_id"), + strconv.FormatInt(userID, 10), + ) + return gamedomain.LaunchSession{ + AppCode: tokenApp, + SessionID: jwtStringClaim(claims, "sid"), + UserID: userID, + DisplayUserID: displayUserID, + Status: gamedomain.SessionActive, + ExpiresAtMS: expiresAt.UnixMilli(), + }, nil +} + +func jwtStringClaim(claims jwt.MapClaims, key string) string { + value, _ := claims[key].(string) + return strings.TrimSpace(value) +} diff --git a/services/game-service/internal/service/game/leadercc_adapter.go b/services/game-service/internal/service/game/leadercc_adapter.go index f3ee7fa8..8c58e2aa 100644 --- a/services/game-service/internal/service/game/leadercc_adapter.go +++ b/services/game-service/internal/service/game/leadercc_adapter.go @@ -9,9 +9,7 @@ import ( "strings" "time" - jwt "github.com/golang-jwt/jwt/v5" gamev1 "hyapp.local/api/proto/game/v1" - "hyapp/pkg/appcode" "hyapp/pkg/xerr" gamedomain "hyapp/services/game-service/internal/domain/game" ) @@ -239,7 +237,7 @@ func (s *Service) handleLeaderCCRepairOrder(ctx context.Context, app string, pla func (s *Service) validLeaderCCSession(ctx context.Context, app string, token string) (gamedomain.LaunchSession, error) { // 灵仙回调直接使用 App 登录 access token;无需预先进入游戏创建 launch session。 if strings.Count(strings.TrimSpace(token), ".") == 2 { - return s.leaderccSessionFromAppToken(app, token) + return s.appSessionFromAccessToken(app, token) } // 兼容历史联调 token:老链路会先 launch,再按 game_launch_sessions 校验。 session, err := s.validYomiSession(ctx, app, token) @@ -260,42 +258,6 @@ func leaderccSessionMatches(session gamedomain.LaunchSession, config leaderccAda normalizedUID == strconv.FormatInt(session.UserID, 10) } -func (s *Service) leaderccSessionFromAppToken(app string, token string) (gamedomain.LaunchSession, error) { - claims := jwt.MapClaims{} - _, _, err := new(jwt.Parser).ParseUnverified(strings.TrimSpace(token), claims) - if err != nil { - return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") - } - if typ := strings.TrimSpace(leaderccStringClaim(claims, "typ")); typ != "" && typ != "access" { - return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") - } - expiresAt, err := claims.GetExpirationTime() - if err != nil || expiresAt == nil || !expiresAt.After(s.now()) { - return gamedomain.LaunchSession{}, xerr.New(xerr.SessionExpired, "token expired") - } - tokenApp := appcode.Normalize(leaderccStringClaim(claims, "app_code")) - if tokenApp != "" && tokenApp != appcode.Normalize(app) { - return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") - } - userID, err := strconv.ParseInt(strings.TrimSpace(leaderccStringClaim(claims, "user_id")), 10, 64) - if err != nil || userID <= 0 { - return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") - } - displayUserID := firstNonEmpty( - leaderccStringClaim(claims, "display_user_id"), - leaderccStringClaim(claims, "default_display_user_id"), - strconv.FormatInt(userID, 10), - ) - return gamedomain.LaunchSession{ - AppCode: tokenApp, - SessionID: leaderccStringClaim(claims, "sid"), - UserID: userID, - DisplayUserID: displayUserID, - Status: gamedomain.SessionActive, - ExpiresAtMS: expiresAt.UnixMilli(), - }, nil -} - func leaderccOpType(value int32) string { // 厂商枚举在适配器内结束,下游钱包只认识 debit/credit。 switch value { @@ -344,11 +306,6 @@ func leaderccTokenOnlyProbe(token string, parts ...string) bool { return true } -func leaderccStringClaim(claims jwt.MapClaims, key string) string { - value, _ := claims[key].(string) - return strings.TrimSpace(value) -} - func leaderccAdapterError(code int, message string, signatureValid bool, providerRequestID string) ([]byte, string, string, bool, string, error) { // signatureValid/providerRequestID 会写入 callback log,帮助后续排查签名和重复订单问题。 raw, contentType := leaderccJSON(code, message, map[string]any{}) diff --git a/services/game-service/internal/service/game/service.go b/services/game-service/internal/service/game/service.go index 200789c8..f476b0dc 100644 --- a/services/game-service/internal/service/game/service.go +++ b/services/game-service/internal/service/game/service.go @@ -186,7 +186,7 @@ func (s *Service) LaunchGame(ctx context.Context, command LaunchCommand) (Launch sessionID := "game_sess_" + strconv.FormatInt(now.UnixMilli(), 10) + "_" + randomHex(6) token := strings.TrimSpace(command.AccessToken) if token == "" { - if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) || strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) { + if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) || strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) { return LaunchResult{}, xerr.New(xerr.InvalidArgument, "access token is required for provider game launch") } token = "gt_" + randomHex(24) @@ -197,6 +197,8 @@ func (s *Service) LaunchGame(ctx context.Context, command LaunchCommand) (Launch sessionTTL = maxDuration(sessionTTL, yomiConfigFromPlatform(game).TokenTTL()) } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) { sessionTTL = maxDuration(sessionTTL, leaderccConfigFromPlatform(game).TokenTTL()) + } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) { + sessionTTL = maxDuration(sessionTTL, zeeoneConfigFromPlatform(game).TokenTTL()) } expiresAt := now.Add(sessionTTL).UnixMilli() session := gamedomain.LaunchSession{ @@ -261,6 +263,8 @@ func (s *Service) HandleCallback(ctx context.Context, req *gamev1.CallbackReques responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleYomiOperation(ctx, app, platform, req, operation, requestHash) case strings.EqualFold(platform.AdapterType, gamedomain.AdapterLeaderCCV1): responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleLeaderCCOperation(ctx, app, platform, req, operation, requestHash) + case strings.EqualFold(platform.AdapterType, gamedomain.AdapterZeeOneV1): + responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleZeeOneOperation(ctx, app, platform, req, operation, requestHash) default: responseBody, contentType, statusCode, err = s.handleDemoOperation(ctx, app, req, operation, requestHash) } @@ -553,7 +557,16 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes // 灵仙当前只需要我们提供回调域名和接口,不要求服务端拼 H5/Auth URL。 return "", nil } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) { + // ZeeOne 的测试/正式游戏经常是同商户多条 H5 地址,优先读后台 JSON 的按游戏覆盖配置。 + if configuredBase := zeeoneLaunchBaseURL(game, zeeoneConfigFromPlatform(game)); configuredBase != "" { + base = configuredBase + } + } if base == "" { + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) { + return "", xerr.New(xerr.InvalidArgument, "zeeone launch url is required") + } // demo 平台可以没有真实厂商域名,保留本地默认地址用于开发自测。 base = "https://game.example.local/h5" } @@ -601,6 +614,33 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes parsed.RawQuery = query.Encode() return parsed.String(), nil } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) { + // ZeeOne 直接加载指定游戏 H5,sessionId 使用 App access token,merchant/platform 来自后台热配置。 + config := zeeoneConfigFromPlatform(game) + lang := config.DefaultLang + if lang == "" { + lang = "en" + } + query.Set("sessionId", token) + query.Set("language", lang) + if config.MerchantID > 0 { + query.Set("merchant", strconv.FormatInt(config.MerchantID, 10)) + } + if config.PlatformID > 0 { + query.Set("platform", strconv.FormatInt(config.PlatformID, 10)) + } + if session.RoomID != "" { + query.Set("sid", session.RoomID) + } + if config.GameMode != "" { + query.Set("gameMode", config.GameMode) + } + if config.Extra != "" { + query.Set("extra", config.Extra) + } + parsed.RawQuery = query.Encode() + return parsed.String(), nil + } // demo adapter 保持内部调试参数完整,方便用一个简单 H5 验证 session 和订单链路。 query.Set("session_id", session.SessionID) query.Set("session_token", token) diff --git a/services/game-service/internal/service/game/service_test.go b/services/game-service/internal/service/game/service_test.go index 204de2bf..81d5279c 100644 --- a/services/game-service/internal/service/game/service_test.go +++ b/services/game-service/internal/service/game/service_test.go @@ -7,6 +7,7 @@ import ( "crypto/md5" "encoding/base64" "encoding/hex" + "encoding/json" "strconv" "strings" "testing" @@ -150,6 +151,81 @@ func TestLaunchGameBuildsLeaderCCURL(t *testing.T) { } } +func TestLaunchGameBuildsZeeOneURL(t *testing.T) { + repo := &fakeRepository{ + launchable: gamedomain.LaunchableGame{ + CatalogItem: gamedomain.CatalogItem{ + AppCode: "lalu", + GameID: "zeeone_gold_olympus", + PlatformCode: "zeeone", + ProviderGameID: "1021", + GameName: "Gold of Olympus", + Status: gamedomain.StatusActive, + Orientation: "portrait", + }, + PlatformStatus: gamedomain.StatusActive, + APIBaseURL: "https://fallback.example.invalid/game.html", + AdapterType: gamedomain.AdapterZeeOneV1, + AdapterConfigJSON: `{"merchant_id":307715,"platform_id":2032,"default_lang":"en","token_ttl_seconds":86400,"game_urls":{"1021":"https://dx3kkv99b7clg.cloudfront.net/test/1021_gold_of_olympus/index.html?merchant=0&platform=0"}}`, + }, + } + svc := New(Config{LaunchSessionTTL: 15 * time.Minute}, repo, &fakeWallet{}, &fakeUser{}) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + result, err := svc.LaunchGame(context.Background(), LaunchCommand{ + AppCode: "lalu", + UserID: 42, + DisplayUserID: "420001", + GameID: "zeeone_gold_olympus", + RoomID: "01", + AccessToken: "app_access_token_zeeone", + }) + if err != nil { + t.Fatalf("LaunchGame failed: %v", err) + } + if result.ExpiresAtMS != 1700086400000 { + t.Fatalf("zeeone launch must use adapter token ttl, got %+v", result) + } + if !strings.HasPrefix(result.LaunchURL, "https://dx3kkv99b7clg.cloudfront.net/test/1021_gold_of_olympus/index.html?") { + t.Fatalf("zeeone launch url must use per-game configured url: %s", result.LaunchURL) + } + for _, part := range []string{"sessionId=app_access_token_zeeone", "language=en", "merchant=307715", "platform=2032", "sid=01"} { + if !strings.Contains(result.LaunchURL, part) { + t.Fatalf("zeeone launch url missing %s: %s", part, result.LaunchURL) + } + } +} + +func TestLaunchGameRequiresZeeOneLaunchURL(t *testing.T) { + repo := &fakeRepository{ + launchable: gamedomain.LaunchableGame{ + CatalogItem: gamedomain.CatalogItem{ + AppCode: "lalu", + GameID: "zeeone_unknown", + PlatformCode: "zeeone", + ProviderGameID: "9999", + GameName: "Unknown ZeeOne Game", + Status: gamedomain.StatusActive, + }, + PlatformStatus: gamedomain.StatusActive, + AdapterType: gamedomain.AdapterZeeOneV1, + AdapterConfigJSON: `{"merchant_id":307715,"platform_id":2032}`, + }, + } + svc := New(Config{LaunchSessionTTL: 15 * time.Minute}, repo, &fakeWallet{}, &fakeUser{}) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + _, err := svc.LaunchGame(context.Background(), LaunchCommand{ + AppCode: "lalu", + UserID: 42, + GameID: "zeeone_unknown", + AccessToken: "app_access_token_zeeone", + }) + if err == nil || !strings.Contains(xerr.MessageOf(err), "zeeone launch url is required") { + t.Fatalf("LaunchGame must reject missing zeeone launch url, got %v", err) + } +} + func TestLaunchGameAllowsLeaderCCWithoutLaunchURL(t *testing.T) { repo := &fakeRepository{ launchable: gamedomain.LaunchableGame{ @@ -475,6 +551,71 @@ func TestHandleYomiRepairOrderOnlyLogs(t *testing.T) { } } +func TestHandleZeeOneUserInfoChangeBalanceAndUpdateSession(t *testing.T) { + secret := "zeeone-test-secret" + token := leaderccTestAccessToken(t, "lalu", 42, "420001", 1700003600) + repo := &fakeRepository{ + platform: gamedomain.Platform{ + PlatformCode: "zeeone", + AdapterType: gamedomain.AdapterZeeOneV1, + CallbackSecretCiphertext: secret, + AdapterConfigJSON: `{"merchant_id":307715,"platform_id":2032,"uid_mode":"display_user_id"}`, + }, + } + wallet := &fakeWallet{balanceAfter: 1880} + user := &fakeUser{} + svc := New(Config{}, repo, wallet, user) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + userBody := `{"appId":"M307715_P2032","userId":"420001","sessionId":"` + token + `","game_id":1021,"extra":"{\"vip\":1}"}` + raw, contentType, err := svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zeeone-user", AppCode: "lalu"}, + PlatformCode: "zeeone", + Operation: "get_user_info", + RawBody: zeeoneTestEnvelope(t, secret, userBody, 1700000000000), + }) + if err != nil { + t.Fatalf("HandleCallback userinfo failed: %v", err) + } + if contentType != "application/json" || !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"balance":1880`) || !strings.Contains(string(raw), `"sessionId"`) { + t.Fatalf("zeeone userinfo response mismatch: %s", raw) + } + if user.lastGet.GetUserId() != 42 { + t.Fatalf("zeeone userinfo must query token user, got %+v", user.lastGet) + } + + changeBody := `{"appId":"M307715_P2032","userId":"420001","sessionId":"` + token + `","currency_diff":-120,"diff_msg":"bet","game_id":1021,"room_id":"01","change_time_at":1700000000,"order_id":"zee_order_1","extend":"round_1"}` + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zeeone-change", AppCode: "lalu"}, + PlatformCode: "zeeone", + Operation: "change_balance", + RawBody: zeeoneTestEnvelope(t, secret, changeBody, 1700000000000), + }) + if err != nil { + t.Fatalf("HandleCallback change failed: %v", err) + } + if !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"currency_balance":1880`) { + t.Fatalf("zeeone change response mismatch: %s", raw) + } + if wallet.lastApply.GetUserId() != 42 || wallet.lastApply.GetOpType() != "debit" || wallet.lastApply.GetCoinAmount() != 120 || wallet.lastApply.GetGameId() != "1021" { + t.Fatalf("zeeone wallet command mismatch: %+v", wallet.lastApply) + } + + updateBody := `{"appId":"M307715_P2032","userId":"420001","sessionId":"` + token + `","game_id":1021}` + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-zeeone-update-session", AppCode: "lalu"}, + PlatformCode: "zeeone", + Operation: "update_session", + RawBody: zeeoneTestEnvelope(t, secret, updateBody, 1700000000000), + }) + if err != nil { + t.Fatalf("HandleCallback update_session failed: %v", err) + } + if !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"expireDate":1700003600000`) { + t.Fatalf("zeeone update_session response mismatch: %s", raw) + } +} + func TestHandleCallbackChangeCoinUsesWalletAndOrderIdempotency(t *testing.T) { repo := &fakeRepository{ launchable: gamedomain.LaunchableGame{CatalogItem: gamedomain.CatalogItem{GameID: "demo_rocket_001", ProviderGameID: "rocket_001"}}, @@ -771,3 +912,16 @@ func leaderccTestAccessToken(t *testing.T, app string, userID int64, displayUser } return signed } + +func zeeoneTestEnvelope(t *testing.T, secret string, body string, timestamp int64) []byte { + t.Helper() + nonce := "5f0eb04d7603a9d8" + raw := nonce + body + strconv.FormatInt(timestamp, 10) + secret + sum := md5.Sum([]byte(raw)) + signature := hex.EncodeToString(sum[:]) + encodedBody, err := json.Marshal(body) + if err != nil { + t.Fatalf("marshal reqbody: %v", err) + } + return []byte(`{"reqbody":` + string(encodedBody) + `,"signature":"` + signature + `","signature_nonce":"` + nonce + `","timestamp":` + strconv.FormatInt(timestamp, 10) + `}`) +} diff --git a/services/game-service/internal/service/game/zeeone_adapter.go b/services/game-service/internal/service/game/zeeone_adapter.go new file mode 100644 index 00000000..30eaa7cd --- /dev/null +++ b/services/game-service/internal/service/game/zeeone_adapter.go @@ -0,0 +1,408 @@ +package game + +import ( + "context" + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "strconv" + "strings" + "time" + + gamev1 "hyapp.local/api/proto/game/v1" + "hyapp/pkg/xerr" + gamedomain "hyapp/services/game-service/internal/domain/game" +) + +const ( + // ZeeOne 文档定义 code=0 成功;HTTP 200 不代表业务成功,游戏侧读取 JSON code。 + zeeoneCodeOK = 0 + zeeoneCodeInvalidArgument = 1 + zeeoneCodeSessionNotFound = 2 + zeeoneCodeSignatureInvalid = 3 + zeeoneCodeSessionInvalid = 5 + zeeoneCodeInsufficientBalance = 6 + + zeeoneDefaultTokenTTL = 24 * time.Hour + zeeoneSignatureValidWindow = 15 * time.Second + zeeoneDefaultSuccessMessage = "succeed" +) + +type zeeoneAdapterConfig struct { + // merchant_id/platform_id 来自 ZeeOne 商户后台;启动 URL 和 appId 校验都依赖这两个值。 + MerchantID int64 `json:"merchant_id"` + PlatformID int64 `json:"platform_id"` + PlatformIDAlias int64 `json:"platform"` + AppID string `json:"app_id"` + UIDMode string `json:"uid_mode"` + DefaultLang string `json:"default_lang"` + TokenTTLSeconds int64 `json:"token_ttl_seconds"` + GameMode string `json:"game_mode"` + Extra string `json:"extra"` + // game_urls 解决同一个 ZeeOne 商户下每款游戏 H5 域名/路径不同的问题;后台改 JSON 后下一次启动即生效。 + GameURLs map[string]string `json:"game_urls"` + // launch_url_template 适合 ZeeOne 后续按固定路径批量上新,支持 {provider_game_id}/{providerGameId}/{game_id}/{gameId} 占位。 + LaunchURLTemplate string `json:"launch_url_template"` +} + +func zeeoneConfigFromPlatform(value any) zeeoneAdapterConfig { + var raw string + switch typed := value.(type) { + case gamedomain.Platform: + raw = typed.AdapterConfigJSON + case gamedomain.LaunchableGame: + raw = typed.AdapterConfigJSON + } + var config zeeoneAdapterConfig + _ = json.Unmarshal([]byte(strings.TrimSpace(raw)), &config) + if config.PlatformID == 0 { + config.PlatformID = config.PlatformIDAlias + } + config.AppID = strings.TrimSpace(config.AppID) + config.UIDMode = strings.ToLower(strings.TrimSpace(config.UIDMode)) + config.DefaultLang = strings.TrimSpace(config.DefaultLang) + config.GameMode = strings.TrimSpace(config.GameMode) + config.Extra = strings.TrimSpace(config.Extra) + config.LaunchURLTemplate = strings.TrimSpace(config.LaunchURLTemplate) + config.GameURLs = normalizeStringMap(config.GameURLs) + return config +} + +func (c zeeoneAdapterConfig) TokenTTL() time.Duration { + if c.TokenTTLSeconds > 0 { + return time.Duration(c.TokenTTLSeconds) * time.Second + } + return zeeoneDefaultTokenTTL +} + +func (c zeeoneAdapterConfig) ExpectedAppID() string { + if c.AppID != "" { + return c.AppID + } + if c.MerchantID > 0 && c.PlatformID > 0 { + return fmt.Sprintf("M%d_P%d", c.MerchantID, c.PlatformID) + } + return "" +} + +func zeeoneLaunchBaseURL(game gamedomain.LaunchableGame, config zeeoneAdapterConfig) string { + for _, key := range []string{game.ProviderGameID, game.GameID, strings.ToLower(game.GameID)} { + if raw := strings.TrimSpace(config.GameURLs[strings.TrimSpace(key)]); raw != "" { + return raw + } + } + if config.LaunchURLTemplate == "" { + return "" + } + replacer := strings.NewReplacer( + "{provider_game_id}", strings.TrimSpace(game.ProviderGameID), + "{providerGameId}", strings.TrimSpace(game.ProviderGameID), + "{game_id}", strings.TrimSpace(game.GameID), + "{gameId}", strings.TrimSpace(game.GameID), + ) + return strings.TrimSpace(replacer.Replace(config.LaunchURLTemplate)) +} + +func normalizeStringMap(input map[string]string) map[string]string { + if len(input) == 0 { + return nil + } + output := make(map[string]string, len(input)) + for key, value := range input { + key = strings.TrimSpace(key) + value = strings.TrimSpace(value) + if key != "" && value != "" { + output[key] = value + } + } + if len(output) == 0 { + return nil + } + return output +} + +func (s *Service) handleZeeOneOperation(ctx context.Context, app string, platform gamedomain.Platform, req *gamev1.CallbackRequest, operation string, requestHash string) ([]byte, string, string, bool, string, error) { + config := zeeoneConfigFromPlatform(platform) + body, signed, decoded, providerRequestID := s.decodeZeeOneSignedBody(platform, req) + if !signed { + raw, contentType := zeeoneJSON(zeeoneCodeSignatureInvalid, "signature invalid", map[string]any{}) + return raw, contentType, strconv.Itoa(zeeoneCodeSignatureInvalid), false, providerRequestID, nil + } + if !decoded { + raw, contentType := zeeoneJSON(zeeoneCodeInvalidArgument, "invalid argument", map[string]any{}) + return raw, contentType, strconv.Itoa(zeeoneCodeInvalidArgument), signed, providerRequestID, nil + } + if err := validateZeeOneAppID(config, body.AppID); err != nil { + raw, contentType := zeeoneJSON(zeeoneCodeInvalidArgument, "invalid appId", map[string]any{}) + return raw, contentType, strconv.Itoa(zeeoneCodeInvalidArgument), signed, providerRequestID, nil + } + switch operation { + case "get_user_info", "userinfo", "user_info": + return s.handleZeeOneUserInfo(ctx, app, config, req, body) + case "change_balance", "change_coin", "update_coin": + return s.handleZeeOneChangeBalance(ctx, app, config, req, body, requestHash) + case "update_session", "refresh_session": + return s.handleZeeOneUpdateSession(ctx, app, config, body) + case "repair_order", "repair": + return s.handleZeeOneRepairOrder(ctx, app, platform, body) + default: + raw, contentType := zeeoneJSON(zeeoneCodeOK, zeeoneDefaultSuccessMessage, map[string]any{}) + return raw, contentType, strconv.Itoa(zeeoneCodeOK), signed, providerRequestID, nil + } +} + +type zeeoneSignedEnvelope struct { + ReqBody string `json:"reqbody"` + Signature string `json:"signature"` + SignatureNonce string `json:"signature_nonce"` + Timestamp int64 `json:"timestamp"` +} + +type zeeoneBusinessBody struct { + AppID string `json:"appId"` + UserID string `json:"userId"` + SessionID string `json:"sessionId"` + Extra string `json:"extra"` + CurrencyDiff int64 `json:"currency_diff"` + DiffMsg string `json:"diff_msg"` + GameID int64 `json:"game_id"` + RoomID string `json:"room_id"` + ChangeTimeAt int64 `json:"change_time_at"` + OrderID string `json:"order_id"` + Extend string `json:"extend"` +} + +func (s *Service) decodeZeeOneSignedBody(platform gamedomain.Platform, req *gamev1.CallbackRequest) (zeeoneBusinessBody, bool, bool, string) { + var envelope zeeoneSignedEnvelope + if err := json.Unmarshal(req.GetRawBody(), &envelope); err != nil { + return zeeoneBusinessBody{}, false, false, "" + } + envelope.ReqBody = strings.TrimSpace(envelope.ReqBody) + providerRequestID := zeeoneProviderRequestID(envelope.ReqBody) + if !s.zeeoneSignatureValid(envelope, platform.CallbackSecretCiphertext) { + return zeeoneBusinessBody{}, false, false, providerRequestID + } + var body zeeoneBusinessBody + decoder := json.NewDecoder(strings.NewReader(envelope.ReqBody)) + decoder.UseNumber() + if err := decoder.Decode(&body); err != nil { + return zeeoneBusinessBody{}, false, true, providerRequestID + } + body.normalize() + return body, true, true, firstNonEmpty(body.OrderID, providerRequestID) +} + +func (s *Service) zeeoneSignatureValid(envelope zeeoneSignedEnvelope, secret string) bool { + secret = strings.TrimSpace(secret) + if secret == "" || envelope.ReqBody == "" || strings.TrimSpace(envelope.SignatureNonce) == "" || envelope.Timestamp <= 0 { + return false + } + now := s.now() + requestAt := time.UnixMilli(envelope.Timestamp) + if requestAt.After(now.Add(zeeoneSignatureValidWindow)) || now.Sub(requestAt) > zeeoneSignatureValidWindow { + return false + } + raw := fmt.Sprintf("%s%s%d%s", strings.TrimSpace(envelope.SignatureNonce), envelope.ReqBody, envelope.Timestamp, secret) + sum := md5.Sum([]byte(raw)) + expected := hex.EncodeToString(sum[:]) + return strings.EqualFold(strings.TrimSpace(envelope.Signature), expected) +} + +func (body *zeeoneBusinessBody) normalize() { + body.AppID = strings.TrimSpace(body.AppID) + body.UserID = strings.TrimSpace(body.UserID) + body.SessionID = strings.TrimSpace(body.SessionID) + body.Extra = strings.TrimSpace(body.Extra) + body.DiffMsg = strings.ToLower(strings.TrimSpace(body.DiffMsg)) + body.RoomID = strings.TrimSpace(body.RoomID) + body.OrderID = strings.TrimSpace(body.OrderID) + body.Extend = strings.TrimSpace(body.Extend) +} + +func validateZeeOneAppID(config zeeoneAdapterConfig, appID string) error { + expected := config.ExpectedAppID() + if expected == "" || strings.TrimSpace(appID) == "" { + return nil + } + if strings.TrimSpace(appID) != expected { + return xerr.New(xerr.InvalidArgument, "appId mismatch") + } + return nil +} + +func (s *Service) handleZeeOneUserInfo(ctx context.Context, app string, config zeeoneAdapterConfig, req *gamev1.CallbackRequest, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) { + session, err := s.validZeeOneSession(ctx, app, body.SessionID) + if err != nil { + return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, "") + } + if !zeeoneSessionMatches(session, config, body.UserID, body.GameID) { + return zeeoneAdapterError(zeeoneCodeSessionInvalid, "sessionId invalid", true, "") + } + snapshot, err := s.yomiUserSnapshot(ctx, app, req, session.UserID) + if err != nil { + return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, "") + } + data := map[string]any{ + "userId": firstNonEmpty(body.UserID, externalUserID(session, config.UIDMode)), + "name": snapshot.Nickname, + "avatar": snapshot.Avatar, + "balance": snapshot.Balance, + "sessionId": body.SessionID, + "expireDate": session.ExpiresAtMS, + } + if body.Extra != "" { + data["extra"] = body.Extra + } + raw, contentType := zeeoneJSON(zeeoneCodeOK, zeeoneDefaultSuccessMessage, data) + return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, "", nil +} + +func (s *Service) handleZeeOneChangeBalance(ctx context.Context, app string, config zeeoneAdapterConfig, req *gamev1.CallbackRequest, body zeeoneBusinessBody, requestHash string) ([]byte, string, string, bool, string, error) { + if body.OrderID == "" || body.UserID == "" || body.SessionID == "" || body.GameID <= 0 || body.DiffMsg == "" { + return zeeoneAdapterError(zeeoneCodeInvalidArgument, "invalid argument", true, body.OrderID) + } + session, err := s.validZeeOneSession(ctx, app, body.SessionID) + if err != nil { + return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, body.OrderID) + } + if !zeeoneSessionMatches(session, config, body.UserID, body.GameID) { + return zeeoneAdapterError(zeeoneCodeSessionInvalid, "sessionId invalid", true, body.OrderID) + } + if session.ProviderGameID == "" { + session.ProviderGameID = strconv.FormatInt(body.GameID, 10) + } + if session.GameID == "" { + session.GameID = session.ProviderGameID + } + opType, amount := zeeoneOpType(body.CurrencyDiff) + result, err := s.applyYomiCoinChange(ctx, app, req, session, body.OrderID, strconv.FormatInt(body.ChangeTimeAt, 10), opType, amount, body.RoomID, requestHash) + if err != nil { + code := zeeoneCodeFromError(err) + balance := s.bestEffortCoinBalance(ctx, app, req.GetMeta().GetRequestId(), session.UserID) + raw, contentType := zeeoneJSON(code, zeeoneMessageFromError(err), map[string]any{"currency_balance": balance}) + return raw, contentType, strconv.Itoa(code), true, body.OrderID, nil + } + raw, contentType := zeeoneJSON(zeeoneCodeOK, zeeoneDefaultSuccessMessage, map[string]any{"currency_balance": result.BalanceAfter}) + return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, body.OrderID, nil +} + +func (s *Service) handleZeeOneUpdateSession(ctx context.Context, app string, config zeeoneAdapterConfig, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) { + session, err := s.validZeeOneSession(ctx, app, body.SessionID) + if err != nil { + return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, "") + } + if !zeeoneSessionMatches(session, config, body.UserID, body.GameID) { + return zeeoneAdapterError(zeeoneCodeSessionInvalid, "sessionId invalid", true, "") + } + raw, contentType := zeeoneJSON(zeeoneCodeOK, zeeoneDefaultSuccessMessage, map[string]any{ + "sessionId": body.SessionID, + "expireDate": session.ExpiresAtMS, + }) + return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, "", nil +} + +func (s *Service) handleZeeOneRepairOrder(ctx context.Context, app string, platform gamedomain.Platform, body zeeoneBusinessBody) ([]byte, string, string, bool, string, error) { + if body.OrderID != "" { + _, _, err := s.repository.CreateRepairOrder(ctx, gamedomain.RepairOrder{ + AppCode: app, + RepairID: "grep_" + stableHash(app+"|"+platform.PlatformCode+"|"+body.OrderID), + PlatformCode: platform.PlatformCode, + ProviderOrderID: body.OrderID, + Reason: "zeeone_repair_order", + Status: gamedomain.RepairStatusLogged, + }) + if err != nil { + return zeeoneAdapterError(zeeoneCodeFromError(err), zeeoneMessageFromError(err), true, body.OrderID) + } + } + raw, contentType := zeeoneJSON(zeeoneCodeOK, zeeoneDefaultSuccessMessage, map[string]any{}) + return raw, contentType, strconv.Itoa(zeeoneCodeOK), true, body.OrderID, nil +} + +func (s *Service) validZeeOneSession(ctx context.Context, app string, sessionID string) (gamedomain.LaunchSession, error) { + sessionID = strings.TrimSpace(sessionID) + if sessionID == "" { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "sessionId not found") + } + if session, err := s.validYomiSession(ctx, app, sessionID); err == nil { + return session, nil + } + if strings.Count(sessionID, ".") == 2 { + return s.appSessionFromAccessToken(app, sessionID) + } + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "sessionId not found") +} + +func zeeoneSessionMatches(session gamedomain.LaunchSession, config zeeoneAdapterConfig, userID string, gameID int64) bool { + if gameID > 0 && strings.TrimSpace(session.ProviderGameID) != "" && strconv.FormatInt(gameID, 10) != strings.TrimSpace(session.ProviderGameID) { + return false + } + userID = strings.TrimSpace(userID) + return userID == "" || + userID == externalUserID(session, config.UIDMode) || + userID == strings.TrimSpace(session.DisplayUserID) || + userID == strconv.FormatInt(session.UserID, 10) +} + +func zeeoneOpType(diff int64) (string, int64) { + if diff < 0 { + return "debit", -diff + } + return "credit", diff +} + +func zeeoneProviderRequestID(reqBody string) string { + var body struct { + OrderID string `json:"order_id"` + } + _ = json.Unmarshal([]byte(reqBody), &body) + return strings.TrimSpace(body.OrderID) +} + +func zeeoneAdapterError(code int, message string, signatureValid bool, providerRequestID string) ([]byte, string, string, bool, string, error) { + raw, contentType := zeeoneJSON(code, message, map[string]any{}) + return raw, contentType, strconv.Itoa(code), signatureValid, providerRequestID, nil +} + +func zeeoneJSON(code int, message string, data any) ([]byte, string) { + if strings.TrimSpace(message) == "" && code == zeeoneCodeOK { + message = zeeoneDefaultSuccessMessage + } + payload := map[string]any{"code": code, "message": strings.TrimSpace(message)} + if data != nil { + payload["data"] = data + } + return jsonResponse(payload) +} + +func zeeoneCodeFromError(err error) int { + switch { + case err == nil: + return zeeoneCodeOK + case xerr.IsCode(err, xerr.InsufficientBalance): + return zeeoneCodeInsufficientBalance + case xerr.IsCode(err, xerr.SessionExpired): + return zeeoneCodeSessionInvalid + case xerr.IsCode(err, xerr.Unauthorized): + return zeeoneCodeSessionNotFound + default: + return zeeoneCodeInvalidArgument + } +} + +func zeeoneMessageFromError(err error) string { + switch zeeoneCodeFromError(err) { + case zeeoneCodeInsufficientBalance: + return "coin not enough" + case zeeoneCodeSessionNotFound: + return "sessionId not found" + case zeeoneCodeSessionInvalid: + return "sessionId invalid" + default: + if err != nil && strings.TrimSpace(xerr.MessageOf(err)) != "" { + return xerr.MessageOf(err) + } + return "invalid argument" + } +} diff --git a/services/game-service/internal/transport/grpc/server.go b/services/game-service/internal/transport/grpc/server.go index 75fb3212..d508f4a4 100644 --- a/services/game-service/internal/transport/grpc/server.go +++ b/services/game-service/internal/transport/grpc/server.go @@ -400,6 +400,8 @@ func normalizeAdapterType(adapterType string) string { return gamedomain.AdapterYomiV4 case gamedomain.AdapterLeaderCCV1: return gamedomain.AdapterLeaderCCV1 + case gamedomain.AdapterZeeOneV1: + return gamedomain.AdapterZeeOneV1 default: return "" } diff --git a/services/gateway-service/internal/app/app.go b/services/gateway-service/internal/app/app.go index cf2ee846..bf88036e 100644 --- a/services/gateway-service/internal/app/app.go +++ b/services/gateway-service/internal/app/app.go @@ -97,6 +97,7 @@ func New(cfg config.Config) (*App, error) { var growthLevelClient client.GrowthLevelClient = client.NewGRPCGrowthLevelClient(activityConn) var achievementClient client.AchievementClient = client.NewGRPCAchievementClient(activityConn) var registrationRewardClient client.RegistrationRewardClient = client.NewGRPCRegistrationRewardClient(activityConn) + var firstRechargeRewardClient client.FirstRechargeRewardClient = client.NewGRPCFirstRechargeRewardClient(activityConn) var sevenDayCheckInClient client.SevenDayCheckInClient = client.NewGRPCSevenDayCheckInClient(activityConn) var broadcastClient client.BroadcastClient = client.NewGRPCBroadcastClient(activityConn) var gameClient client.GameClient = client.NewGRPCGameClient(gameConn) @@ -140,6 +141,7 @@ func New(cfg config.Config) (*App, error) { handler.SetGrowthLevelClient(growthLevelClient) handler.SetAchievementClient(achievementClient) handler.SetRegistrationRewardClient(registrationRewardClient) + handler.SetFirstRechargeRewardClient(firstRechargeRewardClient) handler.SetSevenDayCheckInClient(sevenDayCheckInClient) handler.SetBroadcastClient(broadcastClient) handler.SetGameClient(gameClient) diff --git a/services/gateway-service/internal/client/first_recharge_reward_client.go b/services/gateway-service/internal/client/first_recharge_reward_client.go new file mode 100644 index 00000000..b57d09d5 --- /dev/null +++ b/services/gateway-service/internal/client/first_recharge_reward_client.go @@ -0,0 +1,25 @@ +package client + +import ( + "context" + + "google.golang.org/grpc" + activityv1 "hyapp.local/api/proto/activity/v1" +) + +// FirstRechargeRewardClient abstracts gateway reads from activity-service first recharge reward APIs. +type FirstRechargeRewardClient interface { + GetFirstRechargeRewardStatus(ctx context.Context, req *activityv1.GetFirstRechargeRewardStatusRequest) (*activityv1.GetFirstRechargeRewardStatusResponse, error) +} + +type grpcFirstRechargeRewardClient struct { + client activityv1.FirstRechargeRewardServiceClient +} + +func NewGRPCFirstRechargeRewardClient(conn *grpc.ClientConn) FirstRechargeRewardClient { + return &grpcFirstRechargeRewardClient{client: activityv1.NewFirstRechargeRewardServiceClient(conn)} +} + +func (c *grpcFirstRechargeRewardClient) GetFirstRechargeRewardStatus(ctx context.Context, req *activityv1.GetFirstRechargeRewardStatusRequest) (*activityv1.GetFirstRechargeRewardStatusResponse, error) { + return c.client.GetFirstRechargeRewardStatus(ctx, req) +} diff --git a/services/gateway-service/internal/transport/http/activityapi/first_recharge_reward_handler.go b/services/gateway-service/internal/transport/http/activityapi/first_recharge_reward_handler.go new file mode 100644 index 00000000..cccb26f3 --- /dev/null +++ b/services/gateway-service/internal/transport/http/activityapi/first_recharge_reward_handler.go @@ -0,0 +1,125 @@ +package activityapi + +import ( + "net/http" + + activityv1 "hyapp.local/api/proto/activity/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type firstRechargeRewardTierData struct { + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + TierName string `json:"tier_name"` + MinCoinAmount int64 `json:"min_coin_amount"` + MaxCoinAmount int64 `json:"max_coin_amount"` + ResourceGroupID int64 `json:"resource_group_id"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` +} + +type firstRechargeRewardClaimData struct { + ClaimID string `json:"claim_id"` + TransactionID string `json:"transaction_id"` + UserID int64 `json:"user_id"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ResourceGroupID int64 `json:"resource_group_id"` + RechargeCoinAmount int64 `json:"recharge_coin_amount"` + RechargeSequence int64 `json:"recharge_sequence"` + RechargeType string `json:"recharge_type"` + Status string `json:"status"` + WalletGrantID string `json:"wallet_grant_id"` + FailureReason string `json:"failure_reason"` + RechargedAtMS int64 `json:"recharged_at_ms"` + GrantedAtMS int64 `json:"granted_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type firstRechargeRewardStatusData struct { + Enabled bool `json:"enabled"` + Tiers []firstRechargeRewardTierData `json:"tiers"` + Rewarded bool `json:"rewarded"` + Claim *firstRechargeRewardClaimData `json:"claim,omitempty"` + ServerTimeMS int64 `json:"server_time_ms"` +} + +func (h *Handler) getFirstRechargeRewardStatus(writer http.ResponseWriter, request *http.Request) { + if h.firstRechargeReward == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + resp, err := h.firstRechargeReward.GetFirstRechargeRewardStatus(request.Context(), &activityv1.GetFirstRechargeRewardStatusRequest{ + Meta: httpkit.ActivityMeta(request), + UserId: auth.UserIDFromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, firstRechargeRewardStatusFromProto(resp.GetStatus())) +} + +func firstRechargeRewardStatusFromProto(item *activityv1.FirstRechargeRewardStatus) firstRechargeRewardStatusData { + if item == nil { + return firstRechargeRewardStatusData{Tiers: []firstRechargeRewardTierData{}} + } + tiers := make([]firstRechargeRewardTierData, 0, len(item.GetTiers())) + for _, tier := range item.GetTiers() { + tiers = append(tiers, firstRechargeRewardTierFromProto(tier)) + } + var claim *firstRechargeRewardClaimData + if item.GetClaim() != nil { + converted := firstRechargeRewardClaimFromProto(item.GetClaim()) + claim = &converted + } + return firstRechargeRewardStatusData{ + Enabled: item.GetEnabled(), + Tiers: tiers, + Rewarded: item.GetRewarded(), + Claim: claim, + ServerTimeMS: item.GetServerTimeMs(), + } +} + +func firstRechargeRewardTierFromProto(item *activityv1.FirstRechargeRewardTier) firstRechargeRewardTierData { + if item == nil { + return firstRechargeRewardTierData{} + } + return firstRechargeRewardTierData{ + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + TierName: item.GetTierName(), + MinCoinAmount: item.GetMinCoinAmount(), + MaxCoinAmount: item.GetMaxCoinAmount(), + ResourceGroupID: item.GetResourceGroupId(), + Status: item.GetStatus(), + SortOrder: item.GetSortOrder(), + } +} + +func firstRechargeRewardClaimFromProto(item *activityv1.FirstRechargeRewardClaim) firstRechargeRewardClaimData { + if item == nil { + return firstRechargeRewardClaimData{} + } + return firstRechargeRewardClaimData{ + ClaimID: item.GetClaimId(), + TransactionID: item.GetTransactionId(), + UserID: item.GetUserId(), + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + ResourceGroupID: item.GetResourceGroupId(), + RechargeCoinAmount: item.GetRechargeCoinAmount(), + RechargeSequence: item.GetRechargeSequence(), + RechargeType: item.GetRechargeType(), + Status: item.GetStatus(), + WalletGrantID: item.GetWalletGrantId(), + FailureReason: item.GetFailureReason(), + RechargedAtMS: item.GetRechargedAtMs(), + GrantedAtMS: item.GetGrantedAtMs(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } +} diff --git a/services/gateway-service/internal/transport/http/activityapi/handler.go b/services/gateway-service/internal/transport/http/activityapi/handler.go index d1340387..60f1c0c9 100644 --- a/services/gateway-service/internal/transport/http/activityapi/handler.go +++ b/services/gateway-service/internal/transport/http/activityapi/handler.go @@ -10,37 +10,40 @@ import ( // Handler owns activity-facing HTTP endpoints. // It keeps task and registration reward reads/writes behind activity-service, with gateway only adding auth context. type Handler struct { - taskClient client.TaskClient - growthLevelClient client.GrowthLevelClient - achievementClient client.AchievementClient - userProfileClient client.UserProfileClient - walletClient client.WalletClient - walletDB *sql.DB - registrationReward client.RegistrationRewardClient - sevenDayCheckIn client.SevenDayCheckInClient + taskClient client.TaskClient + growthLevelClient client.GrowthLevelClient + achievementClient client.AchievementClient + userProfileClient client.UserProfileClient + walletClient client.WalletClient + walletDB *sql.DB + registrationReward client.RegistrationRewardClient + firstRechargeReward client.FirstRechargeRewardClient + sevenDayCheckIn client.SevenDayCheckInClient } type Config struct { - TaskClient client.TaskClient - GrowthLevelClient client.GrowthLevelClient - AchievementClient client.AchievementClient - UserProfileClient client.UserProfileClient - WalletClient client.WalletClient - WalletDB *sql.DB - RegistrationReward client.RegistrationRewardClient - SevenDayCheckIn client.SevenDayCheckInClient + TaskClient client.TaskClient + GrowthLevelClient client.GrowthLevelClient + AchievementClient client.AchievementClient + UserProfileClient client.UserProfileClient + WalletClient client.WalletClient + WalletDB *sql.DB + RegistrationReward client.RegistrationRewardClient + FirstRechargeReward client.FirstRechargeRewardClient + SevenDayCheckIn client.SevenDayCheckInClient } func New(config Config) *Handler { return &Handler{ - taskClient: config.TaskClient, - growthLevelClient: config.GrowthLevelClient, - achievementClient: config.AchievementClient, - userProfileClient: config.UserProfileClient, - walletClient: config.WalletClient, - walletDB: config.WalletDB, - registrationReward: config.RegistrationReward, - sevenDayCheckIn: config.SevenDayCheckIn, + taskClient: config.TaskClient, + growthLevelClient: config.GrowthLevelClient, + achievementClient: config.AchievementClient, + userProfileClient: config.UserProfileClient, + walletClient: config.WalletClient, + walletDB: config.WalletDB, + registrationReward: config.RegistrationReward, + firstRechargeReward: config.FirstRechargeReward, + sevenDayCheckIn: config.SevenDayCheckIn, } } @@ -49,6 +52,7 @@ func (h *Handler) TaskHandlers() httproutes.TaskHandlers { ListTaskTabs: h.listTaskTabs, ClaimTaskReward: h.claimTaskReward, GetRegistrationRewardEligibility: h.getRegistrationRewardEligibility, + GetFirstRechargeRewardStatus: h.getFirstRechargeRewardStatus, GetSevenDayCheckInStatus: h.getSevenDayCheckInStatus, SignSevenDayCheckIn: h.signSevenDayCheckIn, ListUserLeaderboards: h.listUserLeaderboards, diff --git a/services/gateway-service/internal/transport/http/handler.go b/services/gateway-service/internal/transport/http/handler.go index 2eb75a6c..1807ade7 100644 --- a/services/gateway-service/internal/transport/http/handler.go +++ b/services/gateway-service/internal/transport/http/handler.go @@ -39,6 +39,7 @@ type Handler struct { growthLevelClient client.GrowthLevelClient achievementClient client.AchievementClient registrationReward client.RegistrationRewardClient + firstRechargeReward client.FirstRechargeRewardClient sevenDayCheckIn client.SevenDayCheckInClient broadcastClient client.BroadcastClient gameClient client.GameClient @@ -193,6 +194,11 @@ func (h *Handler) SetRegistrationRewardClient(registrationReward client.Registra h.registrationReward = registrationReward } +// SetFirstRechargeRewardClient 注入 activity-service 首冲奖励查询 client。 +func (h *Handler) SetFirstRechargeRewardClient(firstRechargeReward client.FirstRechargeRewardClient) { + h.firstRechargeReward = firstRechargeReward +} + // SetSevenDayCheckInClient 注入 activity-service 七日签到 client。 func (h *Handler) SetSevenDayCheckInClient(sevenDayCheckIn client.SevenDayCheckInClient) { h.sevenDayCheckIn = sevenDayCheckIn diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 8e9d0de7..c7598f63 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -130,6 +130,7 @@ type TaskHandlers struct { ListTaskTabs http.HandlerFunc ClaimTaskReward http.HandlerFunc GetRegistrationRewardEligibility http.HandlerFunc + GetFirstRechargeRewardStatus http.HandlerFunc GetSevenDayCheckInStatus http.HandlerFunc SignSevenDayCheckIn http.HandlerFunc ListUserLeaderboards http.HandlerFunc @@ -324,6 +325,7 @@ func (r routes) registerMessageRoutes() { func (r routes) registerTaskRoutes() { h := r.config.Task r.profile("/activities/registration-reward/eligibility", http.MethodGet, h.GetRegistrationRewardEligibility) + r.profile("/activities/first-recharge-reward", http.MethodGet, h.GetFirstRechargeRewardStatus) r.profile("/activities/seven-day-checkin", http.MethodGet, h.GetSevenDayCheckInStatus) r.profile("/activities/seven-day-checkin/sign", http.MethodPost, h.SignSevenDayCheckIn) r.profile("/activities/user-leaderboards", http.MethodGet, h.ListUserLeaderboards) diff --git a/services/gateway-service/internal/transport/http/router.go b/services/gateway-service/internal/transport/http/router.go index bd8250bb..e7a23f6c 100644 --- a/services/gateway-service/internal/transport/http/router.go +++ b/services/gateway-service/internal/transport/http/router.go @@ -57,14 +57,15 @@ func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler { UserProfileClient: h.userProfileClient, }) activityAPI := activityapi.New(activityapi.Config{ - TaskClient: h.taskClient, - GrowthLevelClient: h.growthLevelClient, - AchievementClient: h.achievementClient, - UserProfileClient: h.userProfileClient, - WalletClient: h.walletClient, - WalletDB: h.leaderboardWalletDB, - RegistrationReward: h.registrationReward, - SevenDayCheckIn: h.sevenDayCheckIn, + TaskClient: h.taskClient, + GrowthLevelClient: h.growthLevelClient, + AchievementClient: h.achievementClient, + UserProfileClient: h.userProfileClient, + WalletClient: h.walletClient, + WalletDB: h.leaderboardWalletDB, + RegistrationReward: h.registrationReward, + FirstRechargeReward: h.firstRechargeReward, + SevenDayCheckIn: h.sevenDayCheckIn, }) gameAPI := gameapi.New(gameapi.Config{ GameClient: h.gameClient, diff --git a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql index 47843a97..3bd231ad 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -112,6 +112,7 @@ CREATE TABLE IF NOT EXISTS wallet_recharge_records ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID', user_id BIGINT NOT NULL COMMENT '用户 ID', + recharge_sequence BIGINT NOT NULL DEFAULT 0 COMMENT '该用户成功充值序号,从 1 开始', seller_user_id BIGINT NOT NULL COMMENT '商户用户 ID', seller_region_id BIGINT NOT NULL COMMENT '商户区域 ID', target_region_id BIGINT NOT NULL COMMENT '目标区域 ID', @@ -129,6 +130,28 @@ CREATE TABLE IF NOT EXISTS wallet_recharge_records ( KEY idx_wallet_recharge_records_region_time (app_code, target_region_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包充值记录表'; +CREATE TABLE IF NOT EXISTS wallet_user_recharge_stats ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + user_id BIGINT NOT NULL COMMENT '用户 ID', + recharge_count BIGINT NOT NULL DEFAULT 0 COMMENT '成功充值次数', + first_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '首笔充值交易 ID', + first_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首笔充值时间,UTC epoch ms', + total_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金币', + total_usd_minor_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值美元最小单位金额', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户充值统计表'; + +SET @ddl := IF( + (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_recharge_records' AND COLUMN_NAME = 'recharge_sequence') = 0, + 'ALTER TABLE wallet_recharge_records ADD COLUMN recharge_sequence BIGINT NOT NULL DEFAULT 0 COMMENT ''该用户成功充值序号,从 1 开始'' AFTER user_id', + 'SELECT 1' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + CREATE TABLE IF NOT EXISTS wallet_recharge_products ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', product_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '商品 ID', diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index 773138e4..580226b0 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -96,6 +96,7 @@ type CoinSellerTransferReceipt struct { SellerBalanceAfter int64 TargetBalanceAfter int64 Amount int64 + RechargeSequence int64 RechargeUSDMinor int64 RechargeCurrencyCode string RechargePolicyID int64 diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 933cda3b..1e477a30 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -740,6 +740,10 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. if err != nil { return ledger.CoinSellerTransferReceipt{}, err } + rechargeSequence, err := r.reserveUserRechargeSequence(ctx, tx, command.AppCode, command.TargetUserID, transactionID, command.Amount, rechargeUSDMinor, nowMs) + if err != nil { + return ledger.CoinSellerTransferReceipt{}, err + } sellerAfter := seller.AvailableAmount - command.Amount targetAfter := target.AvailableAmount + command.Amount metadata := coinSellerTransferMetadata{ @@ -754,6 +758,7 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. TargetAssetType: ledger.AssetCoin, SellerBalanceAfter: sellerAfter, TargetBalanceAfter: targetAfter, + RechargeSequence: rechargeSequence, RechargeUSDMinor: rechargeUSDMinor, RechargeCurrencyCode: policy.CurrencyCode, RechargePolicyID: policy.PolicyID, @@ -1062,13 +1067,14 @@ func (r *Repository) insertTransaction(ctx context.Context, tx *sql.Tx, transact func (r *Repository) insertRechargeRecord(ctx context.Context, tx *sql.Tx, transactionID string, metadata coinSellerTransferMetadata, nowMs int64) error { _, err := tx.ExecContext(ctx, `INSERT INTO wallet_recharge_records ( - app_code, transaction_id, user_id, seller_user_id, seller_region_id, target_region_id, + app_code, transaction_id, user_id, recharge_sequence, seller_user_id, seller_region_id, target_region_id, policy_id, policy_version, currency_code, coin_amount, usd_minor_amount, exchange_coin_amount, exchange_usd_minor_amount, created_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, normalizedEntryAppCode(ctx, metadata.AppCode), transactionID, metadata.TargetUserID, + metadata.RechargeSequence, metadata.SellerUserID, metadata.SellerRegionID, metadata.TargetRegionID, @@ -1084,6 +1090,48 @@ func (r *Repository) insertRechargeRecord(ctx context.Context, tx *sql.Tx, trans return err } +func (r *Repository) reserveUserRechargeSequence(ctx context.Context, tx *sql.Tx, appCode string, userID int64, transactionID string, coinAmount int64, usdMinorAmount int64, nowMs int64) (int64, error) { + normalizedApp := normalizedEntryAppCode(ctx, appCode) + var count int64 + err := tx.QueryRowContext(ctx, ` + SELECT recharge_count + FROM wallet_user_recharge_stats + WHERE app_code = ? AND user_id = ? + FOR UPDATE`, + normalizedApp, userID, + ).Scan(&count) + if errors.Is(err, sql.ErrNoRows) { + _, err = tx.ExecContext(ctx, ` + INSERT INTO wallet_user_recharge_stats ( + app_code, user_id, recharge_count, first_transaction_id, first_recharged_at_ms, + total_coin_amount, total_usd_minor_amount, created_at_ms, updated_at_ms + ) VALUES (?, ?, 1, ?, ?, ?, ?, ?, ?)`, + normalizedApp, userID, transactionID, nowMs, coinAmount, usdMinorAmount, nowMs, nowMs, + ) + if err != nil { + return 0, err + } + return 1, nil + } + if err != nil { + return 0, err + } + next := count + 1 + _, err = tx.ExecContext(ctx, ` + UPDATE wallet_user_recharge_stats + SET recharge_count = ?, + total_coin_amount = total_coin_amount + ?, + total_usd_minor_amount = total_usd_minor_amount + ?, + updated_at_ms = ? + WHERE app_code = ? AND user_id = ?`, + next, coinAmount, usdMinorAmount, nowMs, normalizedApp, userID, + ) + if err != nil { + return 0, err + } + return next, nil +} + func (r *Repository) insertCoinSellerStockRecord(ctx context.Context, tx *sql.Tx, transactionID string, commandID string, metadata coinSellerStockMetadata, nowMs int64) error { metadataJSON, err := json.Marshal(metadata) if err != nil { @@ -1333,6 +1381,7 @@ type coinSellerTransferMetadata struct { TargetAssetType string `json:"target_asset_type"` SellerBalanceAfter int64 `json:"seller_balance_after"` TargetBalanceAfter int64 `json:"target_balance_after"` + RechargeSequence int64 `json:"recharge_sequence"` RechargeUSDMinor int64 `json:"recharge_usd_minor"` RechargeCurrencyCode string `json:"recharge_currency_code"` RechargePolicyID int64 `json:"recharge_policy_id"` @@ -1500,6 +1549,7 @@ func receiptFromCoinSellerTransferMetadata(transactionID string, metadata coinSe SellerBalanceAfter: metadata.SellerBalanceAfter, TargetBalanceAfter: metadata.TargetBalanceAfter, Amount: metadata.Amount, + RechargeSequence: metadata.RechargeSequence, RechargeUSDMinor: metadata.RechargeUSDMinor, RechargeCurrencyCode: metadata.RechargeCurrencyCode, RechargePolicyID: metadata.RechargePolicyID,