From 858b0993bc2129d2bc2e14903d75521e07ac2eb6 Mon Sep 17 00:00:00 2001 From: zhx Date: Tue, 2 Jun 2026 23:45:46 +0800 Subject: [PATCH 01/28] feat: simplify lucky gift settlement outbox --- .../configs/config.docker.yaml | 4 +- .../configs/config.tencent.example.yaml | 8 +- services/activity-service/configs/config.yaml | 4 +- .../mysql/initdb/001_activity_service.sql | 15 +- services/activity-service/internal/app/app.go | 2 + .../internal/config/config.go | 32 +- .../internal/domain/luckygift/lucky_gift.go | 3 + .../internal/service/luckygift/service.go | 119 ++-- .../service/luckygift/service_test.go | 82 ++- .../storage/mysql/lucky_gift_repository.go | 587 ++++++++++-------- .../mysql/lucky_gift_repository_test.go | 166 ++++- .../lucky_gift_settlement_pressure_test.go | 196 ++++++ .../internal/storage/mysql/repository.go | 136 ++-- 13 files changed, 903 insertions(+), 451 deletions(-) create mode 100644 services/activity-service/internal/storage/mysql/lucky_gift_settlement_pressure_test.go diff --git a/services/activity-service/configs/config.docker.yaml b/services/activity-service/configs/config.docker.yaml index 8db07f36..8062e942 100644 --- a/services/activity-service/configs/config.docker.yaml +++ b/services/activity-service/configs/config.docker.yaml @@ -21,10 +21,12 @@ lucky_gift_worker: enabled: true worker_poll_interval: "1s" worker_batch_size: 100 - worker_concurrency: 4 + worker_concurrency: 8 worker_lock_ttl: "30s" worker_max_retry: 8 publish_timeout: "5s" + stats_refresh_interval: "10m" + stats_batch_size: 5000 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 1687a4b2..010cfe7c 100644 --- a/services/activity-service/configs/config.tencent.example.yaml +++ b/services/activity-service/configs/config.tencent.example.yaml @@ -19,12 +19,14 @@ red_packet_broadcast_worker: enabled: true lucky_gift_worker: enabled: true - worker_poll_interval: "60s" - worker_batch_size: 10 - worker_concurrency: 4 + worker_poll_interval: "1s" + worker_batch_size: 100 + worker_concurrency: 8 worker_lock_ttl: "30s" worker_max_retry: 8 publish_timeout: "5s" + stats_refresh_interval: "10m" + stats_batch_size: 5000 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 fdf50deb..86d3c302 100644 --- a/services/activity-service/configs/config.yaml +++ b/services/activity-service/configs/config.yaml @@ -21,10 +21,12 @@ lucky_gift_worker: enabled: true worker_poll_interval: "1s" worker_batch_size: 100 - worker_concurrency: 4 + worker_concurrency: 8 worker_lock_ttl: "30s" worker_max_retry: 8 publish_timeout: "5s" + stats_refresh_interval: "10m" + stats_batch_size: 5000 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 8ed8b138..d9da299a 100644 --- a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql +++ b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql @@ -256,7 +256,10 @@ CREATE TABLE IF NOT EXISTS lucky_draw_records ( KEY idx_lucky_draw_user (app_code, user_id, created_at_ms), KEY idx_lucky_draw_gift (app_code, gift_id, created_at_ms), KEY idx_lucky_draw_room (app_code, room_id, created_at_ms), - KEY idx_lucky_draw_status (app_code, reward_status, updated_at_ms) + KEY idx_lucky_draw_status (app_code, reward_status, updated_at_ms), + KEY idx_lucky_draw_created (app_code, created_at_ms, draw_id), + KEY idx_lucky_draw_pool_status_summary (app_code, pool_id, reward_status, created_at_ms, draw_id), + KEY idx_lucky_draw_gift_status_summary (app_code, pool_id, gift_id, reward_status, created_at_ms, draw_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物抽奖事实'; CREATE TABLE IF NOT EXISTS lucky_draw_pool_stats ( @@ -297,6 +300,16 @@ CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_rooms ( PRIMARY KEY (app_code, pool_id, gift_id, room_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物汇总房间去重'; +CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_cursors ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cursor_name VARCHAR(64) NOT NULL COMMENT '游标名称', + last_draw_created_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后已聚合 draw 创建时间', + last_draw_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '同一毫秒内最后已聚合 draw 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, cursor_name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物后台统计快照游标'; + CREATE TABLE IF NOT EXISTS im_broadcast_outbox ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID', diff --git a/services/activity-service/internal/app/app.go b/services/activity-service/internal/app/app.go index aa3b86b1..1737839b 100644 --- a/services/activity-service/internal/app/app.go +++ b/services/activity-service/internal/app/app.go @@ -586,5 +586,7 @@ func luckyGiftWorkerOptions(nodeID string, cfg config.LuckyGiftWorkerConfig) luc LockTTL: cfg.WorkerLockTTL, MaxRetry: cfg.WorkerMaxRetry, PublishTimeout: cfg.PublishTimeout, + StatsInterval: cfg.StatsRefreshInterval, + StatsBatchSize: cfg.StatsBatchSize, } } diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index ab3cef1a..c139957f 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -69,13 +69,15 @@ type RedPacketBroadcastWorkerConfig struct { // LuckyGiftWorkerConfig 保存幸运礼物抽奖副作用补偿策略。 type LuckyGiftWorkerConfig struct { - Enabled bool `yaml:"enabled"` - WorkerPollInterval time.Duration `yaml:"worker_poll_interval"` - WorkerBatchSize int `yaml:"worker_batch_size"` - WorkerConcurrency int `yaml:"worker_concurrency"` - WorkerLockTTL time.Duration `yaml:"worker_lock_ttl"` - WorkerMaxRetry int `yaml:"worker_max_retry"` - PublishTimeout time.Duration `yaml:"publish_timeout"` + Enabled bool `yaml:"enabled"` + WorkerPollInterval time.Duration `yaml:"worker_poll_interval"` + WorkerBatchSize int `yaml:"worker_batch_size"` + WorkerConcurrency int `yaml:"worker_concurrency"` + WorkerLockTTL time.Duration `yaml:"worker_lock_ttl"` + WorkerMaxRetry int `yaml:"worker_max_retry"` + PublishTimeout time.Duration `yaml:"publish_timeout"` + StatsRefreshInterval time.Duration `yaml:"stats_refresh_interval"` + StatsBatchSize int `yaml:"stats_batch_size"` } // TencentIMConfig 描述 activity-service 调用腾讯云 IM REST API 的配置。 @@ -168,13 +170,15 @@ func Default() Config { Enabled: false, }, LuckyGiftWorker: LuckyGiftWorkerConfig{ - Enabled: false, - WorkerPollInterval: time.Second, - WorkerBatchSize: 100, - WorkerConcurrency: 4, - WorkerLockTTL: 30 * time.Second, - WorkerMaxRetry: 8, - PublishTimeout: 5 * time.Second, + Enabled: false, + WorkerPollInterval: time.Second, + WorkerBatchSize: 100, + WorkerConcurrency: 4, + WorkerLockTTL: 30 * time.Second, + WorkerMaxRetry: 8, + PublishTimeout: 5 * time.Second, + StatsRefreshInterval: 10 * time.Minute, + StatsBatchSize: 5000, }, TencentIM: TencentIMConfig{ Enabled: false, diff --git a/services/activity-service/internal/domain/luckygift/lucky_gift.go b/services/activity-service/internal/domain/luckygift/lucky_gift.go index 62cc60bd..e50fe196 100644 --- a/services/activity-service/internal/domain/luckygift/lucky_gift.go +++ b/services/activity-service/internal/domain/luckygift/lucky_gift.go @@ -28,6 +28,9 @@ const ( BroadcastRoom = "room" BroadcastRegion = "region" BroadcastGlobal = "global" + + EventTypeLuckyGiftDrawn = "LuckyGiftDrawn" + EventTypeLuckyGiftRewardSettlement = "LuckyGiftRewardSettlement" ) // Tier 是单个体验池里的候选奖档;权重只塑造体验节奏,基础成本仍由 RTP 窗口兜住。 diff --git a/services/activity-service/internal/service/luckygift/service.go b/services/activity-service/internal/service/luckygift/service.go index 8c0eba38..9471b555 100644 --- a/services/activity-service/internal/service/luckygift/service.go +++ b/services/activity-service/internal/service/luckygift/service.go @@ -35,6 +35,7 @@ type Repository interface { MarkLuckyGiftOutboxDelivered(ctx context.Context, event domain.DrawOutbox, nowMS int64) error MarkLuckyGiftOutboxRetryable(ctx context.Context, event domain.DrawOutbox, retryCount int, nextRetryAtMS int64, lastErr string, nowMS int64) error MarkLuckyGiftOutboxFailed(ctx context.Context, event domain.DrawOutbox, retryCount int, lastErr string, nowMS int64) error + RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, nowMS int64, batchSize int) (int, error) MarkLuckyGiftDrawGranted(ctx context.Context, appCode string, drawID string, walletTransactionID string, nowMS int64) error MarkLuckyGiftDrawFailed(ctx context.Context, appCode string, drawID string, failureReason string, nowMS int64) error // 批量抽奖只产生一条聚合 outbox;worker 处理后需要用 draw_ids 一次性收敛所有明细状态。 @@ -152,17 +153,27 @@ type WorkerOptions struct { LockTTL time.Duration MaxRetry int PublishTimeout time.Duration + StatsInterval time.Duration + StatsBatchSize int } func (s *Service) RunWorker(ctx context.Context, options WorkerOptions) { options = normalizeWorkerOptions(options) ticker := time.NewTicker(options.PollInterval) defer ticker.Stop() + nextStatsRefresh := time.Time{} for { if _, err := s.ProcessPendingDrawOutbox(ctx, options); err != nil && ctx.Err() == nil { // 批处理失败不删除 outbox;锁过期后下一轮或其他实例会继续补偿。 logx.Error(ctx, "lucky_gift_outbox_batch_failed", err, slog.String("worker_id", options.WorkerID)) } + now := s.now().UTC() + if options.StatsInterval > 0 && (nextStatsRefresh.IsZero() || !now.Before(nextStatsRefresh)) { + if _, err := s.repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, now.UnixMilli(), options.StatsBatchSize); err != nil && ctx.Err() == nil { + logx.Error(ctx, "lucky_gift_admin_stats_refresh_failed", err, slog.String("worker_id", options.WorkerID)) + } + nextStatsRefresh = now.Add(options.StatsInterval) + } select { case <-ctx.Done(): return @@ -176,7 +187,7 @@ func (s *Service) ProcessPendingDrawOutbox(ctx context.Context, options WorkerOp return 0, err } options = normalizeWorkerOptions(options) - // outbox 先抢占再处理,避免多实例同时给同一 draw 返奖或重复投递房间 IM。 + // outbox 只承载钱包返奖结算,避免多实例同时给同一 draw 返奖。 events, err := s.repository.ClaimPendingLuckyGiftOutbox(ctx, options.WorkerID, s.now().UTC().UnixMilli(), options.LockTTL, options.BatchSize) if err != nil { return 0, err @@ -238,56 +249,55 @@ func (s *Service) processDrawOutbox(ctx context.Context, event domain.DrawOutbox return s.markOutboxFailed(ctx, event, options, err, false) } eventCtx := appcode.WithContext(ctx, event.AppCode) + switch event.EventType { + case domain.EventTypeLuckyGiftRewardSettlement, domain.EventTypeLuckyGiftDrawn, "": + return s.processRewardSettlementOutbox(eventCtx, event, payload, options) + default: + return s.markOutboxFailed(eventCtx, event, options, fmt.Errorf("unsupported lucky gift outbox event type: %s", event.EventType), false) + } +} + +func (s *Service) processRewardSettlementOutbox(ctx context.Context, event domain.DrawOutbox, payload luckyGiftDrawnPayload, options WorkerOptions) error { + if _, _, err := s.settleLuckyGiftReward(ctx, event, payload, options); err != nil { + return err + } + return s.repository.MarkLuckyGiftOutboxDelivered(ctx, event, s.now().UTC().UnixMilli()) +} + +func (s *Service) settleLuckyGiftReward(ctx context.Context, event domain.DrawOutbox, payload luckyGiftDrawnPayload, options WorkerOptions) (bool, bool, error) { walletTransactionID := "" credited := false alreadyGranted := false if payload.EffectiveRewardCoins > 0 { - state, err := s.repository.GetLuckyGiftDrawRewardState(eventCtx, event.AppCode, payload.DrawIDs) + state, err := s.repository.GetLuckyGiftDrawRewardState(ctx, event.AppCode, payload.DrawIDs) if err != nil { - return s.markOutboxFailed(eventCtx, event, options, err, false) + return false, false, s.markOutboxFailed(ctx, event, options, err, false) } alreadyGranted = state.AllGranted if alreadyGranted { walletTransactionID = state.WalletTransactionID credited = true } else { - receipt, err := s.creditLuckyGiftReward(eventCtx, event.AppCode, payload) + receipt, err := s.creditLuckyGiftReward(ctx, event.AppCode, payload) if err != nil { - return s.markOutboxFailed(eventCtx, event, options, err, false) + return false, false, s.markOutboxFailed(ctx, event, options, err, false) } walletTransactionID = receipt.WalletTransactionID credited = true } } - if credited && !alreadyGranted { - nowMS := s.now().UTC().UnixMilli() - if err := s.repository.MarkLuckyGiftDrawsGranted(eventCtx, event.AppCode, payload.DrawIDs, walletTransactionID, nowMS); err != nil { - return err - } - } - if s.publisher == nil { - // 已返奖但缺少房间发布依赖时不能把 draw 标记 failed,否则会误导账务;只让 outbox 保持可重试。 - return s.markOutboxFailed(eventCtx, event, options, fmt.Errorf("lucky gift room publisher is not configured"), credited) - } - if shouldPublishLuckyGiftRegionBroadcast(payload) { - if s.broadcaster == nil { - return s.markOutboxFailed(eventCtx, event, options, fmt.Errorf("lucky gift region broadcaster is not configured"), credited) - } - // 区域播报先写 broadcast outbox,不直接发 IM;这里失败意味着大额表现未落地,需要保留重试。 - if err := s.publishLuckyGiftRegionBroadcast(eventCtx, payload); err != nil { - return s.markOutboxFailed(eventCtx, event, options, err, credited) - } - } - if err := s.publishLuckyGiftDrawn(eventCtx, payload, options); err != nil { - return s.markOutboxFailed(eventCtx, event, options, err, credited) - } - nowMS := s.now().UTC().UnixMilli() if !credited { - if err := s.repository.MarkLuckyGiftDrawsGranted(eventCtx, event.AppCode, payload.DrawIDs, walletTransactionID, nowMS); err != nil { - return err + if err := s.markLuckyGiftDrawsGrantedAfterWallet(ctx, event.AppCode, payload.DrawIDs, walletTransactionID); err != nil { + return false, false, err + } + return false, false, nil + } + if !alreadyGranted { + if err := s.markLuckyGiftDrawsGrantedAfterWallet(ctx, event.AppCode, payload.DrawIDs, walletTransactionID); err != nil { + return credited, alreadyGranted, err } } - return s.repository.MarkLuckyGiftOutboxDelivered(eventCtx, event, nowMS) + return credited, alreadyGranted, nil } type luckyGiftRewardReceipt struct { @@ -337,7 +347,7 @@ func (s *Service) creditLuckyGiftRewardFastPath(ctx context.Context, cmd domain. result.RewardStatus = domain.StatusGranted result.WalletTransactionID = receipt.WalletTransactionID result.CoinBalanceAfter = receipt.CoinBalanceAfter - if err := s.repository.MarkLuckyGiftDrawsGranted(ctx, payload.AppCode, payload.DrawIDs, receipt.WalletTransactionID, s.now().UTC().UnixMilli()); err != nil { + if err := s.markLuckyGiftDrawsGrantedAfterWallet(ctx, payload.AppCode, payload.DrawIDs, receipt.WalletTransactionID); err != nil { logx.Error(ctx, "lucky_gift_reward_fast_path_mark_granted_failed", err, slog.String("draw_id", result.DrawID), slog.String("command_id", result.CommandID), @@ -347,6 +357,25 @@ func (s *Service) creditLuckyGiftRewardFastPath(ctx context.Context, cmd domain. return result } +func (s *Service) markLuckyGiftDrawsGrantedAfterWallet(ctx context.Context, appCode string, drawIDs []string, walletTransactionID string) error { + baseCtx := context.WithoutCancel(ctx) + var lastErr error + for attempt := 0; attempt < 3; attempt++ { + markCtx, cancel := context.WithTimeout(appcode.WithContext(baseCtx, appCode), 5*time.Second) + err := s.repository.MarkLuckyGiftDrawsGranted(markCtx, appCode, drawIDs, walletTransactionID, s.now().UTC().UnixMilli()) + cancel() + if err == nil { + return nil + } + lastErr = err + if !isRetryableLuckyGrantMarkError(err) { + return err + } + time.Sleep(time.Duration(attempt+1) * 50 * time.Millisecond) + } + return lastErr +} + func (s *Service) creditLuckyGiftReward(ctx context.Context, appCode string, payload luckyGiftDrawnPayload) (luckyGiftRewardReceipt, error) { if s.wallet == nil { return luckyGiftRewardReceipt{}, fmt.Errorf("lucky gift wallet client is not configured") @@ -377,7 +406,7 @@ func (s *Service) publishLuckyGiftDrawn(ctx context.Context, payload luckyGiftDr if err != nil { return err } - // 房间 IM 只是表现层事实同步,不修改 Room Cell;超时由 outbox 重试兜底。 + // 房间 IM 只是表现层事实同步,不参与钱包结算和 reward_status 收敛。 publishCtx, cancel := context.WithTimeout(ctx, options.PublishTimeout) defer cancel() return s.publisher.PublishGroupCustomMessage(publishCtx, tencentim.CustomGroupMessage{ @@ -411,12 +440,12 @@ func (s *Service) markOutboxFailed(ctx context.Context, event domain.DrawOutbox, nextRetryCount := event.RetryCount + 1 if nextRetryCount >= options.MaxRetry { if !alreadyCredited { - // 未返奖的 draw 可以整批标记 failed;已返奖但 IM 失败时不能覆盖账务事实,只停 outbox 并告警。 + // 未返奖的 draw 可以整批标记 failed;钱包已返奖时不能覆盖账务事实。 _ = s.repository.MarkLuckyGiftDrawsFailed(ctx, event.AppCode, drawIDsFromPayload(event.PayloadJSON), cause.Error(), nowMS) } return s.repository.MarkLuckyGiftOutboxFailed(ctx, event, nextRetryCount, cause.Error(), nowMS) } - // 指数退避降低故障期间对钱包和 IM 的压力,同时保留 pending 状态给客户端展示“处理中”。 + // 指数退避降低故障期间对钱包的压力,同时保留 pending 状态给客户端展示“处理中”。 nextRetryAtMS := nowMS + luckyGiftBackoff(nextRetryCount).Milliseconds() return s.repository.MarkLuckyGiftOutboxRetryable(ctx, event, nextRetryCount, nextRetryAtMS, cause.Error(), nowMS) } @@ -676,6 +705,15 @@ func normalizeWorkerOptions(options WorkerOptions) WorkerOptions { if options.PublishTimeout <= 0 { options.PublishTimeout = 5 * time.Second } + if options.StatsInterval <= 0 { + options.StatsInterval = 10 * time.Minute + } + if options.StatsBatchSize <= 0 { + options.StatsBatchSize = 5000 + } + if options.StatsBatchSize > 50000 { + options.StatsBatchSize = 50000 + } return options } @@ -688,3 +726,14 @@ func luckyGiftBackoff(retryCount int) time.Duration { } return time.Duration(1< 0 { - delta.UserIDs[record.Command.UserID] = struct{}{} - } - roomID := strings.TrimSpace(record.Command.RoomID) - if roomID != "" { - delta.RoomIDs[roomID] = struct{}{} - } - } - } - for key, delta := range deltas { - uniqueUsers, err := r.insertLuckyDrawStatUsers(ctx, tx, key, delta.UserIDs, nowMS) - if err != nil { - return err - } - uniqueRooms, err := r.insertLuckyDrawStatRooms(ctx, tx, key, delta.RoomIDs, nowMS) - if err != nil { - return err - } - if err := r.upsertLuckyDrawPoolStatDelta(ctx, tx, key, *delta, uniqueUsers, uniqueRooms, nowMS); err != nil { - return err - } - } - return nil -} - func (r *Repository) insertLuckyDrawStatUsers(ctx context.Context, tx *sql.Tx, key luckyDrawPoolStatKey, userIDs map[int64]struct{}, nowMS int64) (int64, error) { var inserted int64 for userID := range userIDs { @@ -766,7 +701,7 @@ func (r *Repository) insertLuckyDrawStatRooms(ctx context.Context, tx *sql.Tx, k return inserted, nil } -func (r *Repository) upsertLuckyDrawPoolStatDelta(ctx context.Context, tx *sql.Tx, key luckyDrawPoolStatKey, delta luckyDrawPoolStatDelta, uniqueUsers int64, uniqueRooms int64, nowMS int64) error { +func (r *Repository) upsertLuckyDrawPoolStatsSnapshotDelta(ctx context.Context, tx *sql.Tx, key luckyDrawPoolStatKey, delta luckyDrawPoolStatDelta, uniqueUsers int64, uniqueRooms int64, nowMS int64) error { _, err := tx.ExecContext(ctx, ` INSERT INTO lucky_draw_pool_stats ( app_code, pool_id, gift_id, total_draws, unique_users, unique_rooms, total_spent_coins, @@ -778,21 +713,186 @@ func (r *Repository) upsertLuckyDrawPoolStatDelta(ctx context.Context, tx *sql.T unique_users = unique_users + VALUES(unique_users), unique_rooms = unique_rooms + VALUES(unique_rooms), total_spent_coins = total_spent_coins + VALUES(total_spent_coins), - total_reward_coins = total_reward_coins + VALUES(total_reward_coins), - base_reward_coins = base_reward_coins + VALUES(base_reward_coins), - room_atmosphere_reward_coins = room_atmosphere_reward_coins + VALUES(room_atmosphere_reward_coins), - activity_subsidy_coins = activity_subsidy_coins + VALUES(activity_subsidy_coins), - pending_draws = pending_draws + VALUES(pending_draws), - granted_draws = granted_draws + VALUES(granted_draws), - failed_draws = failed_draws + VALUES(failed_draws), - updated_at_ms = VALUES(updated_at_ms)`, + total_reward_coins = total_reward_coins + VALUES(total_reward_coins), + base_reward_coins = base_reward_coins + VALUES(base_reward_coins), + room_atmosphere_reward_coins = room_atmosphere_reward_coins + VALUES(room_atmosphere_reward_coins), + activity_subsidy_coins = activity_subsidy_coins + VALUES(activity_subsidy_coins), + updated_at_ms = VALUES(updated_at_ms)`, key.AppCode, key.PoolID, key.GiftID, delta.TotalDraws, uniqueUsers, uniqueRooms, delta.TotalSpentCoins, delta.TotalRewardCoins, delta.BaseRewardCoins, delta.RoomAtmosphereRewardCoins, delta.ActivitySubsidyCoins, - delta.PendingDraws, delta.GrantedDraws, delta.FailedDraws, nowMS, nowMS, + int64(0), int64(0), int64(0), nowMS, nowMS, ) return err } +type luckyDrawStatsCursor struct { + LastDrawCreatedAtMS int64 + LastDrawID string +} + +type luckyDrawStatsRecord struct { + AppCode string + DrawID string + PoolID string + GiftID string + UserID int64 + RoomID string + TotalSpentCoins int64 + TotalRewardCoins int64 + BaseRewardCoins int64 + RoomAtmosphereRewardCoins int64 + ActivitySubsidyCoins int64 + CreatedAtMS int64 +} + +func (r *Repository) RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, nowMS int64, batchSize int) (int, error) { + if r == nil || r.db == nil { + return 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if batchSize <= 0 { + batchSize = 5000 + } + if batchSize > 50000 { + batchSize = 50000 + } + appCode := appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return 0, err + } + defer func() { _ = tx.Rollback() }() + + cursor, initialized, err := r.lockLuckyDrawStatsCursor(ctx, tx, appCode, nowMS) + if err != nil { + return 0, err + } + if initialized { + if err := tx.Commit(); err != nil { + return 0, err + } + return 0, nil + } + + rows, err := tx.QueryContext(ctx, ` + SELECT app_code, draw_id, pool_id, gift_id, user_id, room_id, coin_spent, + total_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + created_at_ms + FROM lucky_draw_records FORCE INDEX (idx_lucky_draw_created) + WHERE app_code = ? + AND (created_at_ms > ? OR (created_at_ms = ? AND draw_id > ?)) + ORDER BY created_at_ms ASC, draw_id ASC + LIMIT ?`, appCode, cursor.LastDrawCreatedAtMS, cursor.LastDrawCreatedAtMS, cursor.LastDrawID, batchSize) + if err != nil { + return 0, err + } + defer rows.Close() + records := make([]luckyDrawStatsRecord, 0, batchSize) + for rows.Next() { + var record luckyDrawStatsRecord + if err := rows.Scan(&record.AppCode, &record.DrawID, &record.PoolID, &record.GiftID, &record.UserID, &record.RoomID, + &record.TotalSpentCoins, &record.TotalRewardCoins, &record.BaseRewardCoins, + &record.RoomAtmosphereRewardCoins, &record.ActivitySubsidyCoins, &record.CreatedAtMS); err != nil { + return 0, err + } + records = append(records, record) + } + if err := rows.Err(); err != nil { + return 0, err + } + if len(records) == 0 { + if err := tx.Commit(); err != nil { + return 0, err + } + return 0, nil + } + grouped := map[luckyDrawPoolStatKey]*luckyDrawPoolStatDelta{} + last := records[len(records)-1] + for _, record := range records { + keys := []luckyDrawPoolStatKey{{AppCode: record.AppCode, PoolID: record.PoolID, GiftID: ""}} + if giftID := strings.TrimSpace(record.GiftID); giftID != "" { + keys = append(keys, luckyDrawPoolStatKey{AppCode: record.AppCode, PoolID: record.PoolID, GiftID: giftID}) + } + for _, key := range keys { + delta := grouped[key] + if delta == nil { + delta = &luckyDrawPoolStatDelta{UserIDs: map[int64]struct{}{}, RoomIDs: map[string]struct{}{}} + grouped[key] = delta + } + delta.TotalDraws++ + delta.TotalSpentCoins += record.TotalSpentCoins + delta.TotalRewardCoins += record.TotalRewardCoins + delta.BaseRewardCoins += record.BaseRewardCoins + delta.RoomAtmosphereRewardCoins += record.RoomAtmosphereRewardCoins + delta.ActivitySubsidyCoins += record.ActivitySubsidyCoins + if record.UserID > 0 { + delta.UserIDs[record.UserID] = struct{}{} + } + if roomID := strings.TrimSpace(record.RoomID); roomID != "" { + delta.RoomIDs[roomID] = struct{}{} + } + } + } + for key, delta := range grouped { + uniqueUsers, err := r.insertLuckyDrawStatUsers(ctx, tx, key, delta.UserIDs, nowMS) + if err != nil { + return 0, err + } + uniqueRooms, err := r.insertLuckyDrawStatRooms(ctx, tx, key, delta.RoomIDs, nowMS) + if err != nil { + return 0, err + } + if err := r.upsertLuckyDrawPoolStatsSnapshotDelta(ctx, tx, key, *delta, uniqueUsers, uniqueRooms, nowMS); err != nil { + return 0, err + } + } + if _, err := tx.ExecContext(ctx, ` + UPDATE lucky_draw_pool_stat_cursors + SET last_draw_created_at_ms = ?, last_draw_id = ?, updated_at_ms = ? + WHERE app_code = ? AND cursor_name = 'draw_records'`, + last.CreatedAtMS, last.DrawID, nowMS, appCode, + ); err != nil { + return 0, err + } + if err := tx.Commit(); err != nil { + return 0, err + } + return len(records), nil +} + +func (r *Repository) lockLuckyDrawStatsCursor(ctx context.Context, tx *sql.Tx, appCode string, nowMS int64) (luckyDrawStatsCursor, bool, error) { + var cursor luckyDrawStatsCursor + err := tx.QueryRowContext(ctx, ` + SELECT last_draw_created_at_ms, last_draw_id + FROM lucky_draw_pool_stat_cursors + WHERE app_code = ? AND cursor_name = 'draw_records' + FOR UPDATE`, appCode, + ).Scan(&cursor.LastDrawCreatedAtMS, &cursor.LastDrawID) + if err == nil { + return cursor, false, nil + } + if !errors.Is(err, sql.ErrNoRows) { + return luckyDrawStatsCursor{}, false, err + } + if err := tx.QueryRowContext(ctx, ` + SELECT COALESCE(created_at_ms, 0), COALESCE(draw_id, '') + FROM lucky_draw_records FORCE INDEX (idx_lucky_draw_created) + WHERE app_code = ? + ORDER BY created_at_ms DESC, draw_id DESC + LIMIT 1`, appCode, + ).Scan(&cursor.LastDrawCreatedAtMS, &cursor.LastDrawID); err != nil && !errors.Is(err, sql.ErrNoRows) { + return luckyDrawStatsCursor{}, false, err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO lucky_draw_pool_stat_cursors ( + app_code, cursor_name, last_draw_created_at_ms, last_draw_id, created_at_ms, updated_at_ms + ) VALUES (?, 'draw_records', ?, ?, ?, ?)`, + appCode, cursor.LastDrawCreatedAtMS, cursor.LastDrawID, nowMS, nowMS, + ); err != nil { + return luckyDrawStatsCursor{}, false, err + } + return cursor, true, nil +} + // luckyDrawRecordArgs 固定 lucky_draw_records 的列顺序;集中维护可以避免批量 INSERT 和单条 INSERT 语义漂移。 func luckyDrawRecordArgs(input luckyDrawRecordInput) []any { candidateSnapshot, poolSnapshot, rtpSnapshot := luckyDrawRecordSnapshots(input) @@ -830,9 +930,9 @@ func luckyDrawRecordSnapshots(input luckyDrawRecordInput) (string, string, strin return string(candidateSnapshot), string(poolSnapshot), string(rtpSnapshot) } -// insertLuckyAggregateDrawOutbox 为整批抽奖只写一条副作用事件。 -// draw_id 使用聚合响应的首个 draw,draw_ids 保存全部子抽;worker 用总 effective_reward_coins 发一次奖,再批量 granted。 -func (r *Repository) insertLuckyAggregateDrawOutbox(ctx context.Context, tx *sql.Tx, appCode string, cmd domain.DrawCommand, state luckyBatchDrawState, nowMS int64) error { +// insertLuckyAggregateRewardSettlementOutbox 为整批抽奖写聚合返奖结算事件。 +// draw_id 使用聚合响应的首个 draw,draw_ids 保存全部子抽;settlement 用总 effective_reward_coins 发一次奖,再批量 granted。 +func (r *Repository) insertLuckyAggregateRewardSettlementOutbox(ctx context.Context, tx *sql.Tx, appCode string, cmd domain.DrawCommand, state luckyBatchDrawState, nowMS int64) error { aggregate := state.AggregateResult payload, _ := json.Marshal(map[string]any{ "event_type": "lucky_gift_drawn", @@ -862,14 +962,7 @@ func (r *Repository) insertLuckyAggregateDrawOutbox(ctx context.Context, tx *sql "high_multiplier": aggregate.HighMultiplier, "created_at_ms": nowMS, }) - _, err := tx.ExecContext(ctx, ` - INSERT INTO activity_outbox ( - app_code, outbox_id, event_type, payload, status, retry_count, next_retry_at_ms, - locked_by, lock_until_ms, last_error, created_at_ms, updated_at_ms - ) VALUES (?, ?, 'LuckyGiftDrawn', ?, 'pending', 0, ?, '', 0, '', ?, ?)`, - appCode, "lucky_"+aggregate.DrawID, payload, nowMS, nowMS, nowMS, - ) - return err + return r.insertLuckyRewardSettlementOutbox(ctx, tx, appCode, aggregate.DrawID, payload, nowMS) } func (r *Repository) executeSingleLuckyGiftDraw(ctx context.Context, tx *sql.Tx, cmd domain.DrawCommand, nowMS int64) (domain.DrawResult, error) { @@ -1278,29 +1371,8 @@ func (r *Repository) applyLuckyDraw(ctx context.Context, tx *sql.Tx, input lucky ); err != nil { return err } - if err := r.incrementLuckyDrawPoolStats(ctx, tx, []luckyDrawRecordInput{{ - AppCode: input.AppCode, - DrawID: input.DrawID, - Command: input.Command, - Config: input.Config, - ExperiencePool: input.ExperiencePool, - Candidate: input.Candidate, - Limited: input.Limited, - StageFeedback: input.StageFeedback, - GlobalWindow: input.GlobalWindow, - GiftWindow: input.GiftWindow, - PlatformPool: input.PlatformPool, - RoomPool: input.RoomPool, - GiftPool: input.GiftPool, - Atmosphere: input.Atmosphere, - BudgetSourcesJSON: input.BudgetSourcesJSON, - RewardStatus: input.RewardStatus, - NowMS: input.NowMS, - }}, input.NowMS); err != nil { - return err - } - if luckyDrawNeedsOutbox(input.Candidate, input.StageFeedback) { - // outbox 是钱包入账和房间 IM 的唯一异步出口;事务内只写事实,不调用外部 RPC。 + if luckyDrawNeedsRewardSettlementOutbox(input.Candidate) { + // outbox 只记录钱包返奖结算;表现层 IM/广播不参与可靠补偿链路。 payload, _ := json.Marshal(map[string]any{ "event_type": "lucky_gift_drawn", "event_id": "lucky_gift_drawn:" + input.DrawID, @@ -1328,20 +1400,29 @@ func (r *Repository) applyLuckyDraw(ctx context.Context, tx *sql.Tx, input lucky "high_multiplier": input.Candidate.HighMultiplier, "created_at_ms": input.NowMS, }) - if _, err := tx.ExecContext(ctx, ` - INSERT INTO activity_outbox ( - app_code, outbox_id, event_type, payload, status, retry_count, next_retry_at_ms, - locked_by, lock_until_ms, last_error, created_at_ms, updated_at_ms - ) VALUES (?, ?, 'LuckyGiftDrawn', ?, 'pending', 0, ?, '', 0, '', ?, ?)`, - input.AppCode, "lucky_"+input.DrawID, payload, input.NowMS, input.NowMS, input.NowMS, - ); err != nil { + if err := r.insertLuckyRewardSettlementOutbox(ctx, tx, input.AppCode, input.DrawID, payload, input.NowMS); err != nil { return err } } return nil } -// ClaimPendingLuckyGiftOutbox 抢占幸运礼物抽奖副作用。抽奖事实已在同一事务落库,worker 只补偿钱包和房间 IM。 +func (r *Repository) insertLuckyRewardSettlementOutbox(ctx context.Context, tx *sql.Tx, appCode string, drawID string, payload []byte, nowMS int64) error { + return r.insertLuckyDrawOutbox(ctx, tx, appCode, "lucky_reward_"+drawID, domain.EventTypeLuckyGiftRewardSettlement, payload, nowMS) +} + +func (r *Repository) insertLuckyDrawOutbox(ctx context.Context, tx *sql.Tx, appCode string, outboxID string, eventType string, payload []byte, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO activity_outbox ( + app_code, outbox_id, event_type, payload, status, retry_count, next_retry_at_ms, + locked_by, lock_until_ms, last_error, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 'pending', 0, ?, '', 0, '', ?, ?)`, + appCode, outboxID, eventType, payload, nowMS, nowMS, nowMS, + ) + return err +} + +// ClaimPendingLuckyGiftOutbox 抢占幸运礼物抽奖副作用。抽奖事实已在同一事务落库,worker 优先补偿影响 reward_status 的结算事件。 func (r *Repository) ClaimPendingLuckyGiftOutbox(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int) ([]domain.DrawOutbox, error) { if r == nil || r.db == nil { return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") @@ -1366,34 +1447,50 @@ func (r *Repository) ClaimPendingLuckyGiftOutbox(ctx context.Context, workerID s defer func() { _ = tx.Rollback() }() appCode := appcode.FromContext(ctx) - events, err := r.queryLuckyGiftOutboxCandidates(ctx, tx, ` - SELECT app_code, outbox_id, event_type, COALESCE(CAST(payload AS CHAR), '{}'), retry_count, created_at_ms - FROM activity_outbox FORCE INDEX (idx_activity_outbox_lucky_retry) - WHERE app_code = ? - AND event_type = 'LuckyGiftDrawn' - AND status IN ('pending', 'retryable') - AND next_retry_at_ms <= ? - ORDER BY created_at_ms ASC, outbox_id ASC - LIMIT ? - FOR UPDATE`, batchSize, appCode, nowMS, batchSize) - if err != nil { - return nil, err + events := make([]domain.DrawOutbox, 0, batchSize) + priorityTypes := []string{ + domain.EventTypeLuckyGiftRewardSettlement, + domain.EventTypeLuckyGiftDrawn, } - if remaining := batchSize - len(events); remaining > 0 { - retryEvents, err := r.queryLuckyGiftOutboxCandidates(ctx, tx, ` + for _, eventType := range priorityTypes { + candidates, err := r.queryLuckyGiftOutboxCandidates(ctx, tx, ` SELECT app_code, outbox_id, event_type, COALESCE(CAST(payload AS CHAR), '{}'), retry_count, created_at_ms - FROM activity_outbox FORCE INDEX (idx_activity_outbox_lucky_lock) + FROM activity_outbox FORCE INDEX (idx_activity_outbox_lucky_retry) WHERE app_code = ? - AND event_type = 'LuckyGiftDrawn' - AND status = 'delivering' - AND lock_until_ms <= ? + AND event_type = ? + AND status IN ('pending', 'retryable') + AND next_retry_at_ms <= ? ORDER BY created_at_ms ASC, outbox_id ASC LIMIT ? - FOR UPDATE`, remaining, appCode, nowMS, remaining) + FOR UPDATE`, batchSize, appCode, eventType, nowMS, batchSize) if err != nil { return nil, err } - events = append(events, retryEvents...) + if len(candidates) > 0 { + events = append(events, candidates...) + break + } + } + if len(events) == 0 { + for _, eventType := range priorityTypes { + retryEvents, err := r.queryLuckyGiftOutboxCandidates(ctx, tx, ` + SELECT app_code, outbox_id, event_type, COALESCE(CAST(payload AS CHAR), '{}'), retry_count, created_at_ms + FROM activity_outbox FORCE INDEX (idx_activity_outbox_lucky_lock) + WHERE app_code = ? + AND event_type = ? + AND status = 'delivering' + AND lock_until_ms <= ? + ORDER BY created_at_ms ASC, outbox_id ASC + LIMIT ? + FOR UPDATE`, batchSize, appCode, eventType, nowMS, batchSize) + if err != nil { + return nil, err + } + if len(retryEvents) > 0 { + events = append(events, retryEvents...) + break + } + } } lockUntilMS := nowMS + lockTTL.Milliseconds() for _, event := range events { @@ -1566,11 +1663,6 @@ func (r *Repository) markLuckyGiftDraws(ctx context.Context, appCode string, dra if err != nil { return err } - deltas, err := r.selectLuckyDrawStatusDeltas(ctx, tx, appCode, chunk, status, onlyPending) - if err != nil { - _ = tx.Rollback() - return err - } args := []any{status, walletTransactionID, failureReason, nowMS, appCode} for _, drawID := range chunk { args = append(args, drawID) @@ -1588,10 +1680,6 @@ func (r *Repository) markLuckyGiftDraws(ctx context.Context, appCode string, dra _ = tx.Rollback() return err } - if err := r.applyLuckyDrawStatusDeltas(ctx, tx, appCode, deltas, status, nowMS); err != nil { - _ = tx.Rollback() - return err - } if err := tx.Commit(); err != nil { return err } @@ -1599,96 +1687,6 @@ func (r *Repository) markLuckyGiftDraws(ctx context.Context, appCode string, dra return nil } -type luckyDrawStatusDelta struct { - PoolID string - GiftID string - OldStatus string - Count int64 -} - -func (r *Repository) selectLuckyDrawStatusDeltas(ctx context.Context, tx *sql.Tx, appCode string, drawIDs []string, targetStatus string, onlyPending bool) ([]luckyDrawStatusDelta, error) { - args := []any{appCode} - for _, drawID := range drawIDs { - args = append(args, drawID) - } - args = append(args, targetStatus) - query := ` - SELECT pool_id, gift_id, reward_status, COUNT(*) - FROM lucky_draw_records - WHERE app_code = ? AND draw_id IN (` + luckySQLPlaceholders(len(drawIDs)) + `) AND reward_status <> ?` - if onlyPending { - query += ` AND reward_status = ?` - args = append(args, domain.StatusPending) - } - query += ` GROUP BY pool_id, gift_id, reward_status` - rows, err := tx.QueryContext(ctx, query, args...) - if err != nil { - return nil, err - } - defer rows.Close() - deltas := []luckyDrawStatusDelta{} - for rows.Next() { - var delta luckyDrawStatusDelta - if err := rows.Scan(&delta.PoolID, &delta.GiftID, &delta.OldStatus, &delta.Count); err != nil { - return nil, err - } - deltas = append(deltas, delta) - } - return deltas, rows.Err() -} - -func (r *Repository) applyLuckyDrawStatusDeltas(ctx context.Context, tx *sql.Tx, appCode string, deltas []luckyDrawStatusDelta, targetStatus string, nowMS int64) error { - for _, delta := range deltas { - keys := []luckyDrawPoolStatKey{{AppCode: appCode, PoolID: delta.PoolID, GiftID: ""}} - if strings.TrimSpace(delta.GiftID) != "" { - keys = append(keys, luckyDrawPoolStatKey{AppCode: appCode, PoolID: delta.PoolID, GiftID: delta.GiftID}) - } - for _, key := range keys { - if err := r.applyLuckyDrawStatusDelta(ctx, tx, key, delta.OldStatus, targetStatus, delta.Count, nowMS); err != nil { - return err - } - } - } - return nil -} - -func (r *Repository) applyLuckyDrawStatusDelta(ctx context.Context, tx *sql.Tx, key luckyDrawPoolStatKey, oldStatus string, targetStatus string, count int64, nowMS int64) error { - pendingDelta, grantedDelta, failedDelta := luckyStatusCounterDelta(oldStatus, targetStatus, count) - if pendingDelta == 0 && grantedDelta == 0 && failedDelta == 0 { - return nil - } - _, err := tx.ExecContext(ctx, ` - UPDATE lucky_draw_pool_stats - SET pending_draws = pending_draws + ?, - granted_draws = granted_draws + ?, - failed_draws = failed_draws + ?, - updated_at_ms = ? - WHERE app_code = ? AND pool_id = ? AND gift_id = ?`, - pendingDelta, grantedDelta, failedDelta, nowMS, key.AppCode, key.PoolID, key.GiftID, - ) - return err -} - -func luckyStatusCounterDelta(oldStatus string, targetStatus string, count int64) (pending int64, granted int64, failed int64) { - switch oldStatus { - case domain.StatusPending: - pending -= count - case domain.StatusGranted: - granted -= count - case domain.StatusFailed: - failed -= count - } - switch targetStatus { - case domain.StatusPending: - pending += count - case domain.StatusGranted: - granted += count - case domain.StatusFailed: - failed += count - } - return pending, granted, failed -} - // normalizeLuckyDrawIDs 去掉空值和重复值;outbox payload 是补偿输入,必须先清洗再拼 SQL IN。 func normalizeLuckyDrawIDs(drawIDs []string) []string { seen := map[string]bool{} @@ -1820,8 +1818,7 @@ func (r *Repository) getLuckyGiftDrawSummaryFromStats(ctx context.Context, query summary.PoolID = query.PoolID err := r.db.QueryRowContext(ctx, ` SELECT total_draws, unique_users, unique_rooms, total_spent_coins, total_reward_coins, - base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, - pending_draws, granted_draws, failed_draws + base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins FROM lucky_draw_pool_stats WHERE app_code = ? AND pool_id = ? AND gift_id = ?`, appcode.FromContext(ctx), query.PoolID, strings.TrimSpace(query.GiftID), @@ -1834,22 +1831,88 @@ func (r *Repository) getLuckyGiftDrawSummaryFromStats(ctx context.Context, query &summary.BaseRewardCoins, &summary.RoomAtmosphereRewardCoins, &summary.ActivitySubsidyCoins, - &summary.PendingDraws, - &summary.GrantedDraws, - &summary.FailedDraws, ) if errors.Is(err, sql.ErrNoRows) { - return r.getLuckyGiftDrawSummaryFromRecords(ctx, query) + return summary, nil } if err != nil { return domain.DrawSummary{}, err } + if err := r.loadLuckyGiftDrawStatusCounts(ctx, query, &summary); err != nil { + return domain.DrawSummary{}, err + } if summary.TotalSpentCoins > 0 { summary.ActualRTPPPM = summary.TotalRewardCoins * luckyPPMScale / summary.TotalSpentCoins } return summary, nil } +func (r *Repository) loadLuckyGiftDrawStatusCounts(ctx context.Context, query domain.DrawQuery, summary *domain.DrawSummary) error { + if summary == nil { + return nil + } + appCode := appcode.FromContext(ctx) + where := []string{"app_code = ?"} + args := []any{appCode} + if strings.TrimSpace(query.PoolID) != "" { + where = append(where, "pool_id = ?") + args = append(args, query.PoolID) + } + indexName := "idx_lucky_draw_pool_status_summary" + if strings.TrimSpace(query.GiftID) != "" { + indexName = "idx_lucky_draw_gift_status_summary" + where = append(where, "gift_id = ?") + args = append(args, strings.TrimSpace(query.GiftID)) + } + if cursor, exists, err := r.getLuckyDrawStatsCursor(ctx, appCode); err != nil { + return err + } else if exists && (cursor.LastDrawCreatedAtMS > 0 || cursor.LastDrawID != "") { + where = append(where, "(created_at_ms < ? OR (created_at_ms = ? AND draw_id <= ?))") + args = append(args, cursor.LastDrawCreatedAtMS, cursor.LastDrawCreatedAtMS, cursor.LastDrawID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT reward_status, COUNT(*) + FROM lucky_draw_records FORCE INDEX (`+indexName+`) + WHERE `+strings.Join(where, " AND ")+` + GROUP BY reward_status`, args...) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var status string + var count int64 + if err := rows.Scan(&status, &count); err != nil { + return err + } + switch status { + case domain.StatusPending: + summary.PendingDraws = count + case domain.StatusGranted: + summary.GrantedDraws = count + case domain.StatusFailed: + summary.FailedDraws = count + } + } + return rows.Err() +} + +func (r *Repository) getLuckyDrawStatsCursor(ctx context.Context, appCode string) (luckyDrawStatsCursor, bool, error) { + var cursor luckyDrawStatsCursor + err := r.db.QueryRowContext(ctx, ` + SELECT last_draw_created_at_ms, last_draw_id + FROM lucky_draw_pool_stat_cursors + WHERE app_code = ? AND cursor_name = 'draw_records'`, appCode, + ).Scan(&cursor.LastDrawCreatedAtMS, &cursor.LastDrawID) + if errors.Is(err, sql.ErrNoRows) { + return luckyDrawStatsCursor{}, false, nil + } + if err != nil { + return luckyDrawStatsCursor{}, false, err + } + return cursor, true, nil +} + func luckyDrawWhereClause(appCode string, query domain.DrawQuery) (string, []any) { where := []string{"app_code = ?"} args := []any{appCode} @@ -2747,17 +2810,15 @@ func luckyBudgetSourcesJSON(candidate luckyCandidate) string { return string(raw) } -func luckyInitialRewardStatus(candidate luckyCandidate, stageFeedback bool) string { - // 没有金币返还、也没有房间展示副作用时,抽奖事实已经终态化;不能留给不存在的 outbox 消费。 - if !luckyDrawNeedsOutbox(candidate, stageFeedback) { - return domain.StatusGranted +func luckyInitialRewardStatus(candidate luckyCandidate, _ bool) string { + if luckyDrawNeedsRewardSettlementOutbox(candidate) { + return domain.StatusPending } - return domain.StatusPending + return domain.StatusGranted } -func luckyDrawNeedsOutbox(candidate luckyCandidate, stageFeedback bool) bool { - // outbox 只承载真实异步副作用:钱包入账、房间 IM 展示或阶段反馈展示。 - return candidate.effectiveReward() > 0 || stageFeedback || candidate.Presentation +func luckyDrawNeedsRewardSettlementOutbox(candidate luckyCandidate) bool { + return candidate.effectiveReward() > 0 } func luckyEnabledReason(enabled bool) string { diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go index 28e0e160..a2cb3aa0 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go @@ -1,9 +1,13 @@ package mysql import ( + "context" "strings" "testing" + "time" + "hyapp/internal/testutil/mysqlschema" + "hyapp/pkg/appcode" domain "hyapp/services/activity-service/internal/domain/luckygift" ) @@ -36,6 +40,148 @@ func TestLuckyRuntimeConfigScalesTierRewardsByActualSpendButKeepsRiskCapsAbsolut } } +func TestClaimPendingLuckyGiftOutboxPrioritizesRewardSettlement(t *testing.T) { + schema := mysqlschema.New(t, mysqlschema.Config{ + EnvVar: "ACTIVITY_SERVICE_MYSQL_TEST_DSN", + InitDBPath: mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_activity_service.sql"), + DatabasePrefix: "hyapp_activity_lucky_outbox_test", + }) + repository, err := Open(context.Background(), schema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + ctx := appcode.WithContext(context.Background(), "lalu") + nowMS := int64(1_700_000_000_000) + _, err = repository.db.ExecContext(ctx, ` + INSERT INTO activity_outbox ( + app_code, outbox_id, event_type, payload, status, retry_count, next_retry_at_ms, + locked_by, lock_until_ms, last_error, created_at_ms, updated_at_ms + ) VALUES + ('lalu', 'lucky_legacy_draw_1', ?, '{}', 'pending', 0, ?, '', 0, '', ?, ?), + ('lalu', 'lucky_reward_draw_1', ?, '{}', 'pending', 0, ?, '', 0, '', ?, ?)`, + domain.EventTypeLuckyGiftDrawn, nowMS-100, nowMS-200, nowMS-200, + domain.EventTypeLuckyGiftRewardSettlement, nowMS-100, nowMS-100, nowMS-100, + ) + if err != nil { + t.Fatalf("seed activity_outbox: %v", err) + } + + events, err := repository.ClaimPendingLuckyGiftOutbox(ctx, "worker-priority", nowMS, 30*time.Second, 10) + if err != nil { + t.Fatalf("ClaimPendingLuckyGiftOutbox failed: %v", err) + } + if len(events) != 1 || events[0].EventType != domain.EventTypeLuckyGiftRewardSettlement || events[0].OutboxID != "lucky_reward_draw_1" { + t.Fatalf("claim should only return reward settlement first, got %+v", events) + } + var legacyStatus string + if err := repository.db.QueryRowContext(ctx, ` + SELECT status FROM activity_outbox WHERE app_code = 'lalu' AND outbox_id = 'lucky_legacy_draw_1'`).Scan(&legacyStatus); err != nil { + t.Fatalf("read legacy outbox status: %v", err) + } + if legacyStatus != "pending" { + t.Fatalf("legacy outbox should remain pending while reward settlement exists, got %s", legacyStatus) + } +} + +func TestRefreshLuckyGiftAdminStatsSnapshotsAdvancesCursorByBatch(t *testing.T) { + schema := mysqlschema.New(t, mysqlschema.Config{ + EnvVar: "ACTIVITY_SERVICE_MYSQL_TEST_DSN", + InitDBPath: mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_activity_service.sql"), + DatabasePrefix: "hyapp_activity_lucky_stats_test", + }) + repository, err := Open(context.Background(), schema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + ctx := appcode.WithContext(context.Background(), "lalu") + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO lucky_draw_pool_stat_cursors ( + app_code, cursor_name, last_draw_created_at_ms, last_draw_id, created_at_ms, updated_at_ms + ) VALUES ('lalu', 'draw_records', 0, '', 1, 1)`); err != nil { + t.Fatalf("seed stats cursor: %v", err) + } + seedLuckyDrawRecordForStats(t, repository, "draw_001", "cmd_001", domain.StatusGranted, 100, 100, 300) + seedLuckyDrawRecordForStats(t, repository, "draw_002", "cmd_002", domain.StatusPending, 200, 150, 0) + + processed, err := repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, 300, 1) + if err != nil { + t.Fatalf("first refresh failed: %v", err) + } + if processed != 1 { + t.Fatalf("first refresh should process one row, got %d", processed) + } + assertLuckyStatsTotal(t, repository, "", 1, 100, 300) + assertLuckyStatsCursor(t, repository, 100, "draw_001") + + processed, err = repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, 400, 10) + if err != nil { + t.Fatalf("second refresh failed: %v", err) + } + if processed != 1 { + t.Fatalf("second refresh should process remaining row, got %d", processed) + } + assertLuckyStatsTotal(t, repository, "", 2, 250, 300) + assertLuckyStatsCursor(t, repository, 200, "draw_002") +} + +func seedLuckyDrawRecordForStats(t *testing.T, repository *Repository, drawID string, commandID string, status string, createdAtMS int64, spent int64, reward int64) { + t.Helper() + _, err := repository.db.ExecContext(context.Background(), ` + INSERT INTO lucky_draw_records ( + app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, pool_id, gift_id, + coin_spent, rule_version, experience_pool, rtp_window_index, gift_rtp_window_index, + selected_tier_id, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + effective_reward_coins, budget_sources_json, stage_feedback, high_multiplier, + candidate_tiers_json, pool_snapshot_json, rtp_snapshot_json, reward_status, + reward_transaction_id, reward_failure_reason, paid_at_ms, created_at_ms, updated_at_ms + ) VALUES ( + 'lalu', ?, ?, 42, 'device-1', 'room-1', 'anchor-1', 'lucky', 'rose', + ?, 1, 'novice', 1, 1, + 'tier', ?, 0, 0, + ?, '{}', 0, 0, + '{}', '{}', '{}', ?, + '', '', ?, ?, ? + )`, drawID, commandID, spent, reward, reward, status, createdAtMS, createdAtMS, createdAtMS) + if err != nil { + t.Fatalf("seed draw record %s: %v", drawID, err) + } +} + +func assertLuckyStatsTotal(t *testing.T, repository *Repository, giftID string, wantDraws int64, wantSpent int64, wantReward int64) { + t.Helper() + var draws, spent, reward int64 + if err := repository.db.QueryRowContext(context.Background(), ` + SELECT total_draws, total_spent_coins, total_reward_coins + FROM lucky_draw_pool_stats + WHERE app_code = 'lalu' AND pool_id = 'lucky' AND gift_id = ?`, giftID, + ).Scan(&draws, &spent, &reward); err != nil { + t.Fatalf("read stats total: %v", err) + } + if draws != wantDraws || spent != wantSpent || reward != wantReward { + t.Fatalf("stats mismatch: draws=%d spent=%d reward=%d want draws=%d spent=%d reward=%d", draws, spent, reward, wantDraws, wantSpent, wantReward) + } +} + +func assertLuckyStatsCursor(t *testing.T, repository *Repository, wantCreatedAtMS int64, wantDrawID string) { + t.Helper() + var createdAtMS int64 + var drawID string + if err := repository.db.QueryRowContext(context.Background(), ` + SELECT last_draw_created_at_ms, last_draw_id + FROM lucky_draw_pool_stat_cursors + WHERE app_code = 'lalu' AND cursor_name = 'draw_records'`, + ).Scan(&createdAtMS, &drawID); err != nil { + t.Fatalf("read stats cursor: %v", err) + } + if createdAtMS != wantCreatedAtMS || drawID != wantDrawID { + t.Fatalf("cursor mismatch: created_at=%d draw_id=%s want created_at=%d draw_id=%s", createdAtMS, drawID, wantCreatedAtMS, wantDrawID) + } +} + func TestLuckyRuntimeConfigFromRuleConfigUsesV2PoolAndStageTiers(t *testing.T) { ruleConfig := domain.RuleConfig{ AppCode: "lalu", @@ -399,29 +545,31 @@ func TestLuckyInitialRewardStatusGrantsZeroRewardWithoutOutbox(t *testing.T) { if status := luckyInitialRewardStatus(luckyCandidate{TierID: "none"}, false); status != domain.StatusGranted { t.Fatalf("zero reward without presentation should be granted, got %s", status) } - if luckyDrawNeedsOutbox(luckyCandidate{TierID: "none"}, false) { + if luckyDrawNeedsRewardSettlementOutbox(luckyCandidate{TierID: "none"}) { t.Fatalf("zero reward without presentation must not emit outbox") } } -func TestLuckyInitialRewardStatusKeepsAsyncSideEffectsPending(t *testing.T) { +func TestLuckyInitialRewardStatusOnlyWaitsForWalletSettlement(t *testing.T) { tests := []struct { name string candidate luckyCandidate stageFeedback bool + wantStatus string + wantReward bool }{ - {name: "wallet credit", candidate: luckyCandidate{TierID: "hit", BaseReward: 10}}, - {name: "presentation candidate", candidate: luckyCandidate{TierID: "stage", Presentation: true}}, - {name: "stage feedback", candidate: luckyCandidate{TierID: "none"}, stageFeedback: true}, + {name: "wallet credit", candidate: luckyCandidate{TierID: "hit", BaseReward: 10}, wantStatus: domain.StatusPending, wantReward: true}, + {name: "presentation candidate", candidate: luckyCandidate{TierID: "stage", Presentation: true}, wantStatus: domain.StatusGranted}, + {name: "stage feedback", candidate: luckyCandidate{TierID: "none"}, stageFeedback: true, wantStatus: domain.StatusGranted}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - if status := luckyInitialRewardStatus(test.candidate, test.stageFeedback); status != domain.StatusPending { - t.Fatalf("async side effect should stay pending, got %s", status) + if status := luckyInitialRewardStatus(test.candidate, test.stageFeedback); status != test.wantStatus { + t.Fatalf("reward status mismatch: got %s want %s", status, test.wantStatus) } - if !luckyDrawNeedsOutbox(test.candidate, test.stageFeedback) { - t.Fatalf("async side effect should emit outbox") + if got := luckyDrawNeedsRewardSettlementOutbox(test.candidate); got != test.wantReward { + t.Fatalf("reward settlement outbox mismatch: got %v want %v", got, test.wantReward) } }) } diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_settlement_pressure_test.go b/services/activity-service/internal/storage/mysql/lucky_gift_settlement_pressure_test.go new file mode 100644 index 00000000..7f9e2db4 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/lucky_gift_settlement_pressure_test.go @@ -0,0 +1,196 @@ +package mysql + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strings" + "sync/atomic" + "testing" + "time" + + "hyapp/internal/testutil/mysqlschema" + "hyapp/pkg/appcode" + domain "hyapp/services/activity-service/internal/domain/luckygift" + luckygiftservice "hyapp/services/activity-service/internal/service/luckygift" + + "google.golang.org/grpc" + walletv1 "hyapp.local/api/proto/wallet/v1" +) + +func TestLuckyGiftRewardSettlementOutboxPressureLocal(t *testing.T) { + if os.Getenv("RUN_LUCKY_GIFT_SETTLEMENT_PRESSURE") != "1" { + t.Skip("set RUN_LUCKY_GIFT_SETTLEMENT_PRESSURE=1 to run local settlement outbox pressure test") + } + cases := []struct { + name string + total int + batchSize int + concurrency int + }{ + {name: "1k_batch100_c4", total: 1000, batchSize: 100, concurrency: 4}, + {name: "5k_batch100_c4", total: 5000, batchSize: 100, concurrency: 4}, + {name: "10k_batch200_c8", total: 10000, batchSize: 200, concurrency: 8}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + runLuckyGiftSettlementPressureCase(t, tc.total, tc.batchSize, tc.concurrency) + }) + } +} + +func runLuckyGiftSettlementPressureCase(t *testing.T, total int, batchSize int, concurrency int) { + t.Helper() + schema := mysqlschema.New(t, mysqlschema.Config{ + EnvVar: "ACTIVITY_SERVICE_MYSQL_TEST_DSN", + InitDBPath: mysqlschema.InitDBPath(t, mysqlschema.CallerFile(t, 1), "..", "..", "..", "deploy", "mysql", "initdb", "001_activity_service.sql"), + DatabasePrefix: "hy_lucky_press", + }) + repository, err := Open(context.Background(), schema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + seedStart := time.Now() + seedLuckyGiftSettlementPressureRows(t, repository, total) + seedElapsed := time.Since(seedStart) + + wallet := &pressureLuckyGiftWallet{} + service := luckygiftservice.New(repository, luckygiftservice.WithWallet(wallet)) + ctx := appcode.WithContext(context.Background(), "lalu") + options := luckygiftservice.WorkerOptions{ + WorkerID: "pressure-worker", + BatchSize: batchSize, + Concurrency: concurrency, + LockTTL: time.Minute, + MaxRetry: 3, + } + + start := time.Now() + processedTotal := 0 + loops := 0 + for processedTotal < total { + processed, err := service.ProcessPendingDrawOutbox(ctx, options) + if err != nil { + t.Fatalf("process settlement outbox: %v", err) + } + if processed == 0 { + break + } + processedTotal += processed + loops++ + } + elapsed := time.Since(start) + granted := countLuckyGiftPressureRows(t, repository, "lucky_draw_records", "reward_status = 'granted'") + delivered := countLuckyGiftPressureRows(t, repository, "activity_outbox", "status = 'delivered'") + if processedTotal != total || granted != int64(total) || delivered != int64(total) || wallet.calls.Load() != int64(total) { + t.Fatalf("pressure result mismatch: processed=%d granted=%d delivered=%d wallet_calls=%d total=%d", + processedTotal, granted, delivered, wallet.calls.Load(), total) + } + t.Logf("settlement_pressure total=%d batch=%d concurrency=%d loops=%d seed_ms=%d process_ms=%d throughput=%.2f events/s avg_event_ms=%.4f", + total, batchSize, concurrency, loops, seedElapsed.Milliseconds(), elapsed.Milliseconds(), + float64(total)/elapsed.Seconds(), float64(elapsed.Microseconds())/1000.0/float64(total)) +} + +func seedLuckyGiftSettlementPressureRows(t *testing.T, repository *Repository, total int) { + t.Helper() + const chunkSize = 500 + for start := 0; start < total; start += chunkSize { + end := start + chunkSize + if end > total { + end = total + } + if err := seedLuckyGiftSettlementPressureChunk(repository, start, end); err != nil { + t.Fatalf("seed pressure rows %d-%d: %v", start, end, err) + } + } +} + +func seedLuckyGiftSettlementPressureChunk(repository *Repository, start int, end int) error { + nowMS := time.Now().UTC().UnixMilli() + drawPlaceholders := make([]string, 0, end-start) + drawArgs := make([]any, 0, (end-start)*31) + outboxPlaceholders := make([]string, 0, end-start) + outboxArgs := make([]any, 0, (end-start)*12) + for index := start; index < end; index++ { + drawID := fmt.Sprintf("pressure_draw_%08d", index) + commandID := fmt.Sprintf("pressure_cmd_%08d", index) + userID := int64(100000 + index%1000) + roomID := fmt.Sprintf("room_%03d", index%100) + createdAtMS := nowMS + int64(index) + drawPlaceholders = append(drawPlaceholders, "("+luckySQLPlaceholders(31)+")") + drawArgs = append(drawArgs, + "lalu", drawID, commandID, userID, "pressure-device", roomID, "pressure-anchor", "lucky", "rose", + int64(100), int64(1), domain.PoolNovice, int64(1), int64(1), + "hit", int64(10), int64(0), int64(0), + int64(10), "{}", false, false, + "{}", "{}", "{}", domain.StatusPending, "", "", + createdAtMS, createdAtMS, createdAtMS, + ) + payload, _ := json.Marshal(map[string]any{ + "event_type": "lucky_gift_drawn", + "event_id": "lucky_gift_drawn:" + drawID, + "app_code": "lalu", + "draw_id": drawID, + "command_id": commandID, + "pool_id": "lucky", + "user_id": userID, + "room_id": roomID, + "gift_id": "rose", + "gift_count": 1, + "coin_spent": 100, + "effective_reward_coins": 10, + "created_at_ms": createdAtMS, + }) + outboxPlaceholders = append(outboxPlaceholders, "("+luckySQLPlaceholders(12)+")") + outboxArgs = append(outboxArgs, + "lalu", "lucky_reward_"+drawID, domain.EventTypeLuckyGiftRewardSettlement, payload, + "pending", 0, createdAtMS, "", int64(0), "", createdAtMS, createdAtMS, + ) + } + ctx := context.Background() + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO lucky_draw_records ( + app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, pool_id, gift_id, + coin_spent, rule_version, experience_pool, rtp_window_index, gift_rtp_window_index, + selected_tier_id, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + effective_reward_coins, budget_sources_json, stage_feedback, high_multiplier, + candidate_tiers_json, pool_snapshot_json, rtp_snapshot_json, reward_status, + reward_transaction_id, reward_failure_reason, paid_at_ms, created_at_ms, updated_at_ms + ) VALUES `+strings.Join(drawPlaceholders, ","), drawArgs...); err != nil { + return err + } + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO activity_outbox ( + app_code, outbox_id, event_type, payload, status, retry_count, next_retry_at_ms, + locked_by, lock_until_ms, last_error, created_at_ms, updated_at_ms + ) VALUES `+strings.Join(outboxPlaceholders, ","), outboxArgs...); err != nil { + return err + } + return nil +} + +func countLuckyGiftPressureRows(t *testing.T, repository *Repository, table string, where string) int64 { + t.Helper() + var count int64 + if err := repository.db.QueryRowContext(context.Background(), "SELECT COUNT(*) FROM "+table+" WHERE app_code = 'lalu' AND "+where).Scan(&count); err != nil { + t.Fatalf("count %s: %v", table, err) + } + return count +} + +type pressureLuckyGiftWallet struct { + calls atomic.Int64 +} + +func (w *pressureLuckyGiftWallet) CreditLuckyGiftReward(_ context.Context, req *walletv1.CreditLuckyGiftRewardRequest, _ ...grpc.CallOption) (*walletv1.CreditLuckyGiftRewardResponse, error) { + w.calls.Add(1) + return &walletv1.CreditLuckyGiftRewardResponse{ + TransactionId: "pressure_tx_" + req.GetDrawId(), + Balance: &walletv1.AssetBalance{AvailableAmount: 1_000_000}, + Amount: req.GetAmount(), + GrantedAtMs: time.Now().UTC().UnixMilli(), + }, nil +} diff --git a/services/activity-service/internal/storage/mysql/repository.go b/services/activity-service/internal/storage/mysql/repository.go index 781f7542..2d9c43a2 100644 --- a/services/activity-service/internal/storage/mysql/repository.go +++ b/services/activity-service/internal/storage/mysql/repository.go @@ -102,107 +102,22 @@ func (r *Repository) ensureLuckyDrawPoolStatsTables(ctx context.Context) error { PRIMARY KEY (app_code, pool_id, gift_id, user_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物汇总用户去重'`, `CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_rooms ( - app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', - pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', - gift_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '礼物 ID,空值表示奖池汇总', - room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', - created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', - PRIMARY KEY (app_code, pool_id, gift_id, room_id) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物汇总房间去重'`, - } - for _, statement := range statements { - if _, err := r.db.ExecContext(ctx, statement); err != nil { - return err - } - } - return r.backfillLuckyDrawPoolStatsIfEmpty(ctx) -} - -func (r *Repository) backfillLuckyDrawPoolStatsIfEmpty(ctx context.Context) error { - var existing int64 - if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM lucky_draw_pool_stats LIMIT 1`).Scan(&existing); err != nil { - return err - } - if existing > 0 { - return nil - } - return r.backfillLuckyDrawPoolStats(ctx) -} - -func (r *Repository) backfillLuckyDrawPoolStats(ctx context.Context) error { - statements := []string{ - `INSERT IGNORE INTO lucky_draw_pool_stat_users (app_code, pool_id, gift_id, user_id, created_at_ms) - SELECT app_code, pool_id, '', user_id, MIN(created_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id, user_id`, - `INSERT IGNORE INTO lucky_draw_pool_stat_users (app_code, pool_id, gift_id, user_id, created_at_ms) - SELECT app_code, pool_id, gift_id, user_id, MIN(created_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id, gift_id, user_id`, - `INSERT IGNORE INTO lucky_draw_pool_stat_rooms (app_code, pool_id, gift_id, room_id, created_at_ms) - SELECT app_code, pool_id, '', room_id, MIN(created_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id, room_id`, - `INSERT IGNORE INTO lucky_draw_pool_stat_rooms (app_code, pool_id, gift_id, room_id, created_at_ms) - SELECT app_code, pool_id, gift_id, room_id, MIN(created_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id, gift_id, room_id`, - `INSERT INTO lucky_draw_pool_stats ( - app_code, pool_id, gift_id, total_draws, unique_users, unique_rooms, total_spent_coins, - total_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, - pending_draws, granted_draws, failed_draws, created_at_ms, updated_at_ms - ) - SELECT app_code, pool_id, '', COUNT(*), COUNT(DISTINCT user_id), COUNT(DISTINCT room_id), - COALESCE(SUM(coin_spent), 0), COALESCE(SUM(effective_reward_coins), 0), - COALESCE(SUM(base_reward_coins), 0), COALESCE(SUM(room_atmosphere_reward_coins), 0), - COALESCE(SUM(activity_subsidy_coins), 0), - COALESCE(SUM(CASE WHEN reward_status = 'pending' THEN 1 ELSE 0 END), 0), - COALESCE(SUM(CASE WHEN reward_status = 'granted' THEN 1 ELSE 0 END), 0), - COALESCE(SUM(CASE WHEN reward_status = 'failed' THEN 1 ELSE 0 END), 0), - MIN(created_at_ms), MAX(updated_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id - ON DUPLICATE KEY UPDATE - total_draws = VALUES(total_draws), - unique_users = VALUES(unique_users), - unique_rooms = VALUES(unique_rooms), - total_spent_coins = VALUES(total_spent_coins), - total_reward_coins = VALUES(total_reward_coins), - base_reward_coins = VALUES(base_reward_coins), - room_atmosphere_reward_coins = VALUES(room_atmosphere_reward_coins), - activity_subsidy_coins = VALUES(activity_subsidy_coins), - pending_draws = VALUES(pending_draws), - granted_draws = VALUES(granted_draws), - failed_draws = VALUES(failed_draws), - updated_at_ms = VALUES(updated_at_ms)`, - `INSERT INTO lucky_draw_pool_stats ( - app_code, pool_id, gift_id, total_draws, unique_users, unique_rooms, total_spent_coins, - total_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, - pending_draws, granted_draws, failed_draws, created_at_ms, updated_at_ms - ) - SELECT app_code, pool_id, gift_id, COUNT(*), COUNT(DISTINCT user_id), COUNT(DISTINCT room_id), - COALESCE(SUM(coin_spent), 0), COALESCE(SUM(effective_reward_coins), 0), - COALESCE(SUM(base_reward_coins), 0), COALESCE(SUM(room_atmosphere_reward_coins), 0), - COALESCE(SUM(activity_subsidy_coins), 0), - COALESCE(SUM(CASE WHEN reward_status = 'pending' THEN 1 ELSE 0 END), 0), - COALESCE(SUM(CASE WHEN reward_status = 'granted' THEN 1 ELSE 0 END), 0), - COALESCE(SUM(CASE WHEN reward_status = 'failed' THEN 1 ELSE 0 END), 0), - MIN(created_at_ms), MAX(updated_at_ms) - FROM lucky_draw_records - GROUP BY app_code, pool_id, gift_id - ON DUPLICATE KEY UPDATE - total_draws = VALUES(total_draws), - unique_users = VALUES(unique_users), - unique_rooms = VALUES(unique_rooms), - total_spent_coins = VALUES(total_spent_coins), - total_reward_coins = VALUES(total_reward_coins), - base_reward_coins = VALUES(base_reward_coins), - room_atmosphere_reward_coins = VALUES(room_atmosphere_reward_coins), - activity_subsidy_coins = VALUES(activity_subsidy_coins), - pending_draws = VALUES(pending_draws), - granted_draws = VALUES(granted_draws), - failed_draws = VALUES(failed_draws), - updated_at_ms = VALUES(updated_at_ms)`, + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', + gift_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '礼物 ID,空值表示奖池汇总', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, pool_id, gift_id, room_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物汇总房间去重'`, + `CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_cursors ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cursor_name VARCHAR(64) NOT NULL COMMENT '游标名称', + last_draw_created_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后已聚合 draw 创建时间', + last_draw_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '同一毫秒内最后已聚合 draw 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, cursor_name) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物后台统计快照游标'`, } for _, statement := range statements { if _, err := r.db.ExecContext(ctx, statement); err != nil { @@ -279,6 +194,25 @@ func (r *Repository) ensureLuckyDrawPoolID(ctx context.Context) error { return err } } + indexes := []struct { + name string + sql string + }{ + {"idx_lucky_draw_created", `CREATE INDEX idx_lucky_draw_created ON lucky_draw_records (app_code, created_at_ms, draw_id)`}, + {"idx_lucky_draw_pool_status_summary", `CREATE INDEX idx_lucky_draw_pool_status_summary ON lucky_draw_records (app_code, pool_id, reward_status, created_at_ms, draw_id)`}, + {"idx_lucky_draw_gift_status_summary", `CREATE INDEX idx_lucky_draw_gift_status_summary ON lucky_draw_records (app_code, pool_id, gift_id, reward_status, created_at_ms, draw_id)`}, + } + for _, addition := range indexes { + exists, err := r.indexExists(ctx, table, addition.name) + if err != nil { + return err + } + if !exists { + if _, err := r.db.ExecContext(ctx, addition.sql); err != nil { + return err + } + } + } return nil } From 679d068a8287355ad46fcfaa16d352612abccae4 Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 3 Jun 2026 00:02:19 +0800 Subject: [PATCH 02/28] feat: remove generic USD wallet balance --- api/proto/wallet/v1/wallet.pb.go | 943 ++++++------------ api/proto/wallet/v1/wallet.proto | 28 - api/proto/wallet/v1/wallet_grpc.pb.go | 38 - .../Flutter App 通知与钱包余额对接.md | 10 +- docs/主播公会BD后台架构.md | 16 +- docs/主播公会BD实施顺序.md | 6 +- docs/主播公会BD架构.md | 4 +- docs/币商库存授信架构.md | 2 +- docs/我的页概览接口.md | 5 +- docs/接口清单.md | 1 - docs/钱包服务架构.md | 22 +- ...remove_usd_balance_withdrawal_requests.sql | 55 + .../modules/teamsalarysettlement/service.go | 45 +- .../service_integration_test.go | 10 +- .../internal/client/wallet_client.go | 5 - .../transport/http/httproutes/router.go | 2 - .../internal/transport/http/response_test.go | 14 - .../http/walletapi/app_wallet_handler.go | 80 -- .../transport/http/walletapi/handler.go | 1 - .../mysql/initdb/001_wallet_service.sql | 22 - .../internal/domain/ledger/ledger.go | 39 +- .../internal/service/wallet/service.go | 19 - .../internal/service/wallet/service_test.go | 64 +- .../storage/mysql/app_wallet_repository.go | 135 +-- .../storage/mysql/host_salary_settlement.go | 14 +- .../internal/testutil/mysqltest/mysqltest.go | 2 +- .../internal/transport/grpc/server.go | 35 - 27 files changed, 500 insertions(+), 1117 deletions(-) create mode 100644 scripts/mysql/034_remove_usd_balance_withdrawal_requests.sql diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index b60fd2a2..f518ea72 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -6517,7 +6517,6 @@ type WalletFeatureFlags struct { state protoimpl.MessageState `protogen:"open.v1"` RechargeEnabled bool `protobuf:"varint,1,opt,name=recharge_enabled,json=rechargeEnabled,proto3" json:"recharge_enabled,omitempty"` DiamondExchangeEnabled bool `protobuf:"varint,2,opt,name=diamond_exchange_enabled,json=diamondExchangeEnabled,proto3" json:"diamond_exchange_enabled,omitempty"` - WithdrawEnabled bool `protobuf:"varint,3,opt,name=withdraw_enabled,json=withdrawEnabled,proto3" json:"withdraw_enabled,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -6566,13 +6565,6 @@ func (x *WalletFeatureFlags) GetDiamondExchangeEnabled() bool { return false } -func (x *WalletFeatureFlags) GetWithdrawEnabled() bool { - if x != nil { - return x.WithdrawEnabled - } - return false -} - type GetWalletOverviewRequest struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` @@ -8748,250 +8740,6 @@ func (x *ListWalletTransactionsResponse) GetTotal() int64 { return 0 } -type WithdrawalRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - WithdrawalId string `protobuf:"bytes,1,opt,name=withdrawal_id,json=withdrawalId,proto3" json:"withdrawal_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - PayoutAccount string `protobuf:"bytes,6,opt,name=payout_account,json=payoutAccount,proto3" json:"payout_account,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *WithdrawalRequest) Reset() { - *x = WithdrawalRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *WithdrawalRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WithdrawalRequest) ProtoMessage() {} - -func (x *WithdrawalRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] - 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 WithdrawalRequest.ProtoReflect.Descriptor instead. -func (*WithdrawalRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} -} - -func (x *WithdrawalRequest) GetWithdrawalId() string { - if x != nil { - return x.WithdrawalId - } - return "" -} - -func (x *WithdrawalRequest) GetUserId() int64 { - if x != nil { - return x.UserId - } - return 0 -} - -func (x *WithdrawalRequest) GetAssetType() string { - if x != nil { - return x.AssetType - } - return "" -} - -func (x *WithdrawalRequest) GetAmount() int64 { - if x != nil { - return x.Amount - } - return 0 -} - -func (x *WithdrawalRequest) GetStatus() string { - if x != nil { - return x.Status - } - return "" -} - -func (x *WithdrawalRequest) GetPayoutAccount() string { - if x != nil { - return x.PayoutAccount - } - return "" -} - -func (x *WithdrawalRequest) GetReason() string { - if x != nil { - return x.Reason - } - return "" -} - -func (x *WithdrawalRequest) GetCreatedAtMs() int64 { - if x != nil { - return x.CreatedAtMs - } - return 0 -} - -func (x *WithdrawalRequest) GetUpdatedAtMs() int64 { - if x != nil { - return x.UpdatedAtMs - } - return 0 -} - -type ApplyWithdrawalRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - PayoutAccount string `protobuf:"bytes,5,opt,name=payout_account,json=payoutAccount,proto3" json:"payout_account,omitempty"` - Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ApplyWithdrawalRequest) Reset() { - *x = ApplyWithdrawalRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ApplyWithdrawalRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyWithdrawalRequest) ProtoMessage() {} - -func (x *ApplyWithdrawalRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] - 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 ApplyWithdrawalRequest.ProtoReflect.Descriptor instead. -func (*ApplyWithdrawalRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} -} - -func (x *ApplyWithdrawalRequest) GetCommandId() string { - if x != nil { - return x.CommandId - } - return "" -} - -func (x *ApplyWithdrawalRequest) GetAppCode() string { - if x != nil { - return x.AppCode - } - return "" -} - -func (x *ApplyWithdrawalRequest) GetUserId() int64 { - if x != nil { - return x.UserId - } - return 0 -} - -func (x *ApplyWithdrawalRequest) GetAmount() int64 { - if x != nil { - return x.Amount - } - return 0 -} - -func (x *ApplyWithdrawalRequest) GetPayoutAccount() string { - if x != nil { - return x.PayoutAccount - } - return "" -} - -func (x *ApplyWithdrawalRequest) GetReason() string { - if x != nil { - return x.Reason - } - return "" -} - -type ApplyWithdrawalResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Withdrawal *WithdrawalRequest `protobuf:"bytes,1,opt,name=withdrawal,proto3" json:"withdrawal,omitempty"` - Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ApplyWithdrawalResponse) Reset() { - *x = ApplyWithdrawalResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ApplyWithdrawalResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyWithdrawalResponse) ProtoMessage() {} - -func (x *ApplyWithdrawalResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] - 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 ApplyWithdrawalResponse.ProtoReflect.Descriptor instead. -func (*ApplyWithdrawalResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} -} - -func (x *ApplyWithdrawalResponse) GetWithdrawal() *WithdrawalRequest { - if x != nil { - return x.Withdrawal - } - return nil -} - -func (x *ApplyWithdrawalResponse) GetBalance() *AssetBalance { - if x != nil { - return x.Balance - } - return nil -} - type VipRewardItem struct { state protoimpl.MessageState `protogen:"open.v1"` ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` @@ -9009,7 +8757,7 @@ type VipRewardItem struct { func (x *VipRewardItem) Reset() { *x = VipRewardItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9021,7 +8769,7 @@ func (x *VipRewardItem) String() string { func (*VipRewardItem) ProtoMessage() {} func (x *VipRewardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9034,7 +8782,7 @@ func (x *VipRewardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use VipRewardItem.ProtoReflect.Descriptor instead. func (*VipRewardItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} } func (x *VipRewardItem) GetResourceId() int64 { @@ -9123,7 +8871,7 @@ type VipLevel struct { func (x *VipLevel) Reset() { *x = VipLevel{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9135,7 +8883,7 @@ func (x *VipLevel) String() string { func (*VipLevel) ProtoMessage() {} func (x *VipLevel) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9148,7 +8896,7 @@ func (x *VipLevel) ProtoReflect() protoreflect.Message { // Deprecated: Use VipLevel.ProtoReflect.Descriptor instead. func (*VipLevel) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} } func (x *VipLevel) GetLevel() int32 { @@ -9271,7 +9019,7 @@ type UserVip struct { func (x *UserVip) Reset() { *x = UserVip{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9283,7 +9031,7 @@ func (x *UserVip) String() string { func (*UserVip) ProtoMessage() {} func (x *UserVip) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9296,7 +9044,7 @@ func (x *UserVip) ProtoReflect() protoreflect.Message { // Deprecated: Use UserVip.ProtoReflect.Descriptor instead. func (*UserVip) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} } func (x *UserVip) GetUserId() int64 { @@ -9359,7 +9107,7 @@ type ListVipPackagesRequest struct { func (x *ListVipPackagesRequest) Reset() { *x = ListVipPackagesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9371,7 +9119,7 @@ func (x *ListVipPackagesRequest) String() string { func (*ListVipPackagesRequest) ProtoMessage() {} func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9384,7 +9132,7 @@ func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesRequest.ProtoReflect.Descriptor instead. func (*ListVipPackagesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} } func (x *ListVipPackagesRequest) GetRequestId() string { @@ -9418,7 +9166,7 @@ type ListVipPackagesResponse struct { func (x *ListVipPackagesResponse) Reset() { *x = ListVipPackagesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9430,7 +9178,7 @@ func (x *ListVipPackagesResponse) String() string { func (*ListVipPackagesResponse) ProtoMessage() {} func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9443,7 +9191,7 @@ func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesResponse.ProtoReflect.Descriptor instead. func (*ListVipPackagesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} } func (x *ListVipPackagesResponse) GetCurrentVip() *UserVip { @@ -9471,7 +9219,7 @@ type GetMyVipRequest struct { func (x *GetMyVipRequest) Reset() { *x = GetMyVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9483,7 +9231,7 @@ func (x *GetMyVipRequest) String() string { func (*GetMyVipRequest) ProtoMessage() {} func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9496,7 +9244,7 @@ func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipRequest.ProtoReflect.Descriptor instead. func (*GetMyVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} } func (x *GetMyVipRequest) GetRequestId() string { @@ -9529,7 +9277,7 @@ type GetMyVipResponse struct { func (x *GetMyVipResponse) Reset() { *x = GetMyVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9541,7 +9289,7 @@ func (x *GetMyVipResponse) String() string { func (*GetMyVipResponse) ProtoMessage() {} func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9554,7 +9302,7 @@ func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipResponse.ProtoReflect.Descriptor instead. func (*GetMyVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} } func (x *GetMyVipResponse) GetVip() *UserVip { @@ -9576,7 +9324,7 @@ type PurchaseVipRequest struct { func (x *PurchaseVipRequest) Reset() { *x = PurchaseVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9588,7 +9336,7 @@ func (x *PurchaseVipRequest) String() string { func (*PurchaseVipRequest) ProtoMessage() {} func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9601,7 +9349,7 @@ func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipRequest.ProtoReflect.Descriptor instead. func (*PurchaseVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} } func (x *PurchaseVipRequest) GetCommandId() string { @@ -9646,7 +9394,7 @@ type PurchaseVipResponse struct { func (x *PurchaseVipResponse) Reset() { *x = PurchaseVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9658,7 +9406,7 @@ func (x *PurchaseVipResponse) String() string { func (*PurchaseVipResponse) ProtoMessage() {} func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9671,7 +9419,7 @@ func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipResponse.ProtoReflect.Descriptor instead. func (*PurchaseVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} } func (x *PurchaseVipResponse) GetOrderId() string { @@ -9731,7 +9479,7 @@ type GrantVipRequest struct { func (x *GrantVipRequest) Reset() { *x = GrantVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9743,7 +9491,7 @@ func (x *GrantVipRequest) String() string { func (*GrantVipRequest) ProtoMessage() {} func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9756,7 +9504,7 @@ func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipRequest.ProtoReflect.Descriptor instead. func (*GrantVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} } func (x *GrantVipRequest) GetCommandId() string { @@ -9820,7 +9568,7 @@ type GrantVipResponse struct { func (x *GrantVipResponse) Reset() { *x = GrantVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9832,7 +9580,7 @@ func (x *GrantVipResponse) String() string { func (*GrantVipResponse) ProtoMessage() {} func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9845,7 +9593,7 @@ func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipResponse.ProtoReflect.Descriptor instead. func (*GrantVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} } func (x *GrantVipResponse) GetTransactionId() string { @@ -9892,7 +9640,7 @@ type AdminVipLevelInput struct { func (x *AdminVipLevelInput) Reset() { *x = AdminVipLevelInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9904,7 +9652,7 @@ func (x *AdminVipLevelInput) String() string { func (*AdminVipLevelInput) ProtoMessage() {} func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9917,7 +9665,7 @@ func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminVipLevelInput.ProtoReflect.Descriptor instead. func (*AdminVipLevelInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} } func (x *AdminVipLevelInput) GetLevel() int32 { @@ -9986,7 +9734,7 @@ type ListAdminVipLevelsRequest struct { func (x *ListAdminVipLevelsRequest) Reset() { *x = ListAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9998,7 +9746,7 @@ func (x *ListAdminVipLevelsRequest) String() string { func (*ListAdminVipLevelsRequest) ProtoMessage() {} func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10011,7 +9759,7 @@ func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} } func (x *ListAdminVipLevelsRequest) GetRequestId() string { @@ -10038,7 +9786,7 @@ type ListAdminVipLevelsResponse struct { func (x *ListAdminVipLevelsResponse) Reset() { *x = ListAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10050,7 +9798,7 @@ func (x *ListAdminVipLevelsResponse) String() string { func (*ListAdminVipLevelsResponse) ProtoMessage() {} func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10063,7 +9811,7 @@ func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} } func (x *ListAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -10092,7 +9840,7 @@ type UpdateAdminVipLevelsRequest struct { func (x *UpdateAdminVipLevelsRequest) Reset() { *x = UpdateAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10104,7 +9852,7 @@ func (x *UpdateAdminVipLevelsRequest) String() string { func (*UpdateAdminVipLevelsRequest) ProtoMessage() {} func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10117,7 +9865,7 @@ func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} } func (x *UpdateAdminVipLevelsRequest) GetRequestId() string { @@ -10158,7 +9906,7 @@ type UpdateAdminVipLevelsResponse struct { func (x *UpdateAdminVipLevelsResponse) Reset() { *x = UpdateAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10170,7 +9918,7 @@ func (x *UpdateAdminVipLevelsResponse) String() string { func (*UpdateAdminVipLevelsResponse) ProtoMessage() {} func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10183,7 +9931,7 @@ func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} } func (x *UpdateAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -10217,7 +9965,7 @@ type CreditTaskRewardRequest struct { func (x *CreditTaskRewardRequest) Reset() { *x = CreditTaskRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10229,7 +9977,7 @@ func (x *CreditTaskRewardRequest) String() string { func (*CreditTaskRewardRequest) ProtoMessage() {} func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10242,7 +9990,7 @@ func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardRequest.ProtoReflect.Descriptor instead. func (*CreditTaskRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} } func (x *CreditTaskRewardRequest) GetCommandId() string { @@ -10314,7 +10062,7 @@ type CreditTaskRewardResponse struct { func (x *CreditTaskRewardResponse) Reset() { *x = CreditTaskRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10326,7 +10074,7 @@ func (x *CreditTaskRewardResponse) String() string { func (*CreditTaskRewardResponse) ProtoMessage() {} func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10339,7 +10087,7 @@ func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardResponse.ProtoReflect.Descriptor instead. func (*CreditTaskRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} } func (x *CreditTaskRewardResponse) GetTransactionId() string { @@ -10389,7 +10137,7 @@ type CreditLuckyGiftRewardRequest struct { func (x *CreditLuckyGiftRewardRequest) Reset() { *x = CreditLuckyGiftRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10401,7 +10149,7 @@ func (x *CreditLuckyGiftRewardRequest) String() string { func (*CreditLuckyGiftRewardRequest) ProtoMessage() {} func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10414,7 +10162,7 @@ func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardRequest.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} } func (x *CreditLuckyGiftRewardRequest) GetCommandId() string { @@ -10500,7 +10248,7 @@ type CreditLuckyGiftRewardResponse struct { func (x *CreditLuckyGiftRewardResponse) Reset() { *x = CreditLuckyGiftRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10512,7 +10260,7 @@ func (x *CreditLuckyGiftRewardResponse) String() string { func (*CreditLuckyGiftRewardResponse) ProtoMessage() {} func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10525,7 +10273,7 @@ func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardResponse.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} } func (x *CreditLuckyGiftRewardResponse) GetTransactionId() string { @@ -10577,7 +10325,7 @@ type ApplyGameCoinChangeRequest struct { func (x *ApplyGameCoinChangeRequest) Reset() { *x = ApplyGameCoinChangeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10589,7 +10337,7 @@ func (x *ApplyGameCoinChangeRequest) String() string { func (*ApplyGameCoinChangeRequest) ProtoMessage() {} func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10602,7 +10350,7 @@ func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeRequest.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} } func (x *ApplyGameCoinChangeRequest) GetRequestId() string { @@ -10701,7 +10449,7 @@ type ApplyGameCoinChangeResponse struct { func (x *ApplyGameCoinChangeResponse) Reset() { *x = ApplyGameCoinChangeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10713,7 +10461,7 @@ func (x *ApplyGameCoinChangeResponse) String() string { func (*ApplyGameCoinChangeResponse) ProtoMessage() {} func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10726,7 +10474,7 @@ func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeResponse.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} } func (x *ApplyGameCoinChangeResponse) GetWalletTransactionId() string { @@ -10769,7 +10517,7 @@ type RedPacketConfig struct { func (x *RedPacketConfig) Reset() { *x = RedPacketConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10781,7 +10529,7 @@ func (x *RedPacketConfig) String() string { func (*RedPacketConfig) ProtoMessage() {} func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10794,7 +10542,7 @@ func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketConfig.ProtoReflect.Descriptor instead. func (*RedPacketConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} } func (x *RedPacketConfig) GetAppCode() string { @@ -10893,7 +10641,7 @@ type RedPacketClaim struct { func (x *RedPacketClaim) Reset() { *x = RedPacketClaim{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10905,7 +10653,7 @@ func (x *RedPacketClaim) String() string { func (*RedPacketClaim) ProtoMessage() {} func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10918,7 +10666,7 @@ func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketClaim.ProtoReflect.Descriptor instead. func (*RedPacketClaim) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} } func (x *RedPacketClaim) GetAppCode() string { @@ -11028,7 +10776,7 @@ type RedPacket struct { func (x *RedPacket) Reset() { *x = RedPacket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11040,7 +10788,7 @@ func (x *RedPacket) String() string { func (*RedPacket) ProtoMessage() {} func (x *RedPacket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11053,7 +10801,7 @@ func (x *RedPacket) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacket.ProtoReflect.Descriptor instead. func (*RedPacket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} } func (x *RedPacket) GetAppCode() string { @@ -11220,7 +10968,7 @@ type GetRedPacketConfigRequest struct { func (x *GetRedPacketConfigRequest) Reset() { *x = GetRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11232,7 +10980,7 @@ func (x *GetRedPacketConfigRequest) String() string { func (*GetRedPacketConfigRequest) ProtoMessage() {} func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11245,7 +10993,7 @@ func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} } func (x *GetRedPacketConfigRequest) GetRequestId() string { @@ -11272,7 +11020,7 @@ type GetRedPacketConfigResponse struct { func (x *GetRedPacketConfigResponse) Reset() { *x = GetRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11284,7 +11032,7 @@ func (x *GetRedPacketConfigResponse) String() string { func (*GetRedPacketConfigResponse) ProtoMessage() {} func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11297,7 +11045,7 @@ func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} } func (x *GetRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -11332,7 +11080,7 @@ type UpdateRedPacketConfigRequest struct { func (x *UpdateRedPacketConfigRequest) Reset() { *x = UpdateRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11344,7 +11092,7 @@ func (x *UpdateRedPacketConfigRequest) String() string { func (*UpdateRedPacketConfigRequest) ProtoMessage() {} func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11357,7 +11105,7 @@ func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} } func (x *UpdateRedPacketConfigRequest) GetRequestId() string { @@ -11440,7 +11188,7 @@ type UpdateRedPacketConfigResponse struct { func (x *UpdateRedPacketConfigResponse) Reset() { *x = UpdateRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11452,7 +11200,7 @@ func (x *UpdateRedPacketConfigResponse) String() string { func (*UpdateRedPacketConfigResponse) ProtoMessage() {} func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11465,7 +11213,7 @@ func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} } func (x *UpdateRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -11499,7 +11247,7 @@ type CreateRedPacketRequest struct { func (x *CreateRedPacketRequest) Reset() { *x = CreateRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11511,7 +11259,7 @@ func (x *CreateRedPacketRequest) String() string { func (*CreateRedPacketRequest) ProtoMessage() {} func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11524,7 +11272,7 @@ func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketRequest.ProtoReflect.Descriptor instead. func (*CreateRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} } func (x *CreateRedPacketRequest) GetRequestId() string { @@ -11601,7 +11349,7 @@ type CreateRedPacketResponse struct { func (x *CreateRedPacketResponse) Reset() { *x = CreateRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11613,7 +11361,7 @@ func (x *CreateRedPacketResponse) String() string { func (*CreateRedPacketResponse) ProtoMessage() {} func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11626,7 +11374,7 @@ func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketResponse.ProtoReflect.Descriptor instead. func (*CreateRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} } func (x *CreateRedPacketResponse) GetPacket() *RedPacket { @@ -11663,7 +11411,7 @@ type ClaimRedPacketRequest struct { func (x *ClaimRedPacketRequest) Reset() { *x = ClaimRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11675,7 +11423,7 @@ func (x *ClaimRedPacketRequest) String() string { func (*ClaimRedPacketRequest) ProtoMessage() {} func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11688,7 +11436,7 @@ func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketRequest.ProtoReflect.Descriptor instead. func (*ClaimRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} } func (x *ClaimRedPacketRequest) GetRequestId() string { @@ -11738,7 +11486,7 @@ type ClaimRedPacketResponse struct { func (x *ClaimRedPacketResponse) Reset() { *x = ClaimRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11750,7 +11498,7 @@ func (x *ClaimRedPacketResponse) String() string { func (*ClaimRedPacketResponse) ProtoMessage() {} func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11763,7 +11511,7 @@ func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketResponse.ProtoReflect.Descriptor instead. func (*ClaimRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} } func (x *ClaimRedPacketResponse) GetClaim() *RedPacketClaim { @@ -11814,7 +11562,7 @@ type ListRedPacketsRequest struct { func (x *ListRedPacketsRequest) Reset() { *x = ListRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11826,7 +11574,7 @@ func (x *ListRedPacketsRequest) String() string { func (*ListRedPacketsRequest) ProtoMessage() {} func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11839,7 +11587,7 @@ func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ListRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} } func (x *ListRedPacketsRequest) GetRequestId() string { @@ -11937,7 +11685,7 @@ type ListRedPacketsResponse struct { func (x *ListRedPacketsResponse) Reset() { *x = ListRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11949,7 +11697,7 @@ func (x *ListRedPacketsResponse) String() string { func (*ListRedPacketsResponse) ProtoMessage() {} func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11962,7 +11710,7 @@ func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ListRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} } func (x *ListRedPacketsResponse) GetPackets() []*RedPacket { @@ -11999,7 +11747,7 @@ type GetRedPacketRequest struct { func (x *GetRedPacketRequest) Reset() { *x = GetRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12011,7 +11759,7 @@ func (x *GetRedPacketRequest) String() string { func (*GetRedPacketRequest) ProtoMessage() {} func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12024,7 +11772,7 @@ func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} } func (x *GetRedPacketRequest) GetRequestId() string { @@ -12072,7 +11820,7 @@ type GetRedPacketResponse struct { func (x *GetRedPacketResponse) Reset() { *x = GetRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12084,7 +11832,7 @@ func (x *GetRedPacketResponse) String() string { func (*GetRedPacketResponse) ProtoMessage() {} func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12097,7 +11845,7 @@ func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} } func (x *GetRedPacketResponse) GetPacket() *RedPacket { @@ -12125,7 +11873,7 @@ type ExpireRedPacketsRequest struct { func (x *ExpireRedPacketsRequest) Reset() { *x = ExpireRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12137,7 +11885,7 @@ func (x *ExpireRedPacketsRequest) String() string { func (*ExpireRedPacketsRequest) ProtoMessage() {} func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12150,7 +11898,7 @@ func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} } func (x *ExpireRedPacketsRequest) GetRequestId() string { @@ -12185,7 +11933,7 @@ type ExpireRedPacketsResponse struct { func (x *ExpireRedPacketsResponse) Reset() { *x = ExpireRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12197,7 +11945,7 @@ func (x *ExpireRedPacketsResponse) String() string { func (*ExpireRedPacketsResponse) ProtoMessage() {} func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12210,7 +11958,7 @@ func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} } func (x *ExpireRedPacketsResponse) GetExpiredCount() int32 { @@ -12246,7 +11994,7 @@ type RetryRedPacketRefundRequest struct { func (x *RetryRedPacketRefundRequest) Reset() { *x = RetryRedPacketRefundRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12258,7 +12006,7 @@ func (x *RetryRedPacketRefundRequest) String() string { func (*RetryRedPacketRefundRequest) ProtoMessage() {} func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12271,7 +12019,7 @@ func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundRequest.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} } func (x *RetryRedPacketRefundRequest) GetRequestId() string { @@ -12313,7 +12061,7 @@ type RetryRedPacketRefundResponse struct { func (x *RetryRedPacketRefundResponse) Reset() { *x = RetryRedPacketRefundResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12325,7 +12073,7 @@ func (x *RetryRedPacketRefundResponse) String() string { func (*RetryRedPacketRefundResponse) ProtoMessage() {} func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12338,7 +12086,7 @@ func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundResponse.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} } func (x *RetryRedPacketRefundResponse) GetPacket() *RedPacket { @@ -12377,7 +12125,7 @@ type CronBatchRequest struct { func (x *CronBatchRequest) Reset() { *x = CronBatchRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12389,7 +12137,7 @@ func (x *CronBatchRequest) String() string { func (*CronBatchRequest) ProtoMessage() {} func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12402,7 +12150,7 @@ func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchRequest.ProtoReflect.Descriptor instead. func (*CronBatchRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} } func (x *CronBatchRequest) GetRequestId() string { @@ -12461,7 +12209,7 @@ type CronBatchResponse struct { func (x *CronBatchResponse) Reset() { *x = CronBatchResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12473,7 +12221,7 @@ func (x *CronBatchResponse) String() string { func (*CronBatchResponse) ProtoMessage() {} func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12486,7 +12234,7 @@ func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchResponse.ProtoReflect.Descriptor instead. func (*CronBatchResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} } func (x *CronBatchResponse) GetClaimedCount() int32 { @@ -13237,11 +12985,10 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\tpage_size\x18\f \x01(\x05R\bpageSize\"f\n" + "\x19ListRechargeBillsResponse\x123\n" + "\x05bills\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.RechargeBillR\x05bills\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\xa4\x01\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"y\n" + "\x12WalletFeatureFlags\x12)\n" + "\x10recharge_enabled\x18\x01 \x01(\bR\x0frechargeEnabled\x128\n" + - "\x18diamond_exchange_enabled\x18\x02 \x01(\bR\x16diamondExchangeEnabled\x12)\n" + - "\x10withdraw_enabled\x18\x03 \x01(\bR\x0fwithdrawEnabled\"m\n" + + "\x18diamond_exchange_enabled\x18\x02 \x01(\bR\x16diamondExchangeEnabled\"m\n" + "\x18GetWalletOverviewRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + @@ -13461,31 +13208,7 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\tpage_size\x18\x06 \x01(\x05R\bpageSize\"~\n" + "\x1eListWalletTransactionsResponse\x12F\n" + "\ftransactions\x18\x01 \x03(\v2\".hyapp.wallet.v1.WalletTransactionR\ftransactions\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\xa7\x02\n" + - "\x11WithdrawalRequest\x12#\n" + - "\rwithdrawal_id\x18\x01 \x01(\tR\fwithdrawalId\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" + - "\n" + - "asset_type\x18\x03 \x01(\tR\tassetType\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12%\n" + - "\x0epayout_account\x18\x06 \x01(\tR\rpayoutAccount\x12\x16\n" + - "\x06reason\x18\a \x01(\tR\x06reason\x12\"\n" + - "\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\"\xc2\x01\n" + - "\x16ApplyWithdrawalRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12%\n" + - "\x0epayout_account\x18\x05 \x01(\tR\rpayoutAccount\x12\x16\n" + - "\x06reason\x18\x06 \x01(\tR\x06reason\"\x96\x01\n" + - "\x17ApplyWithdrawalResponse\x12B\n" + - "\n" + - "withdrawal\x18\x01 \x01(\v2\".hyapp.wallet.v1.WithdrawalRequestR\n" + - "withdrawal\x127\n" + - "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\"\xb1\x02\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xb1\x02\n" + "\rVipRewardItem\x12\x1f\n" + "\vresource_id\x18\x01 \x01(\x03R\n" + "resourceId\x12#\n" + @@ -13829,7 +13552,7 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x11WalletCronService\x12n\n" + "%ProcessHostSalaryDailySettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12r\n" + ")ProcessHostSalaryHalfMonthSettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12g\n" + - "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\xe52\n" + + "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\xff1\n" + "\rWalletService\x12R\n" + "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12X\n" + "\vGetBalances\x12#.hyapp.wallet.v1.GetBalancesRequest\x1a$.hyapp.wallet.v1.GetBalancesResponse\x12g\n" + @@ -13873,7 +13596,6 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x15DeleteRechargeProduct\x12-.hyapp.wallet.v1.DeleteRechargeProductRequest\x1a..hyapp.wallet.v1.DeleteRechargeProductResponse\x12\x7f\n" + "\x18GetDiamondExchangeConfig\x120.hyapp.wallet.v1.GetDiamondExchangeConfigRequest\x1a1.hyapp.wallet.v1.GetDiamondExchangeConfigResponse\x12y\n" + "\x16ListWalletTransactions\x12..hyapp.wallet.v1.ListWalletTransactionsRequest\x1a/.hyapp.wallet.v1.ListWalletTransactionsResponse\x12d\n" + - "\x0fApplyWithdrawal\x12'.hyapp.wallet.v1.ApplyWithdrawalRequest\x1a(.hyapp.wallet.v1.ApplyWithdrawalResponse\x12d\n" + "\x0fListVipPackages\x12'.hyapp.wallet.v1.ListVipPackagesRequest\x1a(.hyapp.wallet.v1.ListVipPackagesResponse\x12O\n" + "\bGetMyVip\x12 .hyapp.wallet.v1.GetMyVipRequest\x1a!.hyapp.wallet.v1.GetMyVipResponse\x12X\n" + "\vPurchaseVip\x12#.hyapp.wallet.v1.PurchaseVipRequest\x1a$.hyapp.wallet.v1.PurchaseVipResponse\x12O\n" + @@ -13904,7 +13626,7 @@ func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 141) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 138) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest (*DebitGiftResponse)(nil), // 1: hyapp.wallet.v1.DebitGiftResponse @@ -14001,52 +13723,49 @@ var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*WalletTransaction)(nil), // 92: hyapp.wallet.v1.WalletTransaction (*ListWalletTransactionsRequest)(nil), // 93: hyapp.wallet.v1.ListWalletTransactionsRequest (*ListWalletTransactionsResponse)(nil), // 94: hyapp.wallet.v1.ListWalletTransactionsResponse - (*WithdrawalRequest)(nil), // 95: hyapp.wallet.v1.WithdrawalRequest - (*ApplyWithdrawalRequest)(nil), // 96: hyapp.wallet.v1.ApplyWithdrawalRequest - (*ApplyWithdrawalResponse)(nil), // 97: hyapp.wallet.v1.ApplyWithdrawalResponse - (*VipRewardItem)(nil), // 98: hyapp.wallet.v1.VipRewardItem - (*VipLevel)(nil), // 99: hyapp.wallet.v1.VipLevel - (*UserVip)(nil), // 100: hyapp.wallet.v1.UserVip - (*ListVipPackagesRequest)(nil), // 101: hyapp.wallet.v1.ListVipPackagesRequest - (*ListVipPackagesResponse)(nil), // 102: hyapp.wallet.v1.ListVipPackagesResponse - (*GetMyVipRequest)(nil), // 103: hyapp.wallet.v1.GetMyVipRequest - (*GetMyVipResponse)(nil), // 104: hyapp.wallet.v1.GetMyVipResponse - (*PurchaseVipRequest)(nil), // 105: hyapp.wallet.v1.PurchaseVipRequest - (*PurchaseVipResponse)(nil), // 106: hyapp.wallet.v1.PurchaseVipResponse - (*GrantVipRequest)(nil), // 107: hyapp.wallet.v1.GrantVipRequest - (*GrantVipResponse)(nil), // 108: hyapp.wallet.v1.GrantVipResponse - (*AdminVipLevelInput)(nil), // 109: hyapp.wallet.v1.AdminVipLevelInput - (*ListAdminVipLevelsRequest)(nil), // 110: hyapp.wallet.v1.ListAdminVipLevelsRequest - (*ListAdminVipLevelsResponse)(nil), // 111: hyapp.wallet.v1.ListAdminVipLevelsResponse - (*UpdateAdminVipLevelsRequest)(nil), // 112: hyapp.wallet.v1.UpdateAdminVipLevelsRequest - (*UpdateAdminVipLevelsResponse)(nil), // 113: hyapp.wallet.v1.UpdateAdminVipLevelsResponse - (*CreditTaskRewardRequest)(nil), // 114: hyapp.wallet.v1.CreditTaskRewardRequest - (*CreditTaskRewardResponse)(nil), // 115: hyapp.wallet.v1.CreditTaskRewardResponse - (*CreditLuckyGiftRewardRequest)(nil), // 116: hyapp.wallet.v1.CreditLuckyGiftRewardRequest - (*CreditLuckyGiftRewardResponse)(nil), // 117: hyapp.wallet.v1.CreditLuckyGiftRewardResponse - (*ApplyGameCoinChangeRequest)(nil), // 118: hyapp.wallet.v1.ApplyGameCoinChangeRequest - (*ApplyGameCoinChangeResponse)(nil), // 119: hyapp.wallet.v1.ApplyGameCoinChangeResponse - (*RedPacketConfig)(nil), // 120: hyapp.wallet.v1.RedPacketConfig - (*RedPacketClaim)(nil), // 121: hyapp.wallet.v1.RedPacketClaim - (*RedPacket)(nil), // 122: hyapp.wallet.v1.RedPacket - (*GetRedPacketConfigRequest)(nil), // 123: hyapp.wallet.v1.GetRedPacketConfigRequest - (*GetRedPacketConfigResponse)(nil), // 124: hyapp.wallet.v1.GetRedPacketConfigResponse - (*UpdateRedPacketConfigRequest)(nil), // 125: hyapp.wallet.v1.UpdateRedPacketConfigRequest - (*UpdateRedPacketConfigResponse)(nil), // 126: hyapp.wallet.v1.UpdateRedPacketConfigResponse - (*CreateRedPacketRequest)(nil), // 127: hyapp.wallet.v1.CreateRedPacketRequest - (*CreateRedPacketResponse)(nil), // 128: hyapp.wallet.v1.CreateRedPacketResponse - (*ClaimRedPacketRequest)(nil), // 129: hyapp.wallet.v1.ClaimRedPacketRequest - (*ClaimRedPacketResponse)(nil), // 130: hyapp.wallet.v1.ClaimRedPacketResponse - (*ListRedPacketsRequest)(nil), // 131: hyapp.wallet.v1.ListRedPacketsRequest - (*ListRedPacketsResponse)(nil), // 132: hyapp.wallet.v1.ListRedPacketsResponse - (*GetRedPacketRequest)(nil), // 133: hyapp.wallet.v1.GetRedPacketRequest - (*GetRedPacketResponse)(nil), // 134: hyapp.wallet.v1.GetRedPacketResponse - (*ExpireRedPacketsRequest)(nil), // 135: hyapp.wallet.v1.ExpireRedPacketsRequest - (*ExpireRedPacketsResponse)(nil), // 136: hyapp.wallet.v1.ExpireRedPacketsResponse - (*RetryRedPacketRefundRequest)(nil), // 137: hyapp.wallet.v1.RetryRedPacketRefundRequest - (*RetryRedPacketRefundResponse)(nil), // 138: hyapp.wallet.v1.RetryRedPacketRefundResponse - (*CronBatchRequest)(nil), // 139: hyapp.wallet.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 140: hyapp.wallet.v1.CronBatchResponse + (*VipRewardItem)(nil), // 95: hyapp.wallet.v1.VipRewardItem + (*VipLevel)(nil), // 96: hyapp.wallet.v1.VipLevel + (*UserVip)(nil), // 97: hyapp.wallet.v1.UserVip + (*ListVipPackagesRequest)(nil), // 98: hyapp.wallet.v1.ListVipPackagesRequest + (*ListVipPackagesResponse)(nil), // 99: hyapp.wallet.v1.ListVipPackagesResponse + (*GetMyVipRequest)(nil), // 100: hyapp.wallet.v1.GetMyVipRequest + (*GetMyVipResponse)(nil), // 101: hyapp.wallet.v1.GetMyVipResponse + (*PurchaseVipRequest)(nil), // 102: hyapp.wallet.v1.PurchaseVipRequest + (*PurchaseVipResponse)(nil), // 103: hyapp.wallet.v1.PurchaseVipResponse + (*GrantVipRequest)(nil), // 104: hyapp.wallet.v1.GrantVipRequest + (*GrantVipResponse)(nil), // 105: hyapp.wallet.v1.GrantVipResponse + (*AdminVipLevelInput)(nil), // 106: hyapp.wallet.v1.AdminVipLevelInput + (*ListAdminVipLevelsRequest)(nil), // 107: hyapp.wallet.v1.ListAdminVipLevelsRequest + (*ListAdminVipLevelsResponse)(nil), // 108: hyapp.wallet.v1.ListAdminVipLevelsResponse + (*UpdateAdminVipLevelsRequest)(nil), // 109: hyapp.wallet.v1.UpdateAdminVipLevelsRequest + (*UpdateAdminVipLevelsResponse)(nil), // 110: hyapp.wallet.v1.UpdateAdminVipLevelsResponse + (*CreditTaskRewardRequest)(nil), // 111: hyapp.wallet.v1.CreditTaskRewardRequest + (*CreditTaskRewardResponse)(nil), // 112: hyapp.wallet.v1.CreditTaskRewardResponse + (*CreditLuckyGiftRewardRequest)(nil), // 113: hyapp.wallet.v1.CreditLuckyGiftRewardRequest + (*CreditLuckyGiftRewardResponse)(nil), // 114: hyapp.wallet.v1.CreditLuckyGiftRewardResponse + (*ApplyGameCoinChangeRequest)(nil), // 115: hyapp.wallet.v1.ApplyGameCoinChangeRequest + (*ApplyGameCoinChangeResponse)(nil), // 116: hyapp.wallet.v1.ApplyGameCoinChangeResponse + (*RedPacketConfig)(nil), // 117: hyapp.wallet.v1.RedPacketConfig + (*RedPacketClaim)(nil), // 118: hyapp.wallet.v1.RedPacketClaim + (*RedPacket)(nil), // 119: hyapp.wallet.v1.RedPacket + (*GetRedPacketConfigRequest)(nil), // 120: hyapp.wallet.v1.GetRedPacketConfigRequest + (*GetRedPacketConfigResponse)(nil), // 121: hyapp.wallet.v1.GetRedPacketConfigResponse + (*UpdateRedPacketConfigRequest)(nil), // 122: hyapp.wallet.v1.UpdateRedPacketConfigRequest + (*UpdateRedPacketConfigResponse)(nil), // 123: hyapp.wallet.v1.UpdateRedPacketConfigResponse + (*CreateRedPacketRequest)(nil), // 124: hyapp.wallet.v1.CreateRedPacketRequest + (*CreateRedPacketResponse)(nil), // 125: hyapp.wallet.v1.CreateRedPacketResponse + (*ClaimRedPacketRequest)(nil), // 126: hyapp.wallet.v1.ClaimRedPacketRequest + (*ClaimRedPacketResponse)(nil), // 127: hyapp.wallet.v1.ClaimRedPacketResponse + (*ListRedPacketsRequest)(nil), // 128: hyapp.wallet.v1.ListRedPacketsRequest + (*ListRedPacketsResponse)(nil), // 129: hyapp.wallet.v1.ListRedPacketsResponse + (*GetRedPacketRequest)(nil), // 130: hyapp.wallet.v1.GetRedPacketRequest + (*GetRedPacketResponse)(nil), // 131: hyapp.wallet.v1.GetRedPacketResponse + (*ExpireRedPacketsRequest)(nil), // 132: hyapp.wallet.v1.ExpireRedPacketsRequest + (*ExpireRedPacketsResponse)(nil), // 133: hyapp.wallet.v1.ExpireRedPacketsResponse + (*RetryRedPacketRefundRequest)(nil), // 134: hyapp.wallet.v1.RetryRedPacketRefundRequest + (*RetryRedPacketRefundResponse)(nil), // 135: hyapp.wallet.v1.RetryRedPacketRefundResponse + (*CronBatchRequest)(nil), // 136: hyapp.wallet.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 137: hyapp.wallet.v1.CronBatchResponse } var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 2, // 0: hyapp.wallet.v1.GetBalancesResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance @@ -14092,161 +13811,157 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 77, // 40: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct 89, // 41: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule 92, // 42: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction - 95, // 43: hyapp.wallet.v1.ApplyWithdrawalResponse.withdrawal:type_name -> hyapp.wallet.v1.WithdrawalRequest - 2, // 44: hyapp.wallet.v1.ApplyWithdrawalResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 98, // 45: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 100, // 46: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip - 99, // 47: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel - 100, // 48: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 100, // 49: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 98, // 50: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 100, // 51: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 98, // 52: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 99, // 53: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 109, // 54: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput - 99, // 55: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 2, // 56: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 2, // 57: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 121, // 58: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 120, // 59: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 120, // 60: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 122, // 61: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 121, // 62: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 122, // 63: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 122, // 64: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 122, // 65: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 122, // 66: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 139, // 67: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 139, // 68: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 139, // 69: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 0, // 70: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 3, // 71: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 5, // 72: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 7, // 73: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 9, // 74: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 21, // 75: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 23, // 76: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 25, // 77: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 26, // 78: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 27, // 79: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 29, // 80: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 31, // 81: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 33, // 82: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 34, // 83: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 35, // 84: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 37, // 85: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 39, // 86: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 43, // 87: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 44, // 88: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 45, // 89: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 41, // 90: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 47, // 91: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 48, // 92: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 50, // 93: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 52, // 94: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 54, // 95: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 57, // 96: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 59, // 97: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 61, // 98: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 63, // 99: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 66, // 100: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 69, // 101: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 72, // 102: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 75, // 103: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 78, // 104: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 80, // 105: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 82, // 106: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 84, // 107: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 85, // 108: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 86, // 109: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 90, // 110: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 93, // 111: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 96, // 112: hyapp.wallet.v1.WalletService.ApplyWithdrawal:input_type -> hyapp.wallet.v1.ApplyWithdrawalRequest - 101, // 113: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 103, // 114: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 105, // 115: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 107, // 116: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 110, // 117: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 112, // 118: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 114, // 119: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 116, // 120: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 118, // 121: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 123, // 122: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 125, // 123: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 127, // 124: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 129, // 125: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 131, // 126: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 133, // 127: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 135, // 128: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 137, // 129: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 140, // 130: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 140, // 131: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 140, // 132: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 1, // 133: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 4, // 134: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 6, // 135: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 8, // 136: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 10, // 137: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 22, // 138: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 24, // 139: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 28, // 140: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 28, // 141: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 28, // 142: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 30, // 143: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 32, // 144: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 36, // 145: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 36, // 146: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 36, // 147: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 38, // 148: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 40, // 149: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 46, // 150: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 46, // 151: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 46, // 152: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 42, // 153: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 49, // 154: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 49, // 155: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 51, // 156: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 53, // 157: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 55, // 158: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 58, // 159: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 60, // 160: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 62, // 161: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 64, // 162: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 67, // 163: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 70, // 164: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 73, // 165: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 76, // 166: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 79, // 167: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 81, // 168: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 83, // 169: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 87, // 170: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 87, // 171: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 88, // 172: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 91, // 173: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 94, // 174: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 97, // 175: hyapp.wallet.v1.WalletService.ApplyWithdrawal:output_type -> hyapp.wallet.v1.ApplyWithdrawalResponse - 102, // 176: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 104, // 177: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 106, // 178: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 108, // 179: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 111, // 180: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 113, // 181: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 115, // 182: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 117, // 183: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 119, // 184: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 124, // 185: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 126, // 186: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 128, // 187: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 130, // 188: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 132, // 189: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 134, // 190: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 136, // 191: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 138, // 192: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 130, // [130:193] is the sub-list for method output_type - 67, // [67:130] is the sub-list for method input_type - 67, // [67:67] is the sub-list for extension type_name - 67, // [67:67] is the sub-list for extension extendee - 0, // [0:67] is the sub-list for field type_name + 95, // 43: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 97, // 44: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip + 96, // 45: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel + 97, // 46: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 97, // 47: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 95, // 48: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 97, // 49: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 95, // 50: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 96, // 51: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 106, // 52: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput + 96, // 53: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 2, // 54: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 2, // 55: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 118, // 56: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 117, // 57: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 117, // 58: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 119, // 59: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 118, // 60: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 119, // 61: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 119, // 62: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 119, // 63: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 119, // 64: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 136, // 65: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 136, // 66: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 136, // 67: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 0, // 68: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 3, // 69: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 5, // 70: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 7, // 71: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 9, // 72: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 21, // 73: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 23, // 74: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 25, // 75: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 26, // 76: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 27, // 77: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 29, // 78: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 31, // 79: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 33, // 80: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 34, // 81: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 35, // 82: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 37, // 83: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 39, // 84: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 43, // 85: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 44, // 86: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 45, // 87: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 41, // 88: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 47, // 89: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 48, // 90: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 50, // 91: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 52, // 92: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 54, // 93: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 57, // 94: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 59, // 95: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 61, // 96: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 63, // 97: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 66, // 98: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 69, // 99: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 72, // 100: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 75, // 101: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 78, // 102: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 80, // 103: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 82, // 104: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 84, // 105: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 85, // 106: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 86, // 107: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 90, // 108: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 93, // 109: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 98, // 110: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 100, // 111: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 102, // 112: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 104, // 113: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 107, // 114: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 109, // 115: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 111, // 116: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 113, // 117: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 115, // 118: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 120, // 119: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 122, // 120: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 124, // 121: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 126, // 122: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 128, // 123: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 130, // 124: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 132, // 125: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 134, // 126: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 137, // 127: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 137, // 128: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 137, // 129: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 1, // 130: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 4, // 131: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 6, // 132: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 8, // 133: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 10, // 134: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 22, // 135: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 24, // 136: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 28, // 137: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 28, // 138: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 28, // 139: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 30, // 140: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 32, // 141: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 36, // 142: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 36, // 143: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 36, // 144: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 38, // 145: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 40, // 146: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 46, // 147: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 46, // 148: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 46, // 149: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 42, // 150: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 49, // 151: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 49, // 152: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 51, // 153: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 53, // 154: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 55, // 155: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 58, // 156: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 60, // 157: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 62, // 158: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 64, // 159: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 67, // 160: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 70, // 161: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 73, // 162: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 76, // 163: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 79, // 164: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 81, // 165: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 83, // 166: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 87, // 167: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 87, // 168: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 88, // 169: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 91, // 170: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 94, // 171: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 99, // 172: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 101, // 173: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 103, // 174: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 105, // 175: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 108, // 176: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 110, // 177: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 112, // 178: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 114, // 179: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 116, // 180: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 121, // 181: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 123, // 182: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 125, // 183: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 127, // 184: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 129, // 185: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 131, // 186: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 133, // 187: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 135, // 188: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 127, // [127:189] is the sub-list for method output_type + 65, // [65:127] is the sub-list for method input_type + 65, // [65:65] is the sub-list for extension type_name + 65, // [65:65] is the sub-list for extension extendee + 0, // [0:65] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -14262,7 +13977,7 @@ func file_proto_wallet_v1_wallet_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), NumEnums: 0, - NumMessages: 141, + NumMessages: 138, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 662bd61d..1d1b83a2 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -734,7 +734,6 @@ message ListRechargeBillsResponse { message WalletFeatureFlags { bool recharge_enabled = 1; bool diamond_exchange_enabled = 2; - bool withdraw_enabled = 3; } message GetWalletOverviewRequest { @@ -976,32 +975,6 @@ message ListWalletTransactionsResponse { int64 total = 2; } -message WithdrawalRequest { - string withdrawal_id = 1; - int64 user_id = 2; - string asset_type = 3; - int64 amount = 4; - string status = 5; - string payout_account = 6; - string reason = 7; - int64 created_at_ms = 8; - int64 updated_at_ms = 9; -} - -message ApplyWithdrawalRequest { - string command_id = 1; - string app_code = 2; - int64 user_id = 3; - int64 amount = 4; - string payout_account = 5; - string reason = 6; -} - -message ApplyWithdrawalResponse { - WithdrawalRequest withdrawal = 1; - AssetBalance balance = 2; -} - message VipRewardItem { int64 resource_id = 1; string resource_code = 2; @@ -1437,7 +1410,6 @@ service WalletService { rpc DeleteRechargeProduct(DeleteRechargeProductRequest) returns (DeleteRechargeProductResponse); rpc GetDiamondExchangeConfig(GetDiamondExchangeConfigRequest) returns (GetDiamondExchangeConfigResponse); rpc ListWalletTransactions(ListWalletTransactionsRequest) returns (ListWalletTransactionsResponse); - rpc ApplyWithdrawal(ApplyWithdrawalRequest) returns (ApplyWithdrawalResponse); rpc ListVipPackages(ListVipPackagesRequest) returns (ListVipPackagesResponse); rpc GetMyVip(GetMyVipRequest) returns (GetMyVipResponse); rpc PurchaseVip(PurchaseVipRequest) returns (PurchaseVipResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 97346b9c..ffcca4dc 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -243,7 +243,6 @@ const ( WalletService_DeleteRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/DeleteRechargeProduct" WalletService_GetDiamondExchangeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetDiamondExchangeConfig" WalletService_ListWalletTransactions_FullMethodName = "/hyapp.wallet.v1.WalletService/ListWalletTransactions" - WalletService_ApplyWithdrawal_FullMethodName = "/hyapp.wallet.v1.WalletService/ApplyWithdrawal" WalletService_ListVipPackages_FullMethodName = "/hyapp.wallet.v1.WalletService/ListVipPackages" WalletService_GetMyVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GetMyVip" WalletService_PurchaseVip_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseVip" @@ -311,7 +310,6 @@ type WalletServiceClient interface { DeleteRechargeProduct(ctx context.Context, in *DeleteRechargeProductRequest, opts ...grpc.CallOption) (*DeleteRechargeProductResponse, error) GetDiamondExchangeConfig(ctx context.Context, in *GetDiamondExchangeConfigRequest, opts ...grpc.CallOption) (*GetDiamondExchangeConfigResponse, error) ListWalletTransactions(ctx context.Context, in *ListWalletTransactionsRequest, opts ...grpc.CallOption) (*ListWalletTransactionsResponse, error) - ApplyWithdrawal(ctx context.Context, in *ApplyWithdrawalRequest, opts ...grpc.CallOption) (*ApplyWithdrawalResponse, error) ListVipPackages(ctx context.Context, in *ListVipPackagesRequest, opts ...grpc.CallOption) (*ListVipPackagesResponse, error) GetMyVip(ctx context.Context, in *GetMyVipRequest, opts ...grpc.CallOption) (*GetMyVipResponse, error) PurchaseVip(ctx context.Context, in *PurchaseVipRequest, opts ...grpc.CallOption) (*PurchaseVipResponse, error) @@ -759,16 +757,6 @@ func (c *walletServiceClient) ListWalletTransactions(ctx context.Context, in *Li return out, nil } -func (c *walletServiceClient) ApplyWithdrawal(ctx context.Context, in *ApplyWithdrawalRequest, opts ...grpc.CallOption) (*ApplyWithdrawalResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(ApplyWithdrawalResponse) - err := c.cc.Invoke(ctx, WalletService_ApplyWithdrawal_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *walletServiceClient) ListVipPackages(ctx context.Context, in *ListVipPackagesRequest, opts ...grpc.CallOption) (*ListVipPackagesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListVipPackagesResponse) @@ -987,7 +975,6 @@ type WalletServiceServer interface { DeleteRechargeProduct(context.Context, *DeleteRechargeProductRequest) (*DeleteRechargeProductResponse, error) GetDiamondExchangeConfig(context.Context, *GetDiamondExchangeConfigRequest) (*GetDiamondExchangeConfigResponse, error) ListWalletTransactions(context.Context, *ListWalletTransactionsRequest) (*ListWalletTransactionsResponse, error) - ApplyWithdrawal(context.Context, *ApplyWithdrawalRequest) (*ApplyWithdrawalResponse, error) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) GetMyVip(context.Context, *GetMyVipRequest) (*GetMyVipResponse, error) PurchaseVip(context.Context, *PurchaseVipRequest) (*PurchaseVipResponse, error) @@ -1141,9 +1128,6 @@ func (UnimplementedWalletServiceServer) GetDiamondExchangeConfig(context.Context func (UnimplementedWalletServiceServer) ListWalletTransactions(context.Context, *ListWalletTransactionsRequest) (*ListWalletTransactionsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListWalletTransactions not implemented") } -func (UnimplementedWalletServiceServer) ApplyWithdrawal(context.Context, *ApplyWithdrawalRequest) (*ApplyWithdrawalResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ApplyWithdrawal not implemented") -} func (UnimplementedWalletServiceServer) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListVipPackages not implemented") } @@ -1972,24 +1956,6 @@ func _WalletService_ListWalletTransactions_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } -func _WalletService_ApplyWithdrawal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ApplyWithdrawalRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WalletServiceServer).ApplyWithdrawal(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: WalletService_ApplyWithdrawal_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WalletServiceServer).ApplyWithdrawal(ctx, req.(*ApplyWithdrawalRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _WalletService_ListVipPackages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListVipPackagesRequest) if err := dec(in); err != nil { @@ -2471,10 +2437,6 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListWalletTransactions", Handler: _WalletService_ListWalletTransactions_Handler, }, - { - MethodName: "ApplyWithdrawal", - Handler: _WalletService_ApplyWithdrawal_Handler, - }, { MethodName: "ListVipPackages", Handler: _WalletService_ListVipPackages_Handler, diff --git a/docs/flutter对接/Flutter App 通知与钱包余额对接.md b/docs/flutter对接/Flutter App 通知与钱包余额对接.md index 4b1fe947..d0eeb65f 100644 --- a/docs/flutter对接/Flutter App 通知与钱包余额对接.md +++ b/docs/flutter对接/Flutter App 通知与钱包余额对接.md @@ -138,7 +138,7 @@ GET /api/v1/wallet/me/balances 示例: ```text -GET /api/v1/wallet/me/balances?asset_type=COIN&asset_type=DIAMOND&asset_type=USD_BALANCE +GET /api/v1/wallet/me/balances?asset_type=COIN&asset_type=DIAMOND&asset_type=HOST_SALARY_USD&asset_type=AGENCY_SALARY_USD&asset_type=BD_SALARY_USD&asset_type=ADMIN_SALARY_USD ``` ### 返回值 `data` @@ -158,7 +158,7 @@ GET /api/v1/wallet/me/balances?asset_type=COIN&asset_type=DIAMOND&asset_type=USD | 字段 | 类型 | 说明 | | ------------------ | ------ | ------------------------------------------------- | -| `asset_type` | string | `COIN` / `DIAMOND` / `USD_BALANCE` / `GIFT_POINT` | +| `asset_type` | string | `COIN` / `DIAMOND` / `HOST_SALARY_USD` / `AGENCY_SALARY_USD` / `BD_SALARY_USD` / `ADMIN_SALARY_USD` / `GIFT_POINT` | | `available_amount` | int64 | 可用余额 | | `frozen_amount` | int64 | 冻结余额 | | `version` | int64 | 该资产余额版本,用于和 IM 通知去重/防乱序 | @@ -201,7 +201,7 @@ GET /api/v1/wallet/me/overview "version": 4 }, { - "asset_type": "USD_BALANCE", + "asset_type": "HOST_SALARY_USD", "available_amount": 1500, "frozen_amount": 0, "version": 2 @@ -209,8 +209,7 @@ GET /api/v1/wallet/me/overview ], "feature_flags": { "recharge_enabled": true, - "diamond_exchange_enabled": true, - "withdraw_enabled": true + "diamond_exchange_enabled": true } } ``` @@ -220,7 +219,6 @@ GET /api/v1/wallet/me/overview | `balances` | array | 钱包首页需要展示的资产余额 | | `feature_flags.recharge_enabled` | bool | 是否允许充值 | | `feature_flags.diamond_exchange_enabled` | bool | 是否允许钻石兑换 | -| `feature_flags.withdraw_enabled` | bool | 是否允许提现 | ### 可能错误 diff --git a/docs/主播公会BD后台架构.md b/docs/主播公会BD后台架构.md index 9b2d9ea9..b3fa03d8 100644 --- a/docs/主播公会BD后台架构.md +++ b/docs/主播公会BD后台架构.md @@ -2,7 +2,7 @@ 本文只定义后台/Admin 侧实现:政策配置、工资周期、工资单、审核、钱包入账、调整单、后台审计和运营干预。App 侧的主播申请、Agency 成员、BD 邀请和用户可见查询见 [Host Agency BD App Architecture](./主播公会BD架构.md)。 -这里的工资统一指发放到主播侧 `USD_BALANCE` 的业务奖励。提现审核和人工打款仍由 `wallet-service` 拥有,Admin 只负责把审核通过的工资单入账到工资余额,不直接处理线下打款。 +这里的工资统一指发放到主播侧 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 的业务奖励。提现审核和人工打款仍由 `wallet-service` 拥有,Admin 只负责把审核通过的工资单入账到工资余额,不直接处理线下打款。 本文不新增独立 `host-service` 微服务。host、Agency、BD、政策和工资后台能力属于 user-services,代码落在当前仓库的 `services/user-service` host domain。 @@ -11,7 +11,7 @@ - 后台可以配置 host、agency、bd 三类工资政策,并按区域生效。 - 后台可以选择日结、周结、半月结、月结,不把结算周期写死在代码里。 - 后台可以生成工资周期,查看每个 host/Agency/BD/BD Leader 的明细来源。 -- 后台审批后,`user-service` host domain 以幂等方式调用 `wallet-service` 给 `USD_BALANCE` 入账。 +- 后台审批后,`user-service` host domain 以幂等方式调用 `wallet-service` 给 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 入账。 - 后台可以对迟到事件、人工修正、争议处理创建调整单,不能直接修改已入账工资项。 - 后台可以创建或停用 BD Leader、BD、Agency,也可以关闭 Agency;后台可以查看和新增币商 `coin_seller`;所有动作必须有审计记录。 @@ -49,7 +49,7 @@ graph LR | `hyapp-admin-server` | Admin HTTP 入口、后台鉴权、request envelope、后台操作审计;使用独立 `hyapp_admin` 库 | | `user-service` | 用户、区域、账号状态查询;host/Agency/BD/coin_seller 政策、周期、工资单、关系管理、统计聚合、幂等结果、领域 outbox;App/客户端不能提交区域,后台关系命令的 `region_id` 只能来自 `hyapp-admin-server` 鉴权审计入口 | | `room-service` | 只产出上麦和礼物事件,不接收后台工资命令 | -| `wallet-service` | `COIN`、`COIN_SELLER_COIN`、`USD_BALANCE` 入账、提现冻结、提现审核状态和钱包流水 | +| `wallet-service` | `COIN`、`COIN_SELLER_COIN`、`HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 入账、提现冻结、提现审核状态和钱包流水 | ## Admin Permission Model @@ -188,7 +188,7 @@ flowchart LR E --> F F --> G["approve"] G --> H["wallet CreditSalaryBalance"] - H --> I["USD_BALANCE"] + H --> I["identity salary wallet"] ``` ```sql @@ -353,7 +353,7 @@ Leader 直接拥有 Agency 下线时,推荐快照同时设置 `bd_user_id = le 1. Admin 审批 cycle。 2. `user-service` host domain 查询所有 `approved` salary items。 3. 对每个 item 调用 `wallet-service CreditSalaryBalance`,幂等键为 `salary:{salary_item_id}`。 -4. `wallet-service` credit `USD_BALANCE` 并返回 `wallet_transaction_id`。 +4. `wallet-service` credit `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 并返回 `wallet_transaction_id`。 5. `user-service` host domain 保存 `wallet_transaction_id`,把 item 标记为 `posted`。 6. 如果中途失败,只重试未 posted item,幂等键保持不变。 @@ -488,7 +488,7 @@ Outbox consumers can update App message inbox, BI, risk systems, and export jobs | Host changes Agency during cycle | Salary uses `host_daily_stats` relation snapshot and can split across agencies | | Late room event after posted cycle | Create adjustment item; do not mutate posted salary item | | Wallet posting partially fails | Retry unposted items with same idempotency key | -| Admin accidentally posts twice | Wallet idempotency must prevent duplicate `USD_BALANCE` credit | +| Admin accidentally posts twice | Wallet idempotency must prevent duplicate `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` credit | | Agency closed mid-cycle | Work before close remains attributable; future App joins/search stop immediately | | User region changed | Existing cycle uses event snapshots; new policy/cycle matching follows stats region | | Negative adjustment exceeds balance | Move to manual handling; do not force wallet negative unless wallet explicitly supports debt | @@ -507,7 +507,7 @@ Outbox consumers can update App message inbox, BI, risk systems, and export jobs | Agency salary generated | Base uses host salary items under that Agency only | | BD Leader owns direct Agency | Source host salary counted once for the leader | | BD under Leader owns Agency | Host salary contributes to BD and leader according to snapshot | -| Cycle posted twice | Wallet idempotency prevents duplicate `USD_BALANCE` credit | +| Cycle posted twice | Wallet idempotency prevents duplicate `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` credit | | Posting fails after partial success | Retry posts only unposted items | | Posted item needs correction | Adjustment item created; original item remains immutable | | Admin closes Agency | Agency hidden from App search; existing facts remain auditable | @@ -515,7 +515,7 @@ Outbox consumers can update App message inbox, BI, risk systems, and export jobs ## Critical Rules - Admin owns policies and salary cycles; App owns user-initiated relationship flows. -- Wallet is the only owner of `USD_BALANCE` and withdrawal state. +- Wallet is the only owner of `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` and withdrawal state. - Posted salary items are immutable. - BD/BD Leader base is downstream host salary only. - Leader direct Agency salary source must be de-duplicated. diff --git a/docs/主播公会BD实施顺序.md b/docs/主播公会BD实施顺序.md index 80ce03d8..0881713b 100644 --- a/docs/主播公会BD实施顺序.md +++ b/docs/主播公会BD实施顺序.md @@ -142,7 +142,7 @@ - Agency salary:基于下属 host salary item 或明确配置的 agency 指标。 - BD/BD Leader salary:基于 downstream host salary sum,且按 source host salary item 去重。 - 后台审核工资周期。 -- 调用 `wallet-service` 给 `USD_BALANCE` 入账,幂等键为 `salary:{salary_item_id}`。 +- 调用 `wallet-service` 给 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 入账,幂等键为 `salary:{salary_item_id}`。 - 支持调整单:迟到事件、人工修正、争议处理都走补差或冲正。 - Salary posted 和 adjustment posted 事件接入 App message inbox,通知接收人查看收益明细;通知失败不影响钱包入账事实。 @@ -182,7 +182,7 @@ | M3 | Phase 3 | 用户申请、审核、踢出、重新申请、邀请链路完整跑通 | | M3.5 | Phase 3.5 | 申请、邀请、后台创建关系结果能进入 App 系统消息 | | M4 | Phase 4 | 有效上麦和礼物统计按关系快照落库 | -| M5 | Phase 5 | 后台生成工资单,审批后入账 `USD_BALANCE` | +| M5 | Phase 5 | 后台生成工资单,审批后入账 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` | | M6 | Phase 6 | 失败补偿、导出、重建和监控可用 | ## Stop Conditions @@ -191,7 +191,7 @@ - Phase 2 没有完成前,不做 App Agency 搜索上线,因为没有可信组织种子数据。 - Phase 3 没有完成前,不做工资发放,因为 host/Agency/BD 归属还不稳定。 - Phase 4 没有完成前,不做真实工资入账,因为缺少可审计统计输入。 -- Phase 5 没有完成审批和幂等 posting 前,不允许写 `USD_BALANCE`。 +- Phase 5 没有完成审批和幂等 posting 前,不允许写 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`。 ## Verification Commands diff --git a/docs/主播公会BD架构.md b/docs/主播公会BD架构.md index a8f01cb8..146e7735 100644 --- a/docs/主播公会BD架构.md +++ b/docs/主播公会BD架构.md @@ -16,7 +16,7 @@ - BD 默认不是主播;BD 可以加入别的 Agency 成为主播,也可以在未成为主播时邀请自己成为自己的 Agency。 - `coin_seller` 是独立币商身份,可以和 Agency、BD、BD Leader 身份并存;币商拥有专用金币账户,可以给玩家转普通金币。 - App 侧可以展示 host 统计、Agency 成员、申请、邀请和后台已经生成的收益结果。 -- App 侧不能创建政策、计算工资周期、审核工资单或直接给 `USD_BALANCE` 入账。 +- App 侧不能创建政策、计算工资周期、审核工资单或直接给 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 入账。 ## Non-Goals @@ -67,7 +67,7 @@ graph LR | `gateway-service` | HTTP 入口、鉴权、request envelope、调用内部 gRPC | | `user-service` | 用户主数据、国家、区域、账号状态;host 身份、Agency、BD、coin_seller 层级、申请邀请、关系快照、App 查询读模型 | | `room-service` | 房间事件:上麦、确认发流、下麦、送礼、离房 | -| `wallet-service` | `COIN`、`COIN_SELLER_COIN`、`USD_BALANCE`、收益余额、提现冻结/审核/出账 | +| `wallet-service` | `COIN`、`COIN_SELLER_COIN`、`HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`、收益余额、提现冻结/审核/出账 | `user-service` host domain 读取 `room-service` 和 `wallet-service` 事件,但不反向修改房间状态。App 查询只读取当前身份、关系、申请、邀请、统计和后台已生成的收益结果;结算写入链路见 Admin 文档。 diff --git a/docs/币商库存授信架构.md b/docs/币商库存授信架构.md index ae45f19b..4f8be6d1 100644 --- a/docs/币商库存授信架构.md +++ b/docs/币商库存授信架构.md @@ -14,7 +14,7 @@ - `USDT进货`:平台收到币商线下 USDT 后,后台给币商发放 `COIN_SELLER_COIN` 库存;这笔记录计入币商进货/充值统计。 - `金币补偿`:平台因为异常、活动、人工修正等原因给币商补库存;没有充值金额,不计入币商进货/充值统计。 -- 两种类型都不能给币商发放 `USD_BALANCE`,也不能直接影响玩家普通 `COIN`。 +- 两种类型都不能给币商发放 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`,也不能直接影响玩家普通 `COIN`。 ## 服务边界 diff --git a/docs/我的页概览接口.md b/docs/我的页概览接口.md index 25f4def5..643f6dd2 100644 --- a/docs/我的页概览接口.md +++ b/docs/我的页概览接口.md @@ -134,8 +134,8 @@ Authorization: Bearer | --- | --- | --- | | 消息 tab、系统消息、活动消息 | 我的页设计稿不展示消息红点 | 消息 tab 页面接口 | | 邀请码入口和邀请统计 | 截图首屏没有邀请码入口 | 邀请页或活动入口 | -| `wallet.recharge_enabled` / `withdraw_enabled` / `diamond_exchange_enabled` | 首屏卡片不需要操作开关 | `GET /api/v1/wallet/me/overview` | -| `DIAMOND` / `USD_BALANCE` | 首屏钱包卡片只展示金币 | 钱包二级页余额接口 | +| `wallet.recharge_enabled` / `diamond_exchange_enabled` | 首屏卡片不需要操作开关 | `GET /api/v1/wallet/me/overview` | +| `DIAMOND` / `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` | 首屏钱包卡片只展示金币 | 钱包二级页余额接口 | | 邀请用户列表、钱包流水、工资明细、团队成员、背包完整列表、任务列表 | 都需要分页或聚合 | 对应二级页接口 | ## Performance Budget @@ -180,7 +180,6 @@ sequenceDiagram | `GET /api/v1/wallet/me/overview` | 钱包二级页余额和操作开关 | | `GET /api/v1/wallet/recharge/products` | 当前区域充值渠道和档位 | | `GET /api/v1/wallet/diamond-exchange/config` | 钻石兑换金币/余额配置 | -| `POST /api/v1/wallet/withdrawals/apply` | 创建待审核提现申请并冻结 `USD_BALANCE` | | `GET /api/v1/wallet/transactions` | 钱包流水分页 | | `GET /api/v1/vip/me` | 当前 VIP 状态 | | `GET /api/v1/vip/packages` | 可购买 VIP 包 | diff --git a/docs/接口清单.md b/docs/接口清单.md index 1850992b..e581dd27 100644 --- a/docs/接口清单.md +++ b/docs/接口清单.md @@ -99,7 +99,6 @@ | GET | `/api/v1/wallet/me/balances` | wallet | `getMyBalances` | 查询当前用户钱包余额 | | GET | `/api/v1/wallet/recharge/products` | wallet | `listRechargeProducts` | 查询充值商品和渠道 | | GET | `/api/v1/wallet/diamond-exchange/config` | wallet | `getDiamondExchangeConfig` | 查询钻石兑换配置 | -| POST | `/api/v1/wallet/withdrawals/apply` | wallet | `applyWithdrawal` | 提交美元余额提现申请 | | GET | `/api/v1/wallet/coin-transactions` | wallet | `listCoinTransactions` | 分页查询当前用户金币流水 | | GET | `/api/v1/wallet/transactions` | wallet | `listWalletTransactions` | 分页查询钱包流水 | | POST | `/api/v1/wallet/coin-seller/transfer` | wallet | `transferCoinFromSeller` | 币商给玩家转金币 | diff --git a/docs/钱包服务架构.md b/docs/钱包服务架构.md index 52a39796..e284f1e7 100644 --- a/docs/钱包服务架构.md +++ b/docs/钱包服务架构.md @@ -21,9 +21,9 @@ | `COIN_SELLER_COIN` | 币商专用金币库存,只能转给玩家形成普通 `COIN` | yes, seller transfer only | no | wallet-service | | `DIAMOND` | 钻石,不可直接消费,只能按政策兑换金币或美元余额 | no | no | wallet-service | | `GIFT_POINT` | 主播礼物积分,达到政策后结算美元奖励 | no | no | wallet-service | -| `USD_BALANCE` | 主播可提现美元余额,建议单位为 cent 或 micro cent | no | yes | wallet-service | +| `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` | 主播可提现美元余额,建议单位为 cent 或 micro cent | no | yes | wallet-service | -钻石和积分都不是直接消费资产。钻石兑换金币或美元余额时必须落兑换订单,记录政策版本、汇率和结果。主播积分达到政策后,由结算任务发起美元余额奖励入账,用户提现只能提现 `USD_BALANCE`。 +钻石和积分都不是直接消费资产。钻石兑换金币或美元余额时必须落兑换订单,记录政策版本、汇率和结果。主播积分达到政策后,由结算任务发起美元余额奖励入账,用户提现只能提现 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`。 资源组可以通过资源域的 `wallet_asset` 组成员直接给用户发放 `COIN` 或 `DIAMOND`,但这仍然是钱包入账流水,不写用户资源权益;钻石后续兑换仍必须走独立兑换订单。 @@ -40,7 +40,7 @@ | 充值 | `PARTIAL` | 币商转账已写 `wallet_recharge_records`,provider order 未实现 | Apple、Google、线下订单和 provider 校验仍需补齐 | | 币商转金币 | `DONE` | `TransferCoinFromSeller` 扣 `COIN_SELLER_COIN`、加玩家 `COIN`,并按区域充值政策记录美元充值金额 | 限额、线下订单和风控审计仍需补齐 | | 钻石兑换 | `TODO` | 无 diamond exchange order | 需要政策快照、兑换状态机和原子出入账 | -| 主播积分/奖励 | `PARTIAL` | 送礼实时给收礼人加 `GIFT_POINT` | 周期结算任务和 `USD_BALANCE` 奖励入账未落地 | +| 主播积分/奖励 | `PARTIAL` | 送礼实时给收礼人加 `GIFT_POINT` | 周期结算任务和 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 奖励入账未落地 | | 提现 | `TODO` | 无 withdraw request | 需要冻结、审核、人工打款、失败回滚 | | 钱包 outbox | `PARTIAL` | `wallet_outbox` 已和交易同事务写入 `WalletBalanceChanged/WalletGiftDebited/WalletCoinSellerTransferred/WalletRechargeRecorded` | outbox worker 和 MQ 投递适配未落地 | @@ -83,8 +83,8 @@ ### P4: Anchor Reward And Withdraw - 送礼实时加主播 `GIFT_POINT`,但美元奖励由结算任务按政策转换,不能写死在送礼链路。 -- 奖励结算生成 `anchor_reward_settlements`,确认后加主播 `USD_BALANCE`。 -- 提现申请必须先冻结 `USD_BALANCE`,审核拒绝解冻,审核通过后进入人工打款流程。 +- 奖励结算生成 `anchor_reward_settlements`,确认后加主播 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`。 +- 提现申请必须先冻结 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`,审核拒绝解冻,审核通过后进入人工打款流程。 - 人工打款完成后从冻结余额出账;打款失败回到可重试状态,不能自动解冻后丢失审核上下文。 ## Component Diagram @@ -239,7 +239,7 @@ wallet_recharge_records( ); ``` -`wallet_recharge_records.usd_minor_amount` 是用户充值额的权威统计口径;用户不会因此获得 `USD_BALANCE`。政策字段必须保存快照,后续修改区域汇率不能重算历史充值。 +`wallet_recharge_records.usd_minor_amount` 是用户充值额的权威统计口径;用户不会因此获得 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`。政策字段必须保存快照,后续修改区域汇率不能重算历史充值。 ## Send Gift Flow @@ -321,7 +321,7 @@ stateDiagram-v2 flowchart LR A["User DIAMOND account"] -->|"debit diamonds"| X["diamond_exchange_order"] X -->|"policy: diamond to coin"| C["User COIN account"] - X -->|"policy: diamond to USD"| U["User USD_BALANCE account"] + X -->|"policy: diamond to USD"| U["User identity salary wallet account"] ``` 钻石兑换必须冻结政策版本。订单里至少记录 `from_diamond_amount`、`to_asset_type`、`to_amount`、`policy_id`、`rate_snapshot` 和 `status`。兑换成功后写分录和 outbox;兑换失败不能出现钻石扣了但目标资产没到账。 @@ -332,8 +332,8 @@ flowchart LR 1. 送礼时钱包给主播增加 `GIFT_POINT`。 2. 结算任务读取积分和政策,生成 `anchor_reward_settlements`。 -3. 结算单确认后调用钱包 `CreditRewardBalance`,增加主播 `USD_BALANCE`。 -4. 主播提现时先冻结 `USD_BALANCE`,审核拒绝解冻,审核通过后等待人工转账。 +3. 结算单确认后调用钱包 `CreditRewardBalance`,增加主播 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`。 +4. 主播提现时先冻结 `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD`,审核拒绝解冻,审核通过后等待人工转账。 5. 人工转账完成后把冻结余额出账,状态改为 `paid`。 提现状态机: @@ -499,7 +499,7 @@ stateDiagram-v2 提现: -- 提现申请成功后 `USD_BALANCE.available_amount` 减少,`frozen_amount` 增加。 +- 提现申请成功后 `identity salary wallet.available_amount` 减少,`frozen_amount` 增加。 - 审核拒绝后冻结金额回到 available。 - 打款完成后 frozen 减少并写出账分录。 - 打款失败后状态可重试,不丢失冻结关系和审核上下文。 @@ -533,7 +533,7 @@ docker compose config - 幂等键必须覆盖业务语义,同一个 command_id 带不同 payload 必须返回冲突。 - Apple/Google 充值以 provider 真实交易号为最终幂等源,不能只信客户端 request id。 - 币商充值分两段:平台给币商发 `COIN_SELLER_COIN` 库存,币商再把库存转成用户 `COIN`;必须有币商金币余额、充值政策快照、限额和审计。 -- `USD_BALANCE` 是可提现负债,调账和奖励发放需要更高权限和审计。 +- `HOST_SALARY_USD`, `AGENCY_SALARY_USD`, `BD_SALARY_USD`, `ADMIN_SALARY_USD` 是可提现负债,调账和奖励发放需要更高权限和审计。 - 兑换汇率和奖励政策必须记录快照,不能只存当前 policy id。 - 提现人工打款前必须冻结余额,打款失败要回到可重新处理状态。 - 钱包事件投递使用 outbox,MQ 投递失败不回滚账务事实。 diff --git a/scripts/mysql/034_remove_usd_balance_withdrawal_requests.sql b/scripts/mysql/034_remove_usd_balance_withdrawal_requests.sql new file mode 100644 index 00000000..cec71604 --- /dev/null +++ b/scripts/mysql/034_remove_usd_balance_withdrawal_requests.sql @@ -0,0 +1,55 @@ +-- Remove the obsolete generic USD withdrawal request table from the wallet database. +-- Salary settlement now writes role-specific wallets only: +-- HOST_SALARY_USD, AGENCY_SALARY_USD, BD_SALARY_USD, ADMIN_SALARY_USD. +-- Keep an archive copy before dropping the source table so production history is not lost. + +SET @source_exists := ( + SELECT COUNT(*) + FROM information_schema.TABLES + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'wallet_withdrawal_requests' +); + +SET @archive_exists := ( + SELECT COUNT(*) + FROM information_schema.TABLES + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'wallet_withdrawal_requests_removed_20260602' +); + +SET @sql := IF( + @source_exists = 1 AND @archive_exists = 0, + 'CREATE TABLE wallet_withdrawal_requests_removed_20260602 LIKE wallet_withdrawal_requests', + 'SELECT 1' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql := IF( + @source_exists = 1, + 'INSERT IGNORE INTO wallet_withdrawal_requests_removed_20260602 SELECT * FROM wallet_withdrawal_requests', + 'SELECT 1' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @sql := IF( + @source_exists = 1, + 'DROP TABLE wallet_withdrawal_requests', + 'SELECT 1' +); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT + SUM(TABLE_NAME = 'wallet_withdrawal_requests') AS source_table_exists, + SUM(TABLE_NAME = 'wallet_withdrawal_requests_removed_20260602') AS archive_table_exists +FROM information_schema.TABLES +WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME IN ( + 'wallet_withdrawal_requests', + 'wallet_withdrawal_requests_removed_20260602' + ); diff --git a/server/admin/internal/modules/teamsalarysettlement/service.go b/server/admin/internal/modules/teamsalarysettlement/service.go index 005a3805..07af8ce9 100644 --- a/server/admin/internal/modules/teamsalarysettlement/service.go +++ b/server/admin/internal/modules/teamsalarysettlement/service.go @@ -23,8 +23,9 @@ const ( policyTypeAdmin = "admin" triggerAutomatic = "automatic" triggerManual = "manual" - // assetUSDBalance 必须与 wallet-service 钱包资产类型保持一致,BD/Admin 工资直接入美元余额账户。 - assetUSDBalance = "USD_BALANCE" + // BD/Admin 工资钱包资产类型必须与 wallet-service ledger 常量保持一致;admin-server 是独立 module,不能直接复用根 module 常量。 + assetBDSalaryUSD = "BD_SALARY_USD" + assetAdminSalaryUSD = "ADMIN_SALARY_USD" bizTypeTeamSettlement = "team_salary_settlement" statusSucceeded = "succeeded" ) @@ -97,6 +98,7 @@ type settlementMetadata struct { LevelNo int `json:"level_no"` IncomeUSDMinor int64 `json:"income_usd_minor"` SalaryUSDMinorDelta int64 `json:"salary_usd_minor_delta"` + SalaryAssetType string `json:"salary_asset_type"` SettledLevelNo int `json:"settled_level_no"` SettledSalaryUSDMinor int64 `json:"settled_salary_usd_minor"` ProcessedAtMS int64 `json:"processed_at_ms"` @@ -490,6 +492,10 @@ func (s *Service) settleCandidate(ctx context.Context, appCode string, operatorA MonthClosedAtMS: nowMS, Version: progress.Version, } + salaryAssetType := teamSalaryAssetType(candidate.PolicyType) + if salaryAssetType == "" { + return recordDTO{}, false, fmt.Errorf("team salary asset type is invalid: %s", candidate.PolicyType) + } metadata := settlementMetadata{ AppCode: appCode, PolicyType: candidate.PolicyType, @@ -502,6 +508,7 @@ func (s *Service) settleCandidate(ctx context.Context, appCode string, operatorA LevelNo: candidate.Level.LevelNo, IncomeUSDMinor: candidate.IncomeUSDMinor, SalaryUSDMinorDelta: salaryDelta, + SalaryAssetType: salaryAssetType, SettledLevelNo: nextProgress.SettledLevelNo, SettledSalaryUSDMinor: nextProgress.SettledSalaryUSDMinor, ProcessedAtMS: nowMS, @@ -513,11 +520,11 @@ func (s *Service) settleCandidate(ctx context.Context, appCode string, operatorA if err := s.insertWalletTransaction(ctx, tx, appCode, transactionID, commandID, metadata, nowMS); err != nil { return recordDTO{}, false, err } - balanceAfter, version, err := s.creditWallet(ctx, tx, appCode, transactionID, candidate.UserID, salaryDelta, nowMS) + balanceAfter, version, err := s.creditWallet(ctx, tx, appCode, transactionID, candidate.UserID, metadata.SalaryAssetType, salaryDelta, nowMS) if err != nil { return recordDTO{}, false, err } - if err := s.insertWalletOutbox(ctx, tx, appCode, transactionID, commandID, candidate.UserID, salaryDelta, balanceAfter, version, metadata, nowMS); err != nil { + if err := s.insertWalletOutbox(ctx, tx, appCode, transactionID, commandID, candidate.UserID, metadata.SalaryAssetType, salaryDelta, balanceAfter, version, metadata, nowMS); err != nil { return recordDTO{}, false, err } if err := s.insertRecord(ctx, tx, appCode, transactionID, commandID, metadata, nowMS); err != nil { @@ -840,12 +847,12 @@ func (s *Service) insertWalletTransaction(ctx context.Context, tx *sql.Tx, appCo return err } -// creditWallet 锁定美元账户并追加 wallet_entries,使余额、流水和版本在同一事务内一致。 -func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, transactionID string, userID int64, amount int64, nowMS int64) (int64, int64, error) { +// creditWallet 锁定对应角色工资钱包并追加 wallet_entries,使余额、流水和版本在同一事务内一致。 +func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, transactionID string, userID int64, assetType string, amount int64, nowMS int64) (int64, int64, error) { if _, err := tx.ExecContext(ctx, ` INSERT IGNORE INTO wallet_accounts ( app_code, user_id, asset_type, available_amount, frozen_amount, version, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, 0, 0, 1, ?, ?)`, appCode, userID, assetUSDBalance, nowMS, nowMS); err != nil { + ) VALUES (?, ?, ?, 0, 0, 1, ?, ?)`, appCode, userID, assetType, nowMS, nowMS); err != nil { return 0, 0, err } var available int64 @@ -855,7 +862,7 @@ func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, SELECT available_amount, frozen_amount, version FROM wallet_accounts WHERE app_code = ? AND user_id = ? AND asset_type = ? - FOR UPDATE`, appCode, userID, assetUSDBalance, + FOR UPDATE`, appCode, userID, assetType, ).Scan(&available, &frozen, &version); err != nil { return 0, 0, err } @@ -868,7 +875,7 @@ func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, UPDATE wallet_accounts SET available_amount = ?, version = version + 1, updated_at_ms = ? WHERE app_code = ? AND user_id = ? AND asset_type = ? AND version = ?`, - after, nowMS, appCode, userID, assetUSDBalance, version, + after, nowMS, appCode, userID, assetType, version, ); err != nil { return 0, 0, err } @@ -877,7 +884,7 @@ func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, app_code, transaction_id, user_id, asset_type, available_delta, frozen_delta, available_after, frozen_after, counterparty_user_id, room_id, created_at_ms ) VALUES (?, ?, ?, ?, ?, 0, ?, ?, 0, '', ?)`, - appCode, transactionID, userID, assetUSDBalance, amount, after, frozen, nowMS, + appCode, transactionID, userID, assetType, amount, after, frozen, nowMS, ); err != nil { return 0, 0, err } @@ -885,12 +892,12 @@ func (s *Service) creditWallet(ctx context.Context, tx *sql.Tx, appCode string, } // insertWalletOutbox 投递余额变更事件,供后续 MQ/通知链路异步消费。 -func (s *Service) insertWalletOutbox(ctx context.Context, tx *sql.Tx, appCode string, transactionID string, commandID string, userID int64, amount int64, balanceAfter int64, version int64, metadata settlementMetadata, nowMS int64) error { +func (s *Service) insertWalletOutbox(ctx context.Context, tx *sql.Tx, appCode string, transactionID string, commandID string, userID int64, assetType string, amount int64, balanceAfter int64, version int64, metadata settlementMetadata, nowMS int64) error { payload, err := json.Marshal(map[string]any{ "transaction_id": transactionID, "command_id": commandID, "user_id": userID, - "asset_type": assetUSDBalance, + "asset_type": assetType, "available_delta": amount, "available_after": balanceAfter, "version": version, @@ -905,7 +912,7 @@ func (s *Service) insertWalletOutbox(ctx context.Context, tx *sql.Tx, appCode st app_code, event_id, event_type, transaction_id, command_id, user_id, asset_type, available_delta, frozen_delta, payload, status, created_at_ms, updated_at_ms ) VALUES (?, ?, 'WalletBalanceChanged', ?, ?, ?, ?, ?, 0, ?, 'pending', ?, ?)`, - appCode, transactionID+":"+assetUSDBalance, transactionID, commandID, userID, assetUSDBalance, amount, string(payload), nowMS, nowMS, + appCode, transactionID+":"+assetType, transactionID, commandID, userID, assetType, amount, string(payload), nowMS, nowMS, ) return err } @@ -1233,6 +1240,18 @@ func normalizeTriggerMode(value string) string { } } +func teamSalaryAssetType(policyType string) string { + // 用户可以同时拥有 BD/Admin 等多重身份,工资资产必须按本次结算角色拆分,不能混入其它身份钱包。 + switch normalizePolicyType(policyType) { + case policyTypeBD: + return assetBDSalaryUSD + case policyTypeAdmin: + return assetAdminSalaryUSD + default: + return "" + } +} + // normalizeStatus 只允许记录表定义的状态值,避免前端筛选拼接任意 SQL 条件。 func normalizeStatus(value string) string { switch strings.ToLower(strings.TrimSpace(value)) { diff --git a/server/admin/internal/modules/teamsalarysettlement/service_integration_test.go b/server/admin/internal/modules/teamsalarysettlement/service_integration_test.go index 6dfd45ef..98488f07 100644 --- a/server/admin/internal/modules/teamsalarysettlement/service_integration_test.go +++ b/server/admin/internal/modules/teamsalarysettlement/service_integration_test.go @@ -72,8 +72,8 @@ func TestRealMySQLTeamSalaryFullFlow(t *testing.T) { if totalRecords != 2 || len(records) != 2 { t.Fatalf("record count mismatch: total=%d len=%d records=%+v", totalRecords, len(records), records) } - assertWalletBalance(t, walletDB, 4001, 100_000) - assertWalletBalance(t, walletDB, 5001, 20_000) + assertWalletBalance(t, walletDB, 4001, assetBDSalaryUSD, 100_000) + assertWalletBalance(t, walletDB, 5001, assetAdminSalaryUSD, 20_000) assertScalar(t, walletDB, `SELECT COUNT(*) FROM team_salary_settlement_records`, int64(2)) assertScalar(t, walletDB, `SELECT COUNT(*) FROM wallet_transactions WHERE biz_type = 'team_salary_settlement'`, int64(2)) @@ -354,14 +354,14 @@ func execAll(t *testing.T, db *sql.DB, statements ...string) { } } -func assertWalletBalance(t *testing.T, db *sql.DB, userID int64, expected int64) { +func assertWalletBalance(t *testing.T, db *sql.DB, userID int64, assetType string, expected int64) { t.Helper() var amount int64 - if err := db.QueryRow(`SELECT available_amount FROM wallet_accounts WHERE app_code = 'lalu' AND user_id = ? AND asset_type = 'USD_BALANCE'`, userID).Scan(&amount); err != nil { + if err := db.QueryRow(`SELECT available_amount FROM wallet_accounts WHERE app_code = 'lalu' AND user_id = ? AND asset_type = ?`, userID, assetType).Scan(&amount); err != nil { t.Fatalf("query wallet balance failed: %v", err) } if amount != expected { - t.Fatalf("wallet balance mismatch for user %d: got=%d want=%d", userID, amount, expected) + t.Fatalf("wallet balance mismatch for user %d asset %s: got=%d want=%d", userID, assetType, amount, expected) } } diff --git a/services/gateway-service/internal/client/wallet_client.go b/services/gateway-service/internal/client/wallet_client.go index a1a608d8..1176233d 100644 --- a/services/gateway-service/internal/client/wallet_client.go +++ b/services/gateway-service/internal/client/wallet_client.go @@ -18,7 +18,6 @@ type WalletClient interface { ConfirmGooglePayment(ctx context.Context, req *walletv1.ConfirmGooglePaymentRequest) (*walletv1.ConfirmGooglePaymentResponse, error) GetDiamondExchangeConfig(ctx context.Context, req *walletv1.GetDiamondExchangeConfigRequest) (*walletv1.GetDiamondExchangeConfigResponse, error) ListWalletTransactions(ctx context.Context, req *walletv1.ListWalletTransactionsRequest) (*walletv1.ListWalletTransactionsResponse, error) - ApplyWithdrawal(ctx context.Context, req *walletv1.ApplyWithdrawalRequest) (*walletv1.ApplyWithdrawalResponse, error) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) @@ -81,10 +80,6 @@ func (c *grpcWalletClient) ListWalletTransactions(ctx context.Context, req *wall return c.client.ListWalletTransactions(ctx, req) } -func (c *grpcWalletClient) ApplyWithdrawal(ctx context.Context, req *walletv1.ApplyWithdrawalRequest) (*walletv1.ApplyWithdrawalResponse, error) { - return c.client.ApplyWithdrawal(ctx, req) -} - func (c *grpcWalletClient) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) { return c.client.ListVipPackages(ctx, req) } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 62629a84..3fc3b3e8 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -167,7 +167,6 @@ type WalletHandlers struct { ListRechargeProducts http.HandlerFunc ConfirmGooglePayment http.HandlerFunc GetDiamondExchangeConfig http.HandlerFunc - ApplyWithdrawal http.HandlerFunc ListCoinTransactions http.HandlerFunc ListWalletTransactions http.HandlerFunc ListCoinSellers http.HandlerFunc @@ -396,7 +395,6 @@ func (r routes) registerWalletRoutes() { r.profile("/wallet/recharge/products", http.MethodGet, h.ListRechargeProducts) r.profile("/wallet/payments/google/confirm", http.MethodPost, h.ConfirmGooglePayment) r.profile("/wallet/diamond-exchange/config", http.MethodGet, h.GetDiamondExchangeConfig) - r.profile("/wallet/withdrawals/apply", http.MethodPost, h.ApplyWithdrawal) r.profile("/wallet/coin-transactions", http.MethodGet, h.ListCoinTransactions) r.profile("/wallet/transactions", http.MethodGet, h.ListWalletTransactions) r.profile("/wallet/coin-sellers", http.MethodGet, h.ListCoinSellers) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 596b6087..3861ca26 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -429,8 +429,6 @@ type fakeWalletClient struct { diamondExchangeResp *walletv1.GetDiamondExchangeConfigResponse lastTransactions *walletv1.ListWalletTransactionsRequest transactionsResp *walletv1.ListWalletTransactionsResponse - lastWithdrawal *walletv1.ApplyWithdrawalRequest - withdrawalResp *walletv1.ApplyWithdrawalResponse lastVipPackages *walletv1.ListVipPackagesRequest vipPackagesResp *walletv1.ListVipPackagesResponse lastMyVip *walletv1.GetMyVipRequest @@ -1147,7 +1145,6 @@ func (f *fakeWalletClient) GetWalletOverview(_ context.Context, req *walletv1.Ge FeatureFlags: &walletv1.WalletFeatureFlags{ RechargeEnabled: true, DiamondExchangeEnabled: true, - WithdrawEnabled: true, }, }, nil } @@ -1230,17 +1227,6 @@ func (f *fakeWalletClient) ListWalletTransactions(_ context.Context, req *wallet return &walletv1.ListWalletTransactionsResponse{}, nil } -func (f *fakeWalletClient) ApplyWithdrawal(_ context.Context, req *walletv1.ApplyWithdrawalRequest) (*walletv1.ApplyWithdrawalResponse, error) { - f.lastWithdrawal = req - if f.err != nil { - return nil, f.err - } - if f.withdrawalResp != nil { - return f.withdrawalResp, nil - } - return &walletv1.ApplyWithdrawalResponse{}, nil -} - func (f *fakeWalletClient) ListVipPackages(_ context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) { f.lastVipPackages = req if f.vipErr != nil { diff --git a/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go index e763ca0a..65c80704 100644 --- a/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go @@ -47,7 +47,6 @@ type walletOverviewData struct { type walletFeatureFlagsData struct { RechargeEnabled bool `json:"recharge_enabled"` DiamondExchangeEnabled bool `json:"diamond_exchange_enabled"` - WithdrawEnabled bool `json:"withdraw_enabled"` } type walletTransactionData struct { @@ -96,15 +95,6 @@ type giftWallItemData struct { SortOrder int32 `json:"sort_order"` } -type withdrawalApplyRequestBody struct { - CommandID string `json:"command_id"` - CommandIDAlt string `json:"commandId"` - Amount int64 `json:"amount"` - PayoutAccount string `json:"payout_account"` - PayoutAlt string `json:"payoutAccount"` - Reason string `json:"reason"` -} - type googlePaymentConfirmRequestBody struct { CommandID string `json:"command_id"` CommandIDAlt string `json:"commandId"` @@ -134,18 +124,6 @@ type googlePaymentConfirmData struct { ConsumeState string `json:"consume_state"` } -type withdrawalData struct { - WithdrawalID string `json:"withdrawal_id"` - UserID int64 `json:"user_id"` - AssetType string `json:"asset_type"` - Amount int64 `json:"amount"` - Status string `json:"status"` - PayoutAccount string `json:"payout_account"` - Reason string `json:"reason"` - CreatedAtMS int64 `json:"created_at_ms"` - UpdatedAtMS int64 `json:"updated_at_ms"` -} - type vipPurchaseRequestBody struct { CommandID string `json:"command_id"` CommandIDAlt string `json:"commandId"` @@ -387,46 +365,6 @@ func (h *Handler) listWalletTransactionsByAsset(writer http.ResponseWriter, requ httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": resp.GetTotal(), "page": page, "page_size": pageSize}) } -// applyWithdrawal 创建待人工审核的提现申请。 -func (h *Handler) applyWithdrawal(writer http.ResponseWriter, request *http.Request) { - if h.walletClient == nil { - httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") - return - } - var body withdrawalApplyRequestBody - if !httpkit.Decode(writer, request, &body) { - return - } - commandID := strings.TrimSpace(body.CommandID) - if commandID == "" { - commandID = strings.TrimSpace(body.CommandIDAlt) - } - payoutAccount := strings.TrimSpace(body.PayoutAccount) - if payoutAccount == "" { - payoutAccount = strings.TrimSpace(body.PayoutAlt) - } - if commandID == "" || body.Amount <= 0 || payoutAccount == "" { - httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") - return - } - resp, err := h.walletClient.ApplyWithdrawal(request.Context(), &walletv1.ApplyWithdrawalRequest{ - CommandId: commandID, - AppCode: appcode.FromContext(request.Context()), - UserId: auth.UserIDFromContext(request.Context()), - Amount: body.Amount, - PayoutAccount: payoutAccount, - Reason: strings.TrimSpace(body.Reason), - }) - if err != nil { - httpkit.WriteRPCError(writer, request, err) - return - } - httpkit.WriteOK(writer, request, map[string]any{ - "withdrawal": withdrawalFromProto(resp.GetWithdrawal()), - "balance": balanceFromProto(resp.GetBalance()), - }) -} - func rechargeProductFromProto(product *walletv1.RechargeProduct) rechargeProductData { if product == nil { return rechargeProductData{} @@ -496,7 +434,6 @@ func walletOverviewFromProto(resp *walletv1.GetWalletOverviewResponse) walletOve FeatureFlags: walletFeatureFlagsData{ RechargeEnabled: flags.GetRechargeEnabled(), DiamondExchangeEnabled: flags.GetDiamondExchangeEnabled(), - WithdrawEnabled: flags.GetWithdrawEnabled(), }, } } @@ -566,23 +503,6 @@ func giftWallItemFromProto(item *walletv1.GiftWallItem) giftWallItemData { } } -func withdrawalFromProto(item *walletv1.WithdrawalRequest) withdrawalData { - if item == nil { - return withdrawalData{} - } - return withdrawalData{ - WithdrawalID: item.GetWithdrawalId(), - UserID: item.GetUserId(), - AssetType: item.GetAssetType(), - Amount: item.GetAmount(), - Status: item.GetStatus(), - PayoutAccount: item.GetPayoutAccount(), - Reason: item.GetReason(), - CreatedAtMS: item.GetCreatedAtMs(), - UpdatedAtMS: item.GetUpdatedAtMs(), - } -} - func balanceFromProto(balance *walletv1.AssetBalance) assetBalanceData { if balance == nil { return assetBalanceData{} diff --git a/services/gateway-service/internal/transport/http/walletapi/handler.go b/services/gateway-service/internal/transport/http/walletapi/handler.go index c1be1e32..a83a1caa 100644 --- a/services/gateway-service/internal/transport/http/walletapi/handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/handler.go @@ -48,7 +48,6 @@ func (h *Handler) WalletHandlers() httproutes.WalletHandlers { ListRechargeProducts: h.listRechargeProducts, ConfirmGooglePayment: h.confirmGooglePayment, GetDiamondExchangeConfig: h.getDiamondExchangeConfig, - ApplyWithdrawal: h.applyWithdrawal, ListCoinTransactions: h.listCoinTransactions, ListWalletTransactions: h.listWalletTransactions, ListCoinSellers: h.listCoinSellers, 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 a3b1a777..82eb0ae3 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -1046,28 +1046,6 @@ CREATE TABLE IF NOT EXISTS red_packet_user_daily_counters ( PRIMARY KEY (app_code, user_id, send_day) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包用户每日发送计数表'; -CREATE TABLE IF NOT EXISTS wallet_withdrawal_requests ( - app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', - withdrawal_id VARCHAR(96) NOT NULL COMMENT '提现 ID', - command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID', - user_id BIGINT NOT NULL COMMENT '用户 ID', - asset_type VARCHAR(32) NOT NULL COMMENT '钱包资产类型', - amount BIGINT NOT NULL COMMENT '金额或数量', - status VARCHAR(32) NOT NULL COMMENT '业务状态', - payout_account VARCHAR(256) NOT NULL COMMENT '出款账户', - reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '原因', - wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID', - reviewed_by_user_id BIGINT NULL COMMENT '审核用户 ID', - review_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '审核原因', - reviewed_at_ms BIGINT NULL 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, withdrawal_id), - UNIQUE KEY uk_withdrawal_command (app_code, command_id), - KEY idx_withdrawal_user_time (app_code, user_id, created_at_ms), - KEY idx_withdrawal_status_time (app_code, status, created_at_ms) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包提现申请表'; - CREATE TABLE IF NOT EXISTS vip_levels ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', level INT NOT NULL COMMENT '等级', diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index 6af43c6a..05b54dba 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -11,8 +11,14 @@ const ( AssetGiftPoint = "GIFT_POINT" // AssetHostPeriodDiamond 是主播工资周期钻石投影,只参与工资等级结算,不进入通用钱包余额。 AssetHostPeriodDiamond = "HOST_PERIOD_DIAMOND" - // AssetUSDBalance 是主播可提现美元余额,单位由后续提现策略固定。 - AssetUSDBalance = "USD_BALANCE" + // AssetHostSalaryUSD 是主播工资美元钱包,只接收主播工资和月底剩余钻石折美元。 + AssetHostSalaryUSD = "HOST_SALARY_USD" + // AssetAgencySalaryUSD 是代理工资美元钱包,只接收主播结算同时产生的代理工资。 + AssetAgencySalaryUSD = "AGENCY_SALARY_USD" + // AssetBDSalaryUSD 是 BD 工资美元钱包,只接收 BD 政策结算工资。 + AssetBDSalaryUSD = "BD_SALARY_USD" + // AssetAdminSalaryUSD 是 Admin 工资美元钱包,只接收 Admin 政策结算工资。 + AssetAdminSalaryUSD = "ADMIN_SALARY_USD" // StockTypeUSDTPurchase 表示币商线下 USDT 进货后发放专用金币库存。 StockTypeUSDTPurchase = "usdt_purchase" @@ -43,9 +49,6 @@ const ( // GooglePurchaseStatePurchased 是 Google Play 已支付完成状态。 GooglePurchaseStatePurchased = "PURCHASED" - // WithdrawalStatusPending 表示主播美元余额提现已提交,等待后台人工审核和线下转账。 - WithdrawalStatusPending = "pending" - // HostSalarySettlementModeDaily 表示主播工资按日结算等级增量。 HostSalarySettlementModeDaily = "daily" // HostSalarySettlementModeHalfMonth 表示主播工资按半月周期结算等级增量。 @@ -279,7 +282,6 @@ type ListRechargeBillsQuery struct { type WalletFeatureFlags struct { RechargeEnabled bool DiamondExchangeEnabled bool - WithdrawEnabled bool } // WalletOverview 是我的页和钱包首页共同使用的轻量摘要。 @@ -473,29 +475,6 @@ type ListWalletTransactionsQuery struct { PageSize int32 } -// WithdrawalCommand 是主播余额提现申请命令。人工审核和线下转账不在 App 主链路完成。 -type WithdrawalCommand struct { - AppCode string - CommandID string - UserID int64 - Amount int64 - PayoutAccount string - Reason string -} - -// WithdrawalRequest 是提现申请事实。 -type WithdrawalRequest struct { - WithdrawalID string - UserID int64 - AssetType string - Amount int64 - Status string - PayoutAccount string - Reason string - CreatedAtMS int64 - UpdatedAtMS int64 -} - // VipRewardItem 是 VIP 资源组权益的轻量展示投影。 type VipRewardItem struct { ResourceID int64 @@ -786,7 +765,7 @@ type RedPacketExpireResult struct { // ValidAssetType 限定账本允许落账的资产类型,避免写入任意字符串资产。 func ValidAssetType(assetType string) bool { switch assetType { - case AssetCoin, AssetCoinSellerCoin, AssetGiftPoint, AssetUSDBalance: + case AssetCoin, AssetCoinSellerCoin, AssetGiftPoint, AssetHostSalaryUSD, AssetAgencySalaryUSD, AssetBDSalaryUSD, AssetAdminSalaryUSD: return true default: return false diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index 5309c5d5..03b767d6 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -48,7 +48,6 @@ type Repository interface { DeleteRechargeProduct(ctx context.Context, appCode string, productID int64) error GetDiamondExchangeConfig(ctx context.Context, userID int64) ([]ledger.DiamondExchangeRule, error) ListWalletTransactions(ctx context.Context, query ledger.ListWalletTransactionsQuery) ([]ledger.WalletTransaction, int64, error) - ApplyWithdrawal(ctx context.Context, command ledger.WithdrawalCommand) (ledger.WithdrawalRequest, ledger.AssetBalance, error) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, error) PurchaseVip(ctx context.Context, command ledger.PurchaseVipCommand) (ledger.PurchaseVipReceipt, error) @@ -738,24 +737,6 @@ func (s *Service) ListWalletTransactions(ctx context.Context, query ledger.ListW return s.repository.ListWalletTransactions(ctx, query) } -// ApplyWithdrawal 冻结主播美元余额并创建待人工审核提现申请。 -func (s *Service) ApplyWithdrawal(ctx context.Context, command ledger.WithdrawalCommand) (ledger.WithdrawalRequest, ledger.AssetBalance, error) { - if command.CommandID == "" || command.UserID <= 0 || command.Amount <= 0 { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, xerr.New(xerr.InvalidArgument, "withdrawal command is incomplete") - } - command.PayoutAccount = strings.TrimSpace(command.PayoutAccount) - command.Reason = strings.TrimSpace(command.Reason) - if command.PayoutAccount == "" || len(command.PayoutAccount) > 256 || len(command.Reason) > 512 { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, xerr.New(xerr.InvalidArgument, "withdrawal payout account is invalid") - } - if s.repository == nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") - } - command.AppCode = appcode.Normalize(command.AppCode) - ctx = appcode.WithContext(ctx, command.AppCode) - return s.repository.ApplyWithdrawal(ctx, command) -} - // ListVipPackages 返回可购买 VIP 包和当前会员状态。 func (s *Service) ListVipPackages(ctx context.Context, userID int64) (ledger.UserVip, []ledger.VipLevel, error) { if userID <= 0 { diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 7203fbdd..047de1ae 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -264,9 +264,9 @@ func TestHostSalarySettlementCreditsIncrementalRewards(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 || result.FailureCount != 0 { t.Fatalf("first settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 150) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 150) assertBalance(t, svc, 10002, ledger.AssetCoin, 90) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 50) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 50) second, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ CommandID: "cmd-salary-gift-2", @@ -301,9 +301,9 @@ func TestHostSalarySettlementCreditsIncrementalRewards(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 || result.FailureCount != 0 { t.Fatalf("second settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 300) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 300) assertBalance(t, svc, 10002, ledger.AssetCoin, 198) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 80) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 80) if got := repository.CountRows("host_salary_settlement_records", "user_id = ? AND cycle_key = ?", int64(10002), first.HostPeriodCycleKey); got != 2 { t.Fatalf("salary settlement records mismatch, got %d", got) } @@ -391,8 +391,8 @@ func TestHostSalaryManualPolicyRequiresManualTrigger(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 { t.Fatalf("manual settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 150) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 50) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 150) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 50) } // TestHostSalaryMonthEndCreditsResidualAndClearsCycle 验证月底结算补发剩余钻石折美元,并逻辑关闭当月周期。 @@ -455,7 +455,7 @@ func TestHostSalaryMonthEndCreditsResidualAndClearsCycle(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 || result.FailureCount != 0 { t.Fatalf("month-end settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 400) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 400) if got := repository.CountRows("host_salary_settlement_progress", "user_id = ? AND cycle_key = ? AND residual_usd_minor = ? AND month_end_cleared_at_ms > 0", int64(10002), receipt.HostPeriodCycleKey, int64(250)); got != 1 { t.Fatalf("month-end progress should store residual and cleared marker, got %d", got) } @@ -534,9 +534,9 @@ func TestHostSalaryFullLifecycleFromPublishedPolicyToNextCycle(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 || result.FailureCount != 0 { t.Fatalf("level 1 daily settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 150) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 150) assertBalance(t, svc, 10002, ledger.AssetCoin, 90) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 50) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 50) previousIDs := repository.HostSalarySettlementIDs(10002, previousCycle) if len(previousIDs) != 1 || previousIDs[0] == "" { t.Fatalf("level 1 settlement id missing: %v", previousIDs) @@ -598,9 +598,9 @@ func TestHostSalaryFullLifecycleFromPublishedPolicyToNextCycle(t *testing.T) { t.Fatalf("level 2 daily settlement result mismatch: %+v", result) } // 第二次只补发累计 2 级与已发 1 级之间的差额,最终余额等于 2 级累计权益。 - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 300) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 300) assertBalance(t, svc, 10002, ledger.AssetCoin, 198) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 80) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 80) previousIDs = repository.HostSalarySettlementIDs(10002, previousCycle) if len(previousIDs) != 2 { t.Fatalf("level 2 settlement should create second record: %v", previousIDs) @@ -623,7 +623,7 @@ func TestHostSalaryFullLifecycleFromPublishedPolicyToNextCycle(t *testing.T) { t.Fatalf("month-end lifecycle result mismatch: %+v", result) } // 480 钻石达到 2 级后剩余 80 钻石,按 0.01 USD/diamond 折算为 80 美分并标记周期已清算。 - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 380) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 380) if got := repository.CountRows("host_salary_settlement_progress", "user_id = ? AND cycle_key = ? AND last_settled_total_diamonds = ? AND residual_usd_minor = ? AND month_end_cleared_at_ms > 0", int64(10002), previousCycle, int64(480), int64(80)); got != 1 { t.Fatalf("month-end progress should store residual and clear marker, got %d", got) } @@ -683,9 +683,9 @@ func TestHostSalaryFullLifecycleFromPublishedPolicyToNextCycle(t *testing.T) { t.Fatalf("next-cycle daily result mismatch: %+v", result) } // 新 cycle_key 使用独立进度,因此月末清算后的下一周期从 1 级累计权益重新开始发放。 - assertBalance(t, svc, 10002, ledger.AssetUSDBalance, 530) + assertBalance(t, svc, 10002, ledger.AssetHostSalaryUSD, 530) assertBalance(t, svc, 10002, ledger.AssetCoin, 288) - assertBalance(t, svc, 30001, ledger.AssetUSDBalance, 130) + assertBalance(t, svc, 30001, ledger.AssetAgencySalaryUSD, 130) nextIDs := repository.HostSalarySettlementIDs(10002, third.HostPeriodCycleKey) if len(nextIDs) != 1 || nextIDs[0] == "" { t.Fatalf("next-cycle settlement id missing: %v", nextIDs) @@ -757,9 +757,9 @@ func TestHostSalaryHalfMonthSettlementUsesPolicyMode(t *testing.T) { if result.ProcessedCount != 1 || result.SuccessCount != 1 || result.FailureCount != 0 { t.Fatalf("half-month settlement result mismatch: %+v", result) } - assertBalance(t, svc, 10003, ledger.AssetUSDBalance, 150) + assertBalance(t, svc, 10003, ledger.AssetHostSalaryUSD, 150) assertBalance(t, svc, 10003, ledger.AssetCoin, 90) - assertBalance(t, svc, 30002, ledger.AssetUSDBalance, 50) + assertBalance(t, svc, 30002, ledger.AssetAgencySalaryUSD, 50) if ids := repository.HostSalarySettlementIDs(10003, receipt.HostPeriodCycleKey); len(ids) != 1 || ids[0] == "" { t.Fatalf("half-month settlement id missing: %v", ids) } @@ -2499,36 +2499,6 @@ func TestEquipUserResourceRequiresActiveEquipableEntitlement(t *testing.T) { } } -// TestApplyWithdrawalFreezesUSDBalance 验证提现申请只创建待审核事实,并把可提现美元余额转入冻结。 -func TestApplyWithdrawalFreezesUSDBalance(t *testing.T) { - repository := mysqltest.NewRepository(t) - repository.SetAssetBalance(50001, ledger.AssetUSDBalance, 3000) - svc := walletservice.New(repository) - - withdrawal, balance, err := svc.ApplyWithdrawal(context.Background(), ledger.WithdrawalCommand{ - CommandID: "cmd-withdraw-usd", - UserID: 50001, - Amount: 1200, - PayoutAccount: "paypal:host@example.com", - Reason: "host payout", - }) - if err != nil { - t.Fatalf("ApplyWithdrawal failed: %v", err) - } - if withdrawal.WithdrawalID == "" || withdrawal.Status != ledger.WithdrawalStatusPending || withdrawal.Amount != 1200 { - t.Fatalf("withdrawal response mismatch: %+v", withdrawal) - } - if balance.AvailableAmount != 1800 || balance.FrozenAmount != 1200 { - t.Fatalf("withdrawal balance mismatch: %+v", balance) - } - if got := repository.CountRows("wallet_withdrawal_requests", "user_id = ? AND status = ?", int64(50001), ledger.WithdrawalStatusPending); got != 1 { - t.Fatalf("withdrawal request should be persisted once, got %d", got) - } - if got := repository.CountRows("wallet_transactions", "command_id = ? AND biz_type = ?", "cmd-withdraw-usd", "withdrawal_apply"); got != 1 { - t.Fatalf("withdrawal should write one transaction, got %d", got) - } -} - // TestPurchaseVipDebitsCoinAndGrantsReward 验证 VIP 购买在同一账务事务中扣金币、更新会员和发权益。 func TestPurchaseVipDebitsCoinAndGrantsReward(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -2845,7 +2815,7 @@ func TestWalletOverviewDisablesDiamondExchange(t *testing.T) { if err != nil { t.Fatalf("GetWalletOverview failed: %v", err) } - if !overview.FeatureFlags.RechargeEnabled || overview.FeatureFlags.DiamondExchangeEnabled || !overview.FeatureFlags.WithdrawEnabled { + if !overview.FeatureFlags.RechargeEnabled || overview.FeatureFlags.DiamondExchangeEnabled { t.Fatalf("wallet feature flags mismatch: %+v", overview.FeatureFlags) } if balanceAmount(overview.Balances, ledger.AssetCoin) != 700 || balanceAmount(overview.Balances, "DIAMOND") != 0 { diff --git a/services/wallet-service/internal/storage/mysql/app_wallet_repository.go b/services/wallet-service/internal/storage/mysql/app_wallet_repository.go index 100bece9..ed0e1620 100644 --- a/services/wallet-service/internal/storage/mysql/app_wallet_repository.go +++ b/services/wallet-service/internal/storage/mysql/app_wallet_repository.go @@ -16,15 +16,21 @@ import ( ) const ( - bizTypeWithdrawalApply = "withdrawal_apply" - bizTypeVIPPurchase = "vip_purchase" - bizTypeVIPGrant = "vip_grant" - vipOutboxAsset = "VIP" + bizTypeVIPPurchase = "vip_purchase" + bizTypeVIPGrant = "vip_grant" + vipOutboxAsset = "VIP" ) // GetWalletOverview 返回钱包首页摘要;开关放在 wallet-service 内,避免 gateway 硬编码账务能力。 func (r *Repository) GetWalletOverview(ctx context.Context, userID int64) (ledger.WalletOverview, error) { - balances, err := r.GetBalances(ctx, userID, []string{ledger.AssetCoin, ledger.AssetUSDBalance}) + // 钱包首页返回所有可展示的资金口袋;工资钱包按身份拆分,0 余额也返回,便于客户端固定布局。 + balances, err := r.GetBalances(ctx, userID, []string{ + ledger.AssetCoin, + ledger.AssetHostSalaryUSD, + ledger.AssetAgencySalaryUSD, + ledger.AssetBDSalaryUSD, + ledger.AssetAdminSalaryUSD, + }) if err != nil { return ledger.WalletOverview{}, err } @@ -33,7 +39,6 @@ func (r *Repository) GetWalletOverview(ctx context.Context, userID int64) (ledge FeatureFlags: ledger.WalletFeatureFlags{ RechargeEnabled: true, DiamondExchangeEnabled: false, - WithdrawEnabled: true, }, }, nil } @@ -196,124 +201,6 @@ func (r *Repository) ListWalletTransactions(ctx context.Context, query ledger.Li return items, total, rows.Err() } -// ApplyWithdrawal 冻结 USD_BALANCE 并写待审核提现申请。后台审核和人工转账是后续独立命令。 -func (r *Repository) ApplyWithdrawal(ctx context.Context, command ledger.WithdrawalCommand) (ledger.WithdrawalRequest, ledger.AssetBalance, error) { - if r == nil || r.db == nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") - } - ctx = contextWithCommandApp(ctx, command.AppCode) - command.AppCode = appcode.FromContext(ctx) - - tx, err := r.db.BeginTx(ctx, nil) - if err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - defer func() { _ = tx.Rollback() }() - - requestHash := stableHash(fmt.Sprintf("withdrawal|%s|%d|%d|%s", command.AppCode, command.UserID, command.Amount, command.PayoutAccount)) - if txRow, exists, err := r.lookupTransaction(ctx, tx, command.CommandID, requestHash, bizTypeWithdrawalApply); err != nil || exists { - if err != nil || !exists { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - withdrawal, balance, receiptErr := r.withdrawalReceiptForTransaction(ctx, tx, txRow.TransactionID, command.UserID) - return withdrawal, balance, receiptErr - } - - nowMs := time.Now().UnixMilli() - account, err := r.lockAccount(ctx, tx, command.UserID, ledger.AssetUSDBalance, false, nowMs) - if err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - if account.AvailableAmount < command.Amount { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") - } - transactionID := transactionID(command.AppCode, command.CommandID) - withdrawalID := "wdr_" + stableHash(command.AppCode+"|"+command.CommandID) - availableAfter := account.AvailableAmount - command.Amount - frozenAfter := account.FrozenAmount + command.Amount - metadata := map[string]any{ - "app_code": command.AppCode, - "withdrawal_id": withdrawalID, - "user_id": command.UserID, - "asset_type": ledger.AssetUSDBalance, - "amount": command.Amount, - "payout_account": command.PayoutAccount, - "reason": command.Reason, - } - if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeWithdrawalApply, requestHash, withdrawalID, metadata, nowMs); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - if err := r.applyAccountDelta(ctx, tx, account, -command.Amount, command.Amount, nowMs); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - if err := r.insertEntry(ctx, tx, walletEntry{ - TransactionID: transactionID, - UserID: command.UserID, - AssetType: ledger.AssetUSDBalance, - AvailableDelta: -command.Amount, - FrozenDelta: command.Amount, - AvailableAfter: availableAfter, - FrozenAfter: frozenAfter, - CreatedAtMS: nowMs, - }); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - withdrawal := ledger.WithdrawalRequest{ - WithdrawalID: withdrawalID, - UserID: command.UserID, - AssetType: ledger.AssetUSDBalance, - Amount: command.Amount, - Status: ledger.WithdrawalStatusPending, - PayoutAccount: command.PayoutAccount, - Reason: command.Reason, - CreatedAtMS: nowMs, - UpdatedAtMS: nowMs, - } - if _, err := tx.ExecContext(ctx, ` - INSERT INTO wallet_withdrawal_requests ( - app_code, withdrawal_id, command_id, user_id, asset_type, amount, status, - payout_account, reason, wallet_transaction_id, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - command.AppCode, withdrawal.WithdrawalID, command.CommandID, command.UserID, withdrawal.AssetType, - withdrawal.Amount, withdrawal.Status, withdrawal.PayoutAccount, withdrawal.Reason, transactionID, nowMs, nowMs, - ); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ - balanceChangedEvent(transactionID, command.CommandID, command.UserID, ledger.AssetUSDBalance, -command.Amount, command.Amount, availableAfter, frozenAfter, account.Version+1, metadata, nowMs), - }); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - if err := tx.Commit(); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - - return withdrawal, ledger.AssetBalance{ - AppCode: command.AppCode, - UserID: command.UserID, - AssetType: ledger.AssetUSDBalance, - AvailableAmount: availableAfter, - FrozenAmount: frozenAfter, - Version: account.Version + 1, - UpdatedAtMs: nowMs, - }, nil -} - -func (r *Repository) withdrawalReceiptForTransaction(ctx context.Context, tx *sql.Tx, transactionID string, userID int64) (ledger.WithdrawalRequest, ledger.AssetBalance, error) { - row := tx.QueryRowContext(ctx, ` - SELECT withdrawal_id, user_id, asset_type, amount, status, payout_account, reason, created_at_ms, updated_at_ms - FROM wallet_withdrawal_requests - WHERE app_code = ? AND wallet_transaction_id = ?`, - appcode.FromContext(ctx), transactionID, - ) - var withdrawal ledger.WithdrawalRequest - if err := row.Scan(&withdrawal.WithdrawalID, &withdrawal.UserID, &withdrawal.AssetType, &withdrawal.Amount, &withdrawal.Status, &withdrawal.PayoutAccount, &withdrawal.Reason, &withdrawal.CreatedAtMS, &withdrawal.UpdatedAtMS); err != nil { - return ledger.WithdrawalRequest{}, ledger.AssetBalance{}, err - } - balance, err := r.balanceAfterTransaction(ctx, tx, transactionID, userID, ledger.AssetUSDBalance) - return withdrawal, balance, err -} - // GetMyVip 返回用户当前 VIP 状态;过期只影响 active 投影,不直接修改历史事实。 func (r *Repository) GetMyVip(ctx context.Context, userID int64) (ledger.UserVip, error) { if r == nil || r.db == nil { diff --git a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go index 0b444a34..ff3603ff 100644 --- a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go +++ b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go @@ -57,6 +57,8 @@ type hostSalarySettlementMetadata struct { HostUSDBalanceAfter int64 `json:"host_usd_balance_after"` HostCoinBalanceAfter int64 `json:"host_coin_balance_after"` AgencyUSDBalanceAfter int64 `json:"agency_usd_balance_after"` + HostSalaryAssetType string `json:"host_salary_asset_type"` + AgencySalaryAssetType string `json:"agency_salary_asset_type"` SettledLevelNo int `json:"settled_level_no"` SettledHostSalaryUSDMinor int64 `json:"settled_host_salary_usd_minor"` SettledHostCoinReward int64 `json:"settled_host_coin_reward"` @@ -262,6 +264,8 @@ func (r *Repository) processHostSalaryCandidate(ctx context.Context, command led HostCoinRewardDelta: hostCoinDelta, AgencySalaryUSDMinorDelta: agencyPaidDelta, ResidualUSDMinorDelta: residualDelta, + HostSalaryAssetType: ledger.AssetHostSalaryUSD, + AgencySalaryAssetType: ledger.AssetAgencySalaryUSD, SettledLevelNo: nextProgress.SettledLevelNo, SettledHostSalaryUSDMinor: nextProgress.SettledHostSalaryUSDMinor, SettledHostCoinReward: nextProgress.SettledHostCoinReward, @@ -407,12 +411,13 @@ func (r *Repository) applyHostSalaryCredits(ctx context.Context, tx *sql.Tx, tra // 主播美元、主播金币、代理美元共用同一 transaction_id,确保账务上可视为一次工资结算。 events := make([]walletOutboxEvent, 0, 3) if hostUSDDelta > 0 { - balanceAfter, version, err := r.creditSettlementAsset(ctx, tx, transactionID, metadata.HostUserID, ledger.AssetUSDBalance, hostUSDDelta, 0, nowMs) + // 主播工资和月底剩余钻石折美元只进入主播工资钱包,不混入代理或团队工资钱包。 + balanceAfter, version, err := r.creditSettlementAsset(ctx, tx, transactionID, metadata.HostUserID, ledger.AssetHostSalaryUSD, hostUSDDelta, 0, nowMs) if err != nil { return nil, err } metadata.HostUSDBalanceAfter = balanceAfter - events = append(events, balanceChangedEvent(transactionID, commandID, metadata.HostUserID, ledger.AssetUSDBalance, hostUSDDelta, 0, balanceAfter, 0, version, metadata, nowMs)) + events = append(events, balanceChangedEvent(transactionID, commandID, metadata.HostUserID, ledger.AssetHostSalaryUSD, hostUSDDelta, 0, balanceAfter, 0, version, metadata, nowMs)) } if hostCoinDelta > 0 { balanceAfter, version, err := r.creditSettlementAsset(ctx, tx, transactionID, metadata.HostUserID, ledger.AssetCoin, hostCoinDelta, 0, nowMs) @@ -423,12 +428,13 @@ func (r *Repository) applyHostSalaryCredits(ctx context.Context, tx *sql.Tx, tra events = append(events, balanceChangedEvent(transactionID, commandID, metadata.HostUserID, ledger.AssetCoin, hostCoinDelta, 0, balanceAfter, 0, version, metadata, nowMs)) } if agencyUSDDelta > 0 { - balanceAfter, version, err := r.creditSettlementAsset(ctx, tx, transactionID, metadata.AgencyOwnerUserID, ledger.AssetUSDBalance, agencyUSDDelta, metadata.HostUserID, nowMs) + // 代理工资进入代理工资钱包,同一用户若同时是主播也不会和主播工资钱包合并。 + balanceAfter, version, err := r.creditSettlementAsset(ctx, tx, transactionID, metadata.AgencyOwnerUserID, ledger.AssetAgencySalaryUSD, agencyUSDDelta, metadata.HostUserID, nowMs) if err != nil { return nil, err } metadata.AgencyUSDBalanceAfter = balanceAfter - events = append(events, balanceChangedEvent(transactionID, commandID, metadata.AgencyOwnerUserID, ledger.AssetUSDBalance, agencyUSDDelta, 0, balanceAfter, 0, version, metadata, nowMs)) + events = append(events, balanceChangedEvent(transactionID, commandID, metadata.AgencyOwnerUserID, ledger.AssetAgencySalaryUSD, agencyUSDDelta, 0, balanceAfter, 0, version, metadata, nowMs)) } return events, nil } diff --git a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go index 7e14b9a7..5f9c3340 100644 --- a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go @@ -534,7 +534,7 @@ func validateTableName(table string) string { case "wallet_transactions", "wallet_entries", "wallet_outbox", "wallet_accounts", "wallet_recharge_records", "host_period_diamond_accounts", "host_period_diamond_entries", "host_agency_salary_policies", "host_agency_salary_policy_levels", "host_salary_settlement_progress", "host_salary_settlement_records", - "coin_seller_stock_records", "gift_diamond_ratio_configs", "wallet_diamond_exchange_rules", "wallet_withdrawal_requests", + "coin_seller_stock_records", "gift_diamond_ratio_configs", "wallet_diamond_exchange_rules", "vip_levels", "user_vip_memberships", "vip_purchase_orders", "user_vip_history", "resources", "resource_groups", "resource_group_items", "resource_shop_items", "resource_shop_purchase_orders", "gift_type_configs", "gift_configs", "gift_config_regions", "user_gift_wall", "wallet_projection_events", "resource_grants", "resource_grant_items", "user_resource_entitlements", "user_resource_equipment": diff --git a/services/wallet-service/internal/transport/grpc/server.go b/services/wallet-service/internal/transport/grpc/server.go index 205167bf..0f4263f4 100644 --- a/services/wallet-service/internal/transport/grpc/server.go +++ b/services/wallet-service/internal/transport/grpc/server.go @@ -329,26 +329,6 @@ func (s *Server) ListWalletTransactions(ctx context.Context, req *walletv1.ListW return resp, nil } -// ApplyWithdrawal 创建提现申请并冻结美元余额。 -func (s *Server) ApplyWithdrawal(ctx context.Context, req *walletv1.ApplyWithdrawalRequest) (*walletv1.ApplyWithdrawalResponse, error) { - ctx = appcode.WithContext(ctx, req.GetAppCode()) - withdrawal, balance, err := s.svc.ApplyWithdrawal(ctx, ledger.WithdrawalCommand{ - AppCode: req.GetAppCode(), - CommandID: req.GetCommandId(), - UserID: req.GetUserId(), - Amount: req.GetAmount(), - PayoutAccount: req.GetPayoutAccount(), - Reason: req.GetReason(), - }) - if err != nil { - return nil, xerr.ToGRPCError(err) - } - return &walletv1.ApplyWithdrawalResponse{ - Withdrawal: withdrawalToProto(withdrawal), - Balance: balanceToProto(balance), - }, nil -} - // ListVipPackages 返回当前 VIP 和可购买包列表。 func (s *Server) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) @@ -562,21 +542,6 @@ func walletFeatureFlagsToProto(flags ledger.WalletFeatureFlags) *walletv1.Wallet return &walletv1.WalletFeatureFlags{ RechargeEnabled: flags.RechargeEnabled, DiamondExchangeEnabled: flags.DiamondExchangeEnabled, - WithdrawEnabled: flags.WithdrawEnabled, - } -} - -func withdrawalToProto(withdrawal ledger.WithdrawalRequest) *walletv1.WithdrawalRequest { - return &walletv1.WithdrawalRequest{ - WithdrawalId: withdrawal.WithdrawalID, - UserId: withdrawal.UserID, - AssetType: withdrawal.AssetType, - Amount: withdrawal.Amount, - Status: withdrawal.Status, - PayoutAccount: withdrawal.PayoutAccount, - Reason: withdrawal.Reason, - CreatedAtMs: withdrawal.CreatedAtMS, - UpdatedAtMs: withdrawal.UpdatedAtMS, } } From dc28441e1b9950c9a8f7673173311dcbe759f01d Mon Sep 17 00:00:00 2001 From: zhx Date: Wed, 3 Jun 2026 00:05:38 +0800 Subject: [PATCH 03/28] fix: use lucky gift stats for admin summary --- .../storage/mysql/lucky_gift_repository.go | 41 +++++++++++++------ .../mysql/lucky_gift_repository_test.go | 17 ++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go index 1c37c011..12962498 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go @@ -663,6 +663,9 @@ type luckyDrawPoolStatDelta struct { BaseRewardCoins int64 RoomAtmosphereRewardCoins int64 ActivitySubsidyCoins int64 + PendingDraws int64 + GrantedDraws int64 + FailedDraws int64 UserIDs map[int64]struct{} RoomIDs map[string]struct{} } @@ -713,14 +716,17 @@ func (r *Repository) upsertLuckyDrawPoolStatsSnapshotDelta(ctx context.Context, unique_users = unique_users + VALUES(unique_users), unique_rooms = unique_rooms + VALUES(unique_rooms), total_spent_coins = total_spent_coins + VALUES(total_spent_coins), - total_reward_coins = total_reward_coins + VALUES(total_reward_coins), - base_reward_coins = base_reward_coins + VALUES(base_reward_coins), - room_atmosphere_reward_coins = room_atmosphere_reward_coins + VALUES(room_atmosphere_reward_coins), - activity_subsidy_coins = activity_subsidy_coins + VALUES(activity_subsidy_coins), - updated_at_ms = VALUES(updated_at_ms)`, + total_reward_coins = total_reward_coins + VALUES(total_reward_coins), + base_reward_coins = base_reward_coins + VALUES(base_reward_coins), + room_atmosphere_reward_coins = room_atmosphere_reward_coins + VALUES(room_atmosphere_reward_coins), + activity_subsidy_coins = activity_subsidy_coins + VALUES(activity_subsidy_coins), + pending_draws = pending_draws + VALUES(pending_draws), + granted_draws = granted_draws + VALUES(granted_draws), + failed_draws = failed_draws + VALUES(failed_draws), + updated_at_ms = VALUES(updated_at_ms)`, key.AppCode, key.PoolID, key.GiftID, delta.TotalDraws, uniqueUsers, uniqueRooms, delta.TotalSpentCoins, delta.TotalRewardCoins, delta.BaseRewardCoins, delta.RoomAtmosphereRewardCoins, delta.ActivitySubsidyCoins, - int64(0), int64(0), int64(0), nowMS, nowMS, + delta.PendingDraws, delta.GrantedDraws, delta.FailedDraws, nowMS, nowMS, ) return err } @@ -742,6 +748,7 @@ type luckyDrawStatsRecord struct { BaseRewardCoins int64 RoomAtmosphereRewardCoins int64 ActivitySubsidyCoins int64 + RewardStatus string CreatedAtMS int64 } @@ -775,7 +782,8 @@ func (r *Repository) RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, no rows, err := tx.QueryContext(ctx, ` SELECT app_code, draw_id, pool_id, gift_id, user_id, room_id, coin_spent, - total_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + effective_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + reward_status, created_at_ms FROM lucky_draw_records FORCE INDEX (idx_lucky_draw_created) WHERE app_code = ? @@ -791,7 +799,7 @@ func (r *Repository) RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, no var record luckyDrawStatsRecord if err := rows.Scan(&record.AppCode, &record.DrawID, &record.PoolID, &record.GiftID, &record.UserID, &record.RoomID, &record.TotalSpentCoins, &record.TotalRewardCoins, &record.BaseRewardCoins, - &record.RoomAtmosphereRewardCoins, &record.ActivitySubsidyCoins, &record.CreatedAtMS); err != nil { + &record.RoomAtmosphereRewardCoins, &record.ActivitySubsidyCoins, &record.RewardStatus, &record.CreatedAtMS); err != nil { return 0, err } records = append(records, record) @@ -824,6 +832,14 @@ func (r *Repository) RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, no delta.BaseRewardCoins += record.BaseRewardCoins delta.RoomAtmosphereRewardCoins += record.RoomAtmosphereRewardCoins delta.ActivitySubsidyCoins += record.ActivitySubsidyCoins + switch record.RewardStatus { + case domain.StatusPending: + delta.PendingDraws++ + case domain.StatusGranted: + delta.GrantedDraws++ + case domain.StatusFailed: + delta.FailedDraws++ + } if record.UserID > 0 { delta.UserIDs[record.UserID] = struct{}{} } @@ -1818,7 +1834,8 @@ func (r *Repository) getLuckyGiftDrawSummaryFromStats(ctx context.Context, query summary.PoolID = query.PoolID err := r.db.QueryRowContext(ctx, ` SELECT total_draws, unique_users, unique_rooms, total_spent_coins, total_reward_coins, - base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins + base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + pending_draws, granted_draws, failed_draws FROM lucky_draw_pool_stats WHERE app_code = ? AND pool_id = ? AND gift_id = ?`, appcode.FromContext(ctx), query.PoolID, strings.TrimSpace(query.GiftID), @@ -1831,6 +1848,9 @@ func (r *Repository) getLuckyGiftDrawSummaryFromStats(ctx context.Context, query &summary.BaseRewardCoins, &summary.RoomAtmosphereRewardCoins, &summary.ActivitySubsidyCoins, + &summary.PendingDraws, + &summary.GrantedDraws, + &summary.FailedDraws, ) if errors.Is(err, sql.ErrNoRows) { return summary, nil @@ -1838,9 +1858,6 @@ func (r *Repository) getLuckyGiftDrawSummaryFromStats(ctx context.Context, query if err != nil { return domain.DrawSummary{}, err } - if err := r.loadLuckyGiftDrawStatusCounts(ctx, query, &summary); err != nil { - return domain.DrawSummary{}, err - } if summary.TotalSpentCoins > 0 { summary.ActualRTPPPM = summary.TotalRewardCoins * luckyPPMScale / summary.TotalSpentCoins } diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go index a2cb3aa0..e8909bd6 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go @@ -115,6 +115,7 @@ func TestRefreshLuckyGiftAdminStatsSnapshotsAdvancesCursorByBatch(t *testing.T) t.Fatalf("first refresh should process one row, got %d", processed) } assertLuckyStatsTotal(t, repository, "", 1, 100, 300) + assertLuckyStatsStatus(t, repository, "", 0, 1, 0) assertLuckyStatsCursor(t, repository, 100, "draw_001") processed, err = repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, 400, 10) @@ -125,6 +126,7 @@ func TestRefreshLuckyGiftAdminStatsSnapshotsAdvancesCursorByBatch(t *testing.T) t.Fatalf("second refresh should process remaining row, got %d", processed) } assertLuckyStatsTotal(t, repository, "", 2, 250, 300) + assertLuckyStatsStatus(t, repository, "", 1, 1, 0) assertLuckyStatsCursor(t, repository, 200, "draw_002") } @@ -166,6 +168,21 @@ func assertLuckyStatsTotal(t *testing.T, repository *Repository, giftID string, } } +func assertLuckyStatsStatus(t *testing.T, repository *Repository, giftID string, wantPending int64, wantGranted int64, wantFailed int64) { + t.Helper() + var pending, granted, failed int64 + if err := repository.db.QueryRowContext(context.Background(), ` + SELECT pending_draws, granted_draws, failed_draws + FROM lucky_draw_pool_stats + WHERE app_code = 'lalu' AND pool_id = 'lucky' AND gift_id = ?`, giftID, + ).Scan(&pending, &granted, &failed); err != nil { + t.Fatalf("read stats status: %v", err) + } + if pending != wantPending || granted != wantGranted || failed != wantFailed { + t.Fatalf("stats status mismatch: pending=%d granted=%d failed=%d want pending=%d granted=%d failed=%d", pending, granted, failed, wantPending, wantGranted, wantFailed) + } +} + func assertLuckyStatsCursor(t *testing.T, repository *Repository, wantCreatedAtMS int64, wantDrawID string) { t.Helper() var createdAtMS int64 From 155b159c831760770875ebcc736fb3e0e5e16f7f Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 11:24:07 +0800 Subject: [PATCH 04/28] fix: optimize game level outbox claiming --- .../deploy/mysql/initdb/001_game_service.sql | 1 + .../internal/storage/mysql/repository.go | 177 ++++++++++++++++-- .../internal/storage/mysql/repository_test.go | 103 ++++++++++ 3 files changed, 262 insertions(+), 19 deletions(-) diff --git a/services/game-service/deploy/mysql/initdb/001_game_service.sql b/services/game-service/deploy/mysql/initdb/001_game_service.sql index 934660af..39976f52 100644 --- a/services/game-service/deploy/mysql/initdb/001_game_service.sql +++ b/services/game-service/deploy/mysql/initdb/001_game_service.sql @@ -169,6 +169,7 @@ CREATE TABLE IF NOT EXISTS game_level_event_outbox ( UNIQUE KEY uk_game_level_event_order(app_code, order_id), KEY idx_game_level_event_pending(app_code, status, next_retry_at_ms, created_at_ms), KEY idx_game_level_event_claim(app_code, status, locked_until_ms, next_retry_at_ms, created_at_ms, event_id), + KEY idx_game_level_event_claim_order(app_code, status, locked_until_ms, created_at_ms, event_id, next_retry_at_ms), KEY idx_game_level_event_retention(app_code, status, updated_at_ms, event_id), KEY idx_game_level_event_user(app_code, user_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏等级事件 outbox 表'; diff --git a/services/game-service/internal/storage/mysql/repository.go b/services/game-service/internal/storage/mysql/repository.go index cc8ce4bb..b62cddba 100644 --- a/services/game-service/internal/storage/mysql/repository.go +++ b/services/game-service/internal/storage/mysql/repository.go @@ -216,6 +216,7 @@ func (r *Repository) Migrate(ctx context.Context) error { UNIQUE KEY uk_game_level_event_order(app_code, order_id), KEY idx_game_level_event_pending(app_code, status, next_retry_at_ms, created_at_ms), KEY idx_game_level_event_claim(app_code, status, locked_until_ms, next_retry_at_ms, created_at_ms, event_id), + KEY idx_game_level_event_claim_order(app_code, status, locked_until_ms, created_at_ms, event_id, next_retry_at_ms), KEY idx_game_level_event_retention(app_code, status, updated_at_ms, event_id), KEY idx_game_level_event_user(app_code, user_id, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, @@ -286,6 +287,12 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureIndexDefinition(ctx, "game_outbox", "idx_game_outbox_retention", []string{"app_code", "status", "updated_at_ms", "event_id"}, "ALTER TABLE game_outbox ADD INDEX idx_game_outbox_retention(app_code, status, updated_at_ms, event_id)"); err != nil { return err } + if err := r.ensureIndexDefinition(ctx, "game_level_event_outbox", "idx_game_level_event_claim", []string{"app_code", "status", "locked_until_ms", "next_retry_at_ms", "created_at_ms", "event_id"}, "ALTER TABLE game_level_event_outbox ADD INDEX idx_game_level_event_claim(app_code, status, locked_until_ms, next_retry_at_ms, created_at_ms, event_id)"); err != nil { + return err + } + if err := r.ensureIndexDefinition(ctx, "game_level_event_outbox", "idx_game_level_event_claim_order", []string{"app_code", "status", "locked_until_ms", "created_at_ms", "event_id", "next_retry_at_ms"}, "ALTER TABLE game_level_event_outbox ADD INDEX idx_game_level_event_claim_order(app_code, status, locked_until_ms, created_at_ms, event_id, next_retry_at_ms)"); err != nil { + return err + } if err := r.ensureIndexDefinition(ctx, "game_level_event_outbox", "idx_game_level_event_retention", []string{"app_code", "status", "updated_at_ms", "event_id"}, "ALTER TABLE game_level_event_outbox ADD INDEX idx_game_level_event_retention(app_code, status, updated_at_ms, event_id)"); err != nil { return err } @@ -867,6 +874,9 @@ func (r *Repository) ClaimPendingLevelEvents(ctx context.Context, workerID strin if r == nil || r.db == nil { return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") } + if batchSize <= 0 { + return nil, nil + } tx, err := r.db.BeginTx(ctx, nil) if err != nil { return nil, err @@ -874,34 +884,32 @@ func (r *Repository) ClaimPendingLevelEvents(ctx context.Context, workerID strin defer func() { _ = tx.Rollback() }() appCode := appcode.FromContext(ctx) - events, err := r.queryPendingLevelEvents(ctx, tx, ` - WHERE app_code = ? AND status IN ('pending', 'failed') AND next_retry_at_ms <= ? - AND locked_until_ms = 0 - ORDER BY created_at_ms ASC, event_id ASC - LIMIT ? FOR UPDATE SKIP LOCKED`, - appCode, nowMS, batchSize) + // 先用轻量主键查询完成行锁 claim,避免 payload_json 和完整业务列参与排序。 + keys, err := r.queryUnlockedLevelEventClaimKeys(ctx, tx, appCode, nowMS, batchSize) if err != nil { return nil, err } - if remaining := batchSize - len(events); remaining > 0 { - retryEvents, err := r.queryPendingLevelEvents(ctx, tx, ` - WHERE app_code = ? AND status IN ('pending', 'failed') AND next_retry_at_ms <= ? - AND locked_until_ms > 0 AND locked_until_ms <= ? - ORDER BY created_at_ms ASC, event_id ASC - LIMIT ? FOR UPDATE SKIP LOCKED`, - appCode, nowMS, nowMS, remaining) + // 普通未锁事件优先处理;不足一批时再接管锁过期事件,保持原有补偿顺序。 + if remaining := batchSize - len(keys); remaining > 0 { + retryKeys, err := r.queryExpiredLevelEventClaimKeys(ctx, tx, appCode, nowMS, remaining) if err != nil { return nil, err } - events = append(events, retryEvents...) + keys = append(keys, retryKeys...) + } + // 状态更新前按主键回读完整事件,让上层仍拿到 pending/failed 的原始状态和负载。 + events, err := r.fetchLevelEventsByClaimKeys(ctx, tx, appCode, keys) + if err != nil { + return nil, err } lockUntil := nowMS + lockTTL.Milliseconds() - for _, event := range events { + // 只有被本事务锁住且准备返回的事件会切到 running,额外扫描到的候选行随提交释放锁。 + for _, key := range keys { if _, err := tx.ExecContext(ctx, ` UPDATE game_level_event_outbox SET status = 'running', attempt_count = attempt_count + 1, locked_by = ?, locked_until_ms = ?, updated_at_ms = ? WHERE app_code = ? AND event_id = ?`, - workerID, lockUntil, nowMS, appcode.FromContext(ctx), event.EventID, + workerID, lockUntil, nowMS, appCode, key.EventID, ); err != nil { return nil, err } @@ -912,13 +920,144 @@ func (r *Repository) ClaimPendingLevelEvents(ctx context.Context, workerID strin return events, nil } -func (r *Repository) queryPendingLevelEvents(ctx context.Context, tx *sql.Tx, whereSQL string, args ...any) ([]gamedomain.LevelEventOutbox, error) { - rows, err := tx.QueryContext(ctx, levelEventOutboxSelectSQL()+whereSQL, args...) +type levelEventClaimKey struct { + EventID string + CreatedAtMS int64 +} + +func (r *Repository) queryUnlockedLevelEventClaimKeys(ctx context.Context, tx *sql.Tx, appCode string, nowMS int64, batchSize int) ([]levelEventClaimKey, error) { + // status 拆成两个等值查询,避免 MySQL 把 status IN 展开成多段 range 后再 filesort。 + return queryLevelEventClaimKeysByStatus(batchSize, func(status string) ([]levelEventClaimKey, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT event_id, created_at_ms + FROM game_level_event_outbox FORCE INDEX (idx_game_level_event_claim_order) + WHERE app_code = ? AND status = ? AND locked_until_ms = 0 AND next_retry_at_ms <= ? + ORDER BY created_at_ms ASC, event_id ASC + LIMIT ? FOR UPDATE SKIP LOCKED`, + appCode, status, nowMS, batchSize, + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanLevelEventClaimKeys(rows) + }) +} + +func (r *Repository) queryExpiredLevelEventClaimKeys(ctx context.Context, tx *sql.Tx, appCode string, nowMS int64, batchSize int) ([]levelEventClaimKey, error) { + // 过期锁接管仍使用 retry/lock 前缀缩小范围,但只锁主键,避免大 JSON 字段进入排序和慢日志。 + return queryLevelEventClaimKeysByStatus(batchSize, func(status string) ([]levelEventClaimKey, error) { + rows, err := tx.QueryContext(ctx, ` + SELECT event_id, created_at_ms + FROM game_level_event_outbox FORCE INDEX (idx_game_level_event_claim) + WHERE app_code = ? AND status = ? AND next_retry_at_ms <= ? + AND locked_until_ms > 0 AND locked_until_ms <= ? + ORDER BY created_at_ms ASC, event_id ASC + LIMIT ? FOR UPDATE SKIP LOCKED`, + appCode, status, nowMS, nowMS, batchSize, + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanLevelEventClaimKeys(rows) + }) +} + +func queryLevelEventClaimKeysByStatus(batchSize int, query func(status string) ([]levelEventClaimKey, error)) ([]levelEventClaimKey, error) { + statuses := []string{"pending", "failed"} + groups := make([][]levelEventClaimKey, 0, len(statuses)) + for _, status := range statuses { + keys, err := query(status) + if err != nil { + return nil, err + } + groups = append(groups, keys) + } + return mergeLevelEventClaimKeys(batchSize, groups...), nil +} + +func scanLevelEventClaimKeys(rows *sql.Rows) ([]levelEventClaimKey, error) { + keys := make([]levelEventClaimKey, 0) + for rows.Next() { + var key levelEventClaimKey + if err := rows.Scan(&key.EventID, &key.CreatedAtMS); err != nil { + return nil, err + } + keys = append(keys, key) + } + return keys, rows.Err() +} + +func mergeLevelEventClaimKeys(limit int, groups ...[]levelEventClaimKey) []levelEventClaimKey { + if limit <= 0 { + return nil + } + offsets := make([]int, len(groups)) + merged := make([]levelEventClaimKey, 0, limit) + // 每个 status 查询内部已经按 created_at/event_id 排序,这里做小规模归并来维持原 SQL 的跨状态顺序。 + for len(merged) < limit { + bestGroup := -1 + var best levelEventClaimKey + for groupIndex, group := range groups { + offset := offsets[groupIndex] + if offset >= len(group) { + continue + } + candidate := group[offset] + if bestGroup == -1 || levelEventClaimKeyLess(candidate, best) { + bestGroup = groupIndex + best = candidate + } + } + if bestGroup == -1 { + break + } + merged = append(merged, best) + offsets[bestGroup]++ + } + return merged +} + +func levelEventClaimKeyLess(left levelEventClaimKey, right levelEventClaimKey) bool { + if left.CreatedAtMS != right.CreatedAtMS { + return left.CreatedAtMS < right.CreatedAtMS + } + return left.EventID < right.EventID +} + +func (r *Repository) fetchLevelEventsByClaimKeys(ctx context.Context, tx *sql.Tx, appCode string, keys []levelEventClaimKey) ([]gamedomain.LevelEventOutbox, error) { + if len(keys) == 0 { + return nil, nil + } + placeholders := strings.TrimRight(strings.Repeat("?,", len(keys)), ",") + args := make([]any, 0, len(keys)+1) + args = append(args, appCode) + for _, key := range keys { + args = append(args, key.EventID) + } + rows, err := tx.QueryContext(ctx, levelEventOutboxSelectSQL()+`WHERE app_code = ? AND event_id IN (`+placeholders+`)`, args...) if err != nil { return nil, err } defer rows.Close() - return scanLevelEventOutboxRows(rows) + items, err := scanLevelEventOutboxRows(rows) + if err != nil { + return nil, err + } + byID := make(map[string]gamedomain.LevelEventOutbox, len(items)) + for _, item := range items { + byID[item.EventID] = item + } + ordered := make([]gamedomain.LevelEventOutbox, 0, len(keys)) + for _, key := range keys { + item, ok := byID[key.EventID] + if !ok { + return nil, errors.New("claimed level event disappeared before fetch") + } + ordered = append(ordered, item) + } + return ordered, nil } func (r *Repository) MarkLevelEventDelivered(ctx context.Context, eventID string, nowMS int64) error { diff --git a/services/game-service/internal/storage/mysql/repository_test.go b/services/game-service/internal/storage/mysql/repository_test.go index c8923379..80f812b0 100644 --- a/services/game-service/internal/storage/mysql/repository_test.go +++ b/services/game-service/internal/storage/mysql/repository_test.go @@ -2,6 +2,7 @@ package mysql import ( "context" + "strings" "testing" "time" @@ -63,6 +64,108 @@ func TestMarkOrderSucceededCreatesClaimableLevelOutboxEvent(t *testing.T) { } } +func TestClaimPendingLevelEventsPreservesCreatedOrderAcrossStatuses(t *testing.T) { + caller := mysqlschema.CallerFile(t, 1) + schema := mysqlschema.New(t, mysqlschema.Config{ + InitDBPath: mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_game_service.sql"), + DatabasePrefix: "hy_game_test", + }) + + ctx := appcode.WithContext(context.Background(), "lalu") + repo, err := Open(ctx, schema.DSN) + if err != nil { + t.Fatalf("open repository failed: %v", err) + } + t.Cleanup(func() { _ = repo.Close() }) + + insertLevelEvent := func(eventID string, orderID string, status string, nextRetryAtMS int64, createdAtMS int64, payload string) { + t.Helper() + if _, err := repo.db.ExecContext(ctx, ` + INSERT INTO game_level_event_outbox ( + app_code, event_id, order_id, user_id, game_id, provider_order_id, + provider_round_id, coin_amount, wallet_transaction_id, payload_json, + status, attempt_count, next_retry_at_ms, locked_by, locked_until_ms, + failure_reason, occurred_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, 42, 'game_1', ?, '', 100, 'wallet_tx_1', ?, + ?, 0, ?, '', 0, '', ?, ?, ?)`, + "lalu", eventID, orderID, "provider_"+orderID, payload, status, nextRetryAtMS, createdAtMS, createdAtMS, createdAtMS, + ); err != nil { + t.Fatalf("insert level event %s failed: %v", eventID, err) + } + } + insertLevelEvent("event_failed_old", "order_failed_old", "failed", 1000, 1000, `{"source":"failed"}`) + insertLevelEvent("event_failed_future", "order_failed_future", "failed", 999999, 1500, `{"source":"future"}`) + insertLevelEvent("event_pending_new", "order_pending_new", "pending", 0, 2000, `{"source":"pending"}`) + + events, err := repo.ClaimPendingLevelEvents(ctx, "worker_1", 3000, 30*time.Second, 2) + if err != nil { + t.Fatalf("claim level events failed: %v", err) + } + if len(events) != 2 { + t.Fatalf("expected two claimed events, got %+v", events) + } + if events[0].EventID != "event_failed_old" || events[0].Status != "failed" || !strings.Contains(events[0].PayloadJSON, `"source": "failed"`) { + t.Fatalf("first claimed event should be the older failed payload, got %+v", events[0]) + } + if events[1].EventID != "event_pending_new" || events[1].Status != "pending" || !strings.Contains(events[1].PayloadJSON, `"source": "pending"`) { + t.Fatalf("second claimed event should be the pending payload, got %+v", events[1]) + } + + var runningCount int + if err := repo.db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM game_level_event_outbox + WHERE app_code = 'lalu' AND status = 'running' AND locked_by = 'worker_1' AND locked_until_ms = 33000`, + ).Scan(&runningCount); err != nil { + t.Fatalf("query running events failed: %v", err) + } + if runningCount != 2 { + t.Fatalf("expected two running claimed events, got %d", runningCount) + } + var futureStatus string + if err := repo.db.QueryRowContext(ctx, ` + SELECT status FROM game_level_event_outbox WHERE app_code = 'lalu' AND event_id = 'event_failed_future'`, + ).Scan(&futureStatus); err != nil { + t.Fatalf("query future retry event failed: %v", err) + } + if futureStatus != "failed" { + t.Fatalf("future retry event should stay failed, got %s", futureStatus) + } +} + +func TestLevelEventClaimKeyQueryUsesOrderIndexWithoutFilesort(t *testing.T) { + caller := mysqlschema.CallerFile(t, 1) + schema := mysqlschema.New(t, mysqlschema.Config{ + InitDBPath: mysqlschema.InitDBPath(t, caller, "../../../deploy/mysql/initdb/001_game_service.sql"), + DatabasePrefix: "hy_game_test", + }) + + ctx := appcode.WithContext(context.Background(), "lalu") + repo, err := Open(ctx, schema.DSN) + if err != nil { + t.Fatalf("open repository failed: %v", err) + } + t.Cleanup(func() { _ = repo.Close() }) + + var plan string + if err := repo.db.QueryRowContext(ctx, ` + EXPLAIN FORMAT=JSON + SELECT event_id, created_at_ms + FROM game_level_event_outbox FORCE INDEX (idx_game_level_event_claim_order) + WHERE app_code = ? AND status = ? AND locked_until_ms = 0 AND next_retry_at_ms <= ? + ORDER BY created_at_ms ASC, event_id ASC + LIMIT 100`, + "lalu", "pending", int64(1780542672724), + ).Scan(&plan); err != nil { + t.Fatalf("explain level event claim key query failed: %v", err) + } + if !strings.Contains(plan, `"key": "idx_game_level_event_claim_order"`) { + t.Fatalf("claim key query did not use idx_game_level_event_claim_order:\n%s", plan) + } + if strings.Contains(strings.ToLower(plan), `"using_filesort": true`) { + t.Fatalf("claim key query should avoid filesort:\n%s", plan) + } +} + func TestUpsertCatalogCreatesDefaultVoiceRoomDisplayRule(t *testing.T) { caller := mysqlschema.CallerFile(t, 1) schema := mysqlschema.New(t, mysqlschema.Config{ From 802136d47fe62646c00d78024752b556307ef58d Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 13:41:21 +0800 Subject: [PATCH 05/28] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=92=B1=E5=8C=85?= =?UTF-8?q?=E5=85=85=E5=80=BCbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/钱包服务架构.md | 2 +- ...5_wallet_recharge_record_currency_code.sql | 27 +++++++++++++++++++ .../mysql/initdb/001_wallet_service.sql | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 scripts/mysql/035_wallet_recharge_record_currency_code.sql diff --git a/docs/钱包服务架构.md b/docs/钱包服务架构.md index e284f1e7..83e85924 100644 --- a/docs/钱包服务架构.md +++ b/docs/钱包服务架构.md @@ -229,7 +229,7 @@ wallet_recharge_records( target_region_id BIGINT NOT NULL, policy_id BIGINT NOT NULL, policy_version VARCHAR(64) NOT NULL, - currency_code VARCHAR(3) NOT NULL, + currency_code VARCHAR(8) NOT NULL, coin_amount BIGINT NOT NULL, usd_minor_amount BIGINT NOT NULL, exchange_coin_amount BIGINT NOT NULL, diff --git a/scripts/mysql/035_wallet_recharge_record_currency_code.sql b/scripts/mysql/035_wallet_recharge_record_currency_code.sql new file mode 100644 index 00000000..60d0cade --- /dev/null +++ b/scripts/mysql/035_wallet_recharge_record_currency_code.sql @@ -0,0 +1,27 @@ +-- Expand wallet recharge record currency codes so Google Play products such as USDT +-- can be snapshotted before payment order auditing and Google consume. + +SET @wallet_recharge_record_currency_ddl := ( + SELECT CASE + WHEN COUNT(*) = 0 THEN 'SELECT 1' + WHEN MAX(CHARACTER_MAXIMUM_LENGTH) < 8 THEN + 'ALTER TABLE wallet_recharge_records MODIFY COLUMN currency_code VARCHAR(8) NOT NULL COMMENT ''币种编码''' + ELSE 'SELECT 1' + END + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'wallet_recharge_records' + AND COLUMN_NAME = 'currency_code' +); + +PREPARE stmt FROM @wallet_recharge_record_currency_ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT + COLUMN_TYPE AS wallet_recharge_records_currency_code_type, + IS_NULLABLE AS wallet_recharge_records_currency_code_nullable +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'wallet_recharge_records' + AND COLUMN_NAME = 'currency_code'; 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 38d5873e..cc7356b0 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -439,7 +439,7 @@ CREATE TABLE IF NOT EXISTS wallet_recharge_records ( target_region_id BIGINT NOT NULL COMMENT '目标区域 ID', policy_id BIGINT NOT NULL COMMENT '策略 ID', policy_version VARCHAR(64) NOT NULL COMMENT '策略版本', - currency_code VARCHAR(3) NOT NULL COMMENT '币种编码', + currency_code VARCHAR(8) NOT NULL COMMENT '币种编码', coin_amount BIGINT NOT NULL COMMENT '金币数量', usd_minor_amount BIGINT NOT NULL COMMENT '美元最小单位数量', exchange_coin_amount BIGINT NOT NULL COMMENT '兑换金币数量', From 8b2181dee7659a3847469f6b411629b520674f68 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 15:32:43 +0800 Subject: [PATCH 06/28] fix: configure admin refresh cookie same site --- .../admin/configs/config.tencent.example.yaml | 1 + server/admin/configs/config.yaml | 1 + server/admin/internal/config/config.go | 68 +++++++++++-------- server/admin/internal/modules/auth/handler.go | 14 +++- 4 files changed, 56 insertions(+), 28 deletions(-) diff --git a/server/admin/configs/config.tencent.example.yaml b/server/admin/configs/config.tencent.example.yaml index 4acfddce..78edae8a 100644 --- a/server/admin/configs/config.tencent.example.yaml +++ b/server/admin/configs/config.tencent.example.yaml @@ -25,6 +25,7 @@ cors_allowed_origins: - "http://hyapp-platform.global-interaction.com" - "https://hyapp-platform.global-interaction.com" refresh_cookie_secure: true +refresh_cookie_same_site: "none" bootstrap: # 仅首次初始化或显式 -bootstrap 时打开;生产常驻进程不要每次启动重放 seed。 enabled: false diff --git a/server/admin/configs/config.yaml b/server/admin/configs/config.yaml index 26d9be1e..9b4ac1db 100644 --- a/server/admin/configs/config.yaml +++ b/server/admin/configs/config.yaml @@ -26,6 +26,7 @@ cors_allowed_origins: - "http://localhost:7002" - "http://127.0.0.1:7002" refresh_cookie_secure: false +refresh_cookie_same_site: "lax" bootstrap: enabled: true seed_demo_data: true diff --git a/server/admin/internal/config/config.go b/server/admin/internal/config/config.go index 5cc4a248..b0595e31 100644 --- a/server/admin/internal/config/config.go +++ b/server/admin/internal/config/config.go @@ -13,32 +13,33 @@ import ( ) type Config struct { - ServiceName string `yaml:"service_name"` - NodeID string `yaml:"node_id"` - Environment string `yaml:"environment"` - Log logging.Config `yaml:"log"` - HTTPAddr string `yaml:"http_addr"` - MySQLDSN string `yaml:"mysql_dsn"` - UserMySQLDSN string `yaml:"user_mysql_dsn"` - WalletMySQLDSN string `yaml:"wallet_mysql_dsn"` - MySQLAutoMigrate bool `yaml:"mysql_auto_migrate"` - Migrations MigrationConfig `yaml:"migrations"` - JWTSecret string `yaml:"jwt_secret"` - AccessTokenTTL time.Duration `yaml:"access_token_ttl"` - RefreshTokenTTL time.Duration `yaml:"refresh_token_ttl"` - CORSAllowedOrigins []string `yaml:"cors_allowed_origins"` - RefreshCookieSecure bool `yaml:"refresh_cookie_secure"` - Bootstrap BootstrapConfig `yaml:"bootstrap"` - BootstrapPassword string `yaml:"bootstrap_password"` - UserService UserServiceConfig `yaml:"user_service"` - TencentCOS TencentCOSConfig `yaml:"tencent-cos"` - Redis RedisConfig `yaml:"redis"` - Jobs JobsConfig `yaml:"jobs"` - WalletService WalletServiceConfig `yaml:"wallet_service"` - RoomService RoomServiceConfig `yaml:"room_service"` - ActivityService ActivityServiceConfig `yaml:"activity_service"` - GameService GameServiceConfig `yaml:"game_service"` - StatisticsService StatisticsServiceConfig `yaml:"statistics_service"` + ServiceName string `yaml:"service_name"` + NodeID string `yaml:"node_id"` + Environment string `yaml:"environment"` + Log logging.Config `yaml:"log"` + HTTPAddr string `yaml:"http_addr"` + MySQLDSN string `yaml:"mysql_dsn"` + UserMySQLDSN string `yaml:"user_mysql_dsn"` + WalletMySQLDSN string `yaml:"wallet_mysql_dsn"` + MySQLAutoMigrate bool `yaml:"mysql_auto_migrate"` + Migrations MigrationConfig `yaml:"migrations"` + JWTSecret string `yaml:"jwt_secret"` + AccessTokenTTL time.Duration `yaml:"access_token_ttl"` + RefreshTokenTTL time.Duration `yaml:"refresh_token_ttl"` + CORSAllowedOrigins []string `yaml:"cors_allowed_origins"` + RefreshCookieSecure bool `yaml:"refresh_cookie_secure"` + RefreshCookieSameSite string `yaml:"refresh_cookie_same_site"` + Bootstrap BootstrapConfig `yaml:"bootstrap"` + BootstrapPassword string `yaml:"bootstrap_password"` + UserService UserServiceConfig `yaml:"user_service"` + TencentCOS TencentCOSConfig `yaml:"tencent-cos"` + Redis RedisConfig `yaml:"redis"` + Jobs JobsConfig `yaml:"jobs"` + WalletService WalletServiceConfig `yaml:"wallet_service"` + RoomService RoomServiceConfig `yaml:"room_service"` + ActivityService ActivityServiceConfig `yaml:"activity_service"` + GameService GameServiceConfig `yaml:"game_service"` + StatisticsService StatisticsServiceConfig `yaml:"statistics_service"` } type MigrationConfig struct { @@ -135,7 +136,8 @@ func Default() Config { "http://localhost:7001", "http://127.0.0.1:7001", }, - RefreshCookieSecure: false, + RefreshCookieSecure: false, + RefreshCookieSameSite: "lax", Bootstrap: BootstrapConfig{ Enabled: true, SeedDemoData: true, @@ -225,6 +227,10 @@ func (cfg *Config) Normalize() { if cfg.Log.MaxPayloadBytes <= 0 { cfg.Log.MaxPayloadBytes = 2048 } + cfg.RefreshCookieSameSite = strings.ToLower(strings.TrimSpace(cfg.RefreshCookieSameSite)) + if cfg.RefreshCookieSameSite == "" { + cfg.RefreshCookieSameSite = "lax" + } cfg.ServiceName = strings.TrimSpace(cfg.ServiceName) cfg.NodeID = strings.TrimSpace(cfg.NodeID) if cfg.NodeID == "" { @@ -332,6 +338,14 @@ func (cfg Config) Validate() error { if cfg.RefreshTokenTTL <= 0 { return errors.New("refresh_token_ttl must be greater than 0") } + switch strings.ToLower(strings.TrimSpace(cfg.RefreshCookieSameSite)) { + case "lax", "strict", "none": + default: + return errors.New("refresh_cookie_same_site must be one of lax, strict, none") + } + if strings.EqualFold(strings.TrimSpace(cfg.RefreshCookieSameSite), "none") && !cfg.RefreshCookieSecure { + return errors.New("refresh_cookie_secure must be true when refresh_cookie_same_site is none") + } if isLockedEnvironment(cfg.Environment) { if cfg.JWTSecret == "dev-shared-secret" || len(cfg.JWTSecret) < 32 { return errors.New("jwt_secret must be a non-default value with at least 32 characters outside local/dev") diff --git a/server/admin/internal/modules/auth/handler.go b/server/admin/internal/modules/auth/handler.go index c6d20fd3..b4657c31 100644 --- a/server/admin/internal/modules/auth/handler.go +++ b/server/admin/internal/modules/auth/handler.go @@ -2,6 +2,7 @@ package auth import ( "net/http" + "strings" "github.com/gin-gonic/gin" "hyapp-admin-server/internal/config" @@ -112,6 +113,17 @@ func (h *Handler) ChangePassword(c *gin.Context) { } func (h *Handler) setRefreshCookie(c *gin.Context, token string, maxAge int) { - c.SetSameSite(http.SameSiteLaxMode) + c.SetSameSite(refreshCookieSameSite(h.cfg.RefreshCookieSameSite)) c.SetCookie(refreshCookieName, token, maxAge, "/api/v1/auth", "", h.cfg.RefreshCookieSecure, true) } + +func refreshCookieSameSite(value string) http.SameSite { + switch strings.ToLower(strings.TrimSpace(value)) { + case "strict": + return http.SameSiteStrictMode + case "none": + return http.SameSiteNoneMode + default: + return http.SameSiteLaxMode + } +} From 82dfb9238f084a51c8511fb7586320104f4f32a3 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 18:31:06 +0800 Subject: [PATCH 07/28] =?UTF-8?q?=E4=B8=BB=E6=92=AD=E7=BB=93=E7=AE=97?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=92=8C=E6=88=BF=E9=97=B4=E9=94=81=E6=88=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/proto/events/room/v1/events.pb.go | 24 +- api/proto/events/room/v1/events.proto | 2 + api/proto/room/v1/room.pb.go | 909 ++++--- api/proto/room/v1/room.proto | 20 + api/proto/room/v1/room_grpc.pb.go | 38 + api/proto/wallet/v1/wallet.pb.go | 2152 +++++++++++------ api/proto/wallet/v1/wallet.proto | 62 + api/proto/wallet/v1/wallet_grpc.pb.go | 76 + docs/Flutter麦上心跳接口.md | 88 + docs/flutter对接/房间锁房接口Flutter对接.md | 409 ++-- docs/语音房客户端接口流程.md | 40 + .../internal/domain/broadcast/broadcast.go | 2 + .../internal/service/broadcast/service.go | 65 +- .../service/broadcast/service_test.go | 51 + .../internal/client/room_client.go | 5 + .../internal/client/wallet_client.go | 10 + .../transport/http/httproutes/router.go | 6 + .../internal/transport/http/response_test.go | 338 ++- .../transport/http/roomapi/handler.go | 1 + .../transport/http/roomapi/room_handler.go | 21 + .../transport/http/roomapi/room_view.go | 2 + .../transport/http/userapi/handler.go | 2 + .../userapi/host_center_agency_handler.go | 69 + .../userapi/host_center_policy_handler.go | 219 ++ .../internal/integration/tencent_im.go | 6 +- .../internal/integration/tencent_im_test.go | 19 + .../internal/room/command/command.go | 14 + .../internal/room/service/lock_test.go | 22 + .../room-service/internal/room/service/mic.go | 86 + .../internal/room/service/mic_test.go | 112 + .../internal/room/service/presence.go | 10 +- .../internal/room/service/recovery.go | 16 + .../internal/room/service/room_lock.go | 16 +- .../internal/room/service/rtc_event.go | 1 + .../internal/room/service/service.go | 2 + .../room-service/internal/room/state/state.go | 4 + .../internal/transport/grpc/server.go | 12 + .../internal/domain/ledger/ledger.go | 11 + .../internal/service/wallet/service.go | 50 + .../internal/service/wallet/service_test.go | 78 + .../storage/mysql/host_salary_settlement.go | 59 +- .../internal/transport/grpc/server.go | 68 + 42 files changed, 3737 insertions(+), 1460 deletions(-) create mode 100644 docs/Flutter麦上心跳接口.md create mode 100644 services/gateway-service/internal/transport/http/userapi/host_center_agency_handler.go create mode 100644 services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go create mode 100644 services/room-service/internal/room/service/mic_test.go diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index c2234e94..9466dc61 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -875,11 +875,13 @@ func (x *RoomChatEnabledChanged) GetEnabled() bool { // RoomPasswordChanged 表达房间入房密码状态变更,不携带明文或哈希。 type RoomPasswordChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState `protogen:"open.v1"` + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` + // visible_region_id 是房间当前可见区域,activity-service 用它把锁房变化投到区域播报群。 + VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *RoomPasswordChanged) Reset() { @@ -926,6 +928,13 @@ func (x *RoomPasswordChanged) GetLocked() bool { return false } +func (x *RoomPasswordChanged) GetVisibleRegionId() int64 { + if x != nil { + return x.VisibleRegionId + } + return 0 +} + // RoomAdminChanged 表达房间管理员集合变更。 type RoomAdminChanged struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2001,10 +2010,11 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\x06locked\x18\x03 \x01(\bR\x06locked\"V\n" + "\x16RoomChatEnabledChanged\x12\"\n" + "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x18\n" + - "\aenabled\x18\x02 \x01(\bR\aenabled\"Q\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\"}\n" + "\x13RoomPasswordChanged\x12\"\n" + "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x16\n" + - "\x06locked\x18\x02 \x01(\bR\x06locked\"v\n" + + "\x06locked\x18\x02 \x01(\bR\x06locked\x12*\n" + + "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\"v\n" + "\x10RoomAdminChanged\x12\"\n" + "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x18\n" + diff --git a/api/proto/events/room/v1/events.proto b/api/proto/events/room/v1/events.proto index c643063d..2c749ea0 100644 --- a/api/proto/events/room/v1/events.proto +++ b/api/proto/events/room/v1/events.proto @@ -112,6 +112,8 @@ message RoomChatEnabledChanged { message RoomPasswordChanged { int64 actor_user_id = 1; bool locked = 2; + // visible_region_id 是房间当前可见区域,activity-service 用它把锁房变化投到区域播报群。 + int64 visible_region_id = 3; } // RoomAdminChanged 表达房间管理员集合变更。 diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 47853acd..2fca303c 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -368,9 +368,11 @@ type SeatState struct { // mic_muted 是服务端可见的麦克风静音状态,用于同步其他用户 UI。 MicMuted bool `protobuf:"varint,9,opt,name=mic_muted,json=micMuted,proto3" json:"mic_muted,omitempty"` // seat_status 是服务端派生的展示状态:empty/locked/occupied/publishing/muted。 - SeatStatus string `protobuf:"bytes,10,opt,name=seat_status,json=seatStatus,proto3" json:"seat_status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + SeatStatus string `protobuf:"bytes,10,opt,name=seat_status,json=seatStatus,proto3" json:"seat_status,omitempty"` + // mic_heartbeat_at_ms 是当前 mic_session 最近一次服务端接受麦上心跳的 UTC epoch ms。 + MicHeartbeatAtMs int64 `protobuf:"varint,11,opt,name=mic_heartbeat_at_ms,json=micHeartbeatAtMs,proto3" json:"mic_heartbeat_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *SeatState) Reset() { @@ -473,6 +475,13 @@ func (x *SeatState) GetSeatStatus() string { return "" } +func (x *SeatState) GetMicHeartbeatAtMs() int64 { + if x != nil { + return x.MicHeartbeatAtMs + } + return 0 +} + // RankItem 表达房间内本地礼物榜项目。 type RankItem struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -5395,6 +5404,138 @@ func (x *ConfirmMicPublishingResponse) GetRoom() *RoomSnapshot { return nil } +// MicHeartbeatRequest 刷新当前 publishing 麦位会话的服务端麦上心跳。 +type MicHeartbeatRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + // target_user_id 为空时默认刷新 actor_user_id 自己的麦上会话。 + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + // mic_session_id 必须匹配当前麦位上的会话,避免旧心跳续住新会话。 + MicSessionId string `protobuf:"bytes,3,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MicHeartbeatRequest) Reset() { + *x = MicHeartbeatRequest{} + mi := &file_proto_room_v1_room_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MicHeartbeatRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MicHeartbeatRequest) ProtoMessage() {} + +func (x *MicHeartbeatRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_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 MicHeartbeatRequest.ProtoReflect.Descriptor instead. +func (*MicHeartbeatRequest) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} +} + +func (x *MicHeartbeatRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *MicHeartbeatRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *MicHeartbeatRequest) GetMicSessionId() string { + if x != nil { + return x.MicSessionId + } + return "" +} + +// MicHeartbeatResponse 返回刷新后的麦位和房间快照。 +type MicHeartbeatResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` + MicHeartbeatAtMs int64 `protobuf:"varint,4,opt,name=mic_heartbeat_at_ms,json=micHeartbeatAtMs,proto3" json:"mic_heartbeat_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MicHeartbeatResponse) Reset() { + *x = MicHeartbeatResponse{} + mi := &file_proto_room_v1_room_proto_msgTypes[71] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MicHeartbeatResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MicHeartbeatResponse) ProtoMessage() {} + +func (x *MicHeartbeatResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_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 MicHeartbeatResponse.ProtoReflect.Descriptor instead. +func (*MicHeartbeatResponse) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} +} + +func (x *MicHeartbeatResponse) GetResult() *CommandResult { + if x != nil { + return x.Result + } + return nil +} + +func (x *MicHeartbeatResponse) GetSeatNo() int32 { + if x != nil { + return x.SeatNo + } + return 0 +} + +func (x *MicHeartbeatResponse) GetRoom() *RoomSnapshot { + if x != nil { + return x.Room + } + return nil +} + +func (x *MicHeartbeatResponse) GetMicHeartbeatAtMs() int64 { + if x != nil { + return x.MicHeartbeatAtMs + } + return 0 +} + // SetMicMuteRequest 修改麦位上的服务端可见静音态。 type SetMicMuteRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -5408,7 +5549,7 @@ type SetMicMuteRequest struct { func (x *SetMicMuteRequest) Reset() { *x = SetMicMuteRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5420,7 +5561,7 @@ func (x *SetMicMuteRequest) String() string { func (*SetMicMuteRequest) ProtoMessage() {} func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5433,7 +5574,7 @@ func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteRequest.ProtoReflect.Descriptor instead. func (*SetMicMuteRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} } func (x *SetMicMuteRequest) GetMeta() *RequestMeta { @@ -5469,7 +5610,7 @@ type SetMicMuteResponse struct { func (x *SetMicMuteResponse) Reset() { *x = SetMicMuteResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5481,7 +5622,7 @@ func (x *SetMicMuteResponse) String() string { func (*SetMicMuteResponse) ProtoMessage() {} func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5494,7 +5635,7 @@ func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteResponse.ProtoReflect.Descriptor instead. func (*SetMicMuteResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} } func (x *SetMicMuteResponse) GetResult() *CommandResult { @@ -5535,7 +5676,7 @@ type ApplyRTCEventRequest struct { func (x *ApplyRTCEventRequest) Reset() { *x = ApplyRTCEventRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5547,7 +5688,7 @@ func (x *ApplyRTCEventRequest) String() string { func (*ApplyRTCEventRequest) ProtoMessage() {} func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5560,7 +5701,7 @@ func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventRequest.ProtoReflect.Descriptor instead. func (*ApplyRTCEventRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} } func (x *ApplyRTCEventRequest) GetMeta() *RequestMeta { @@ -5624,7 +5765,7 @@ type ApplyRTCEventResponse struct { func (x *ApplyRTCEventResponse) Reset() { *x = ApplyRTCEventResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5636,7 +5777,7 @@ func (x *ApplyRTCEventResponse) String() string { func (*ApplyRTCEventResponse) ProtoMessage() {} func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5649,7 +5790,7 @@ func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventResponse.ProtoReflect.Descriptor instead. func (*ApplyRTCEventResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} } func (x *ApplyRTCEventResponse) GetResult() *CommandResult { @@ -5685,7 +5826,7 @@ type SetMicSeatLockRequest struct { func (x *SetMicSeatLockRequest) Reset() { *x = SetMicSeatLockRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5697,7 +5838,7 @@ func (x *SetMicSeatLockRequest) String() string { func (*SetMicSeatLockRequest) ProtoMessage() {} func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5710,7 +5851,7 @@ func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockRequest.ProtoReflect.Descriptor instead. func (*SetMicSeatLockRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} } func (x *SetMicSeatLockRequest) GetMeta() *RequestMeta { @@ -5745,7 +5886,7 @@ type SetMicSeatLockResponse struct { func (x *SetMicSeatLockResponse) Reset() { *x = SetMicSeatLockResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5757,7 +5898,7 @@ func (x *SetMicSeatLockResponse) String() string { func (*SetMicSeatLockResponse) ProtoMessage() {} func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5770,7 +5911,7 @@ func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockResponse.ProtoReflect.Descriptor instead. func (*SetMicSeatLockResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} } func (x *SetMicSeatLockResponse) GetResult() *CommandResult { @@ -5798,7 +5939,7 @@ type SetChatEnabledRequest struct { func (x *SetChatEnabledRequest) Reset() { *x = SetChatEnabledRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5810,7 +5951,7 @@ func (x *SetChatEnabledRequest) String() string { func (*SetChatEnabledRequest) ProtoMessage() {} func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5823,7 +5964,7 @@ func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledRequest.ProtoReflect.Descriptor instead. func (*SetChatEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} } func (x *SetChatEnabledRequest) GetMeta() *RequestMeta { @@ -5851,7 +5992,7 @@ type SetChatEnabledResponse struct { func (x *SetChatEnabledResponse) Reset() { *x = SetChatEnabledResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5863,7 +6004,7 @@ func (x *SetChatEnabledResponse) String() string { func (*SetChatEnabledResponse) ProtoMessage() {} func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5876,7 +6017,7 @@ func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledResponse.ProtoReflect.Descriptor instead. func (*SetChatEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} } func (x *SetChatEnabledResponse) GetResult() *CommandResult { @@ -5906,7 +6047,7 @@ type SetRoomPasswordRequest struct { func (x *SetRoomPasswordRequest) Reset() { *x = SetRoomPasswordRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5918,7 +6059,7 @@ func (x *SetRoomPasswordRequest) String() string { func (*SetRoomPasswordRequest) ProtoMessage() {} func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5931,7 +6072,7 @@ func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordRequest.ProtoReflect.Descriptor instead. func (*SetRoomPasswordRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} } func (x *SetRoomPasswordRequest) GetMeta() *RequestMeta { @@ -5966,7 +6107,7 @@ type SetRoomPasswordResponse struct { func (x *SetRoomPasswordResponse) Reset() { *x = SetRoomPasswordResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5978,7 +6119,7 @@ func (x *SetRoomPasswordResponse) String() string { func (*SetRoomPasswordResponse) ProtoMessage() {} func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5991,7 +6132,7 @@ func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordResponse.ProtoReflect.Descriptor instead. func (*SetRoomPasswordResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} } func (x *SetRoomPasswordResponse) GetResult() *CommandResult { @@ -6020,7 +6161,7 @@ type SetRoomAdminRequest struct { func (x *SetRoomAdminRequest) Reset() { *x = SetRoomAdminRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6032,7 +6173,7 @@ func (x *SetRoomAdminRequest) String() string { func (*SetRoomAdminRequest) ProtoMessage() {} func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6045,7 +6186,7 @@ func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminRequest.ProtoReflect.Descriptor instead. func (*SetRoomAdminRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} } func (x *SetRoomAdminRequest) GetMeta() *RequestMeta { @@ -6080,7 +6221,7 @@ type SetRoomAdminResponse struct { func (x *SetRoomAdminResponse) Reset() { *x = SetRoomAdminResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6092,7 +6233,7 @@ func (x *SetRoomAdminResponse) String() string { func (*SetRoomAdminResponse) ProtoMessage() {} func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6105,7 +6246,7 @@ func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminResponse.ProtoReflect.Descriptor instead. func (*SetRoomAdminResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} } func (x *SetRoomAdminResponse) GetResult() *CommandResult { @@ -6134,7 +6275,7 @@ type MuteUserRequest struct { func (x *MuteUserRequest) Reset() { *x = MuteUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6146,7 +6287,7 @@ func (x *MuteUserRequest) String() string { func (*MuteUserRequest) ProtoMessage() {} func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6159,7 +6300,7 @@ func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserRequest.ProtoReflect.Descriptor instead. func (*MuteUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} } func (x *MuteUserRequest) GetMeta() *RequestMeta { @@ -6194,7 +6335,7 @@ type MuteUserResponse struct { func (x *MuteUserResponse) Reset() { *x = MuteUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6206,7 +6347,7 @@ func (x *MuteUserResponse) String() string { func (*MuteUserResponse) ProtoMessage() {} func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6219,7 +6360,7 @@ func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserResponse.ProtoReflect.Descriptor instead. func (*MuteUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} } func (x *MuteUserResponse) GetResult() *CommandResult { @@ -6249,7 +6390,7 @@ type KickUserRequest struct { func (x *KickUserRequest) Reset() { *x = KickUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6261,7 +6402,7 @@ func (x *KickUserRequest) String() string { func (*KickUserRequest) ProtoMessage() {} func (x *KickUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6274,7 +6415,7 @@ func (x *KickUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserRequest.ProtoReflect.Descriptor instead. func (*KickUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} } func (x *KickUserRequest) GetMeta() *RequestMeta { @@ -6313,7 +6454,7 @@ type KickUserResponse struct { func (x *KickUserResponse) Reset() { *x = KickUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6325,7 +6466,7 @@ func (x *KickUserResponse) String() string { func (*KickUserResponse) ProtoMessage() {} func (x *KickUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6338,7 +6479,7 @@ func (x *KickUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserResponse.ProtoReflect.Descriptor instead. func (*KickUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} } func (x *KickUserResponse) GetResult() *CommandResult { @@ -6380,7 +6521,7 @@ type UnbanUserRequest struct { func (x *UnbanUserRequest) Reset() { *x = UnbanUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6392,7 +6533,7 @@ func (x *UnbanUserRequest) String() string { func (*UnbanUserRequest) ProtoMessage() {} func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6405,7 +6546,7 @@ func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserRequest.ProtoReflect.Descriptor instead. func (*UnbanUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} } func (x *UnbanUserRequest) GetMeta() *RequestMeta { @@ -6433,7 +6574,7 @@ type UnbanUserResponse struct { func (x *UnbanUserResponse) Reset() { *x = UnbanUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6445,7 +6586,7 @@ func (x *UnbanUserResponse) String() string { func (*UnbanUserResponse) ProtoMessage() {} func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6458,7 +6599,7 @@ func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserResponse.ProtoReflect.Descriptor instead. func (*UnbanUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} } func (x *UnbanUserResponse) GetResult() *CommandResult { @@ -6491,7 +6632,7 @@ type SystemEvictUserRequest struct { func (x *SystemEvictUserRequest) Reset() { *x = SystemEvictUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6503,7 +6644,7 @@ func (x *SystemEvictUserRequest) String() string { func (*SystemEvictUserRequest) ProtoMessage() {} func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6516,7 +6657,7 @@ func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserRequest.ProtoReflect.Descriptor instead. func (*SystemEvictUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} } func (x *SystemEvictUserRequest) GetMeta() *RequestMeta { @@ -6569,7 +6710,7 @@ type SystemEvictUserResponse struct { func (x *SystemEvictUserResponse) Reset() { *x = SystemEvictUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6581,7 +6722,7 @@ func (x *SystemEvictUserResponse) String() string { func (*SystemEvictUserResponse) ProtoMessage() {} func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6594,7 +6735,7 @@ func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserResponse.ProtoReflect.Descriptor instead. func (*SystemEvictUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} } func (x *SystemEvictUserResponse) GetHadCurrentRoom() bool { @@ -6665,7 +6806,7 @@ type SendGiftRequest struct { func (x *SendGiftRequest) Reset() { *x = SendGiftRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6677,7 +6818,7 @@ func (x *SendGiftRequest) String() string { func (*SendGiftRequest) ProtoMessage() {} func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6690,7 +6831,7 @@ func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftRequest.ProtoReflect.Descriptor instead. func (*SendGiftRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} } func (x *SendGiftRequest) GetMeta() *RequestMeta { @@ -6789,7 +6930,7 @@ type SendGiftResponse struct { func (x *SendGiftResponse) Reset() { *x = SendGiftResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6801,7 +6942,7 @@ func (x *SendGiftResponse) String() string { func (*SendGiftResponse) ProtoMessage() {} func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6814,7 +6955,7 @@ func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftResponse.ProtoReflect.Descriptor instead. func (*SendGiftResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} } func (x *SendGiftResponse) GetResult() *CommandResult { @@ -6885,7 +7026,7 @@ type CheckSpeakPermissionRequest struct { func (x *CheckSpeakPermissionRequest) Reset() { *x = CheckSpeakPermissionRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6897,7 +7038,7 @@ func (x *CheckSpeakPermissionRequest) String() string { func (*CheckSpeakPermissionRequest) ProtoMessage() {} func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6910,7 +7051,7 @@ func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionRequest.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} } func (x *CheckSpeakPermissionRequest) GetRoomId() string { @@ -6946,7 +7087,7 @@ type CheckSpeakPermissionResponse struct { func (x *CheckSpeakPermissionResponse) Reset() { *x = CheckSpeakPermissionResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6958,7 +7099,7 @@ func (x *CheckSpeakPermissionResponse) String() string { func (*CheckSpeakPermissionResponse) ProtoMessage() {} func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6971,7 +7112,7 @@ func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionResponse.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} } func (x *CheckSpeakPermissionResponse) GetAllowed() bool { @@ -7009,7 +7150,7 @@ type VerifyRoomPresenceRequest struct { func (x *VerifyRoomPresenceRequest) Reset() { *x = VerifyRoomPresenceRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7021,7 +7162,7 @@ func (x *VerifyRoomPresenceRequest) String() string { func (*VerifyRoomPresenceRequest) ProtoMessage() {} func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7034,7 +7175,7 @@ func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceRequest.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} } func (x *VerifyRoomPresenceRequest) GetRoomId() string { @@ -7084,7 +7225,7 @@ type VerifyRoomPresenceResponse struct { func (x *VerifyRoomPresenceResponse) Reset() { *x = VerifyRoomPresenceResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7096,7 +7237,7 @@ func (x *VerifyRoomPresenceResponse) String() string { func (*VerifyRoomPresenceResponse) ProtoMessage() {} func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7109,7 +7250,7 @@ func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceResponse.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} } func (x *VerifyRoomPresenceResponse) GetPresent() bool { @@ -7150,7 +7291,7 @@ type ListRoomsRequest struct { func (x *ListRoomsRequest) Reset() { *x = ListRoomsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7162,7 +7303,7 @@ func (x *ListRoomsRequest) String() string { func (*ListRoomsRequest) ProtoMessage() {} func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7175,7 +7316,7 @@ func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsRequest.ProtoReflect.Descriptor instead. func (*ListRoomsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} } func (x *ListRoomsRequest) GetMeta() *RequestMeta { @@ -7246,7 +7387,7 @@ type ListRoomFeedsRequest struct { func (x *ListRoomFeedsRequest) Reset() { *x = ListRoomFeedsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7258,7 +7399,7 @@ func (x *ListRoomFeedsRequest) String() string { func (*ListRoomFeedsRequest) ProtoMessage() {} func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7271,7 +7412,7 @@ func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomFeedsRequest.ProtoReflect.Descriptor instead. func (*ListRoomFeedsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} } func (x *ListRoomFeedsRequest) GetMeta() *RequestMeta { @@ -7343,7 +7484,7 @@ type ListRoomGiftLeaderboardRequest struct { func (x *ListRoomGiftLeaderboardRequest) Reset() { *x = ListRoomGiftLeaderboardRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7355,7 +7496,7 @@ func (x *ListRoomGiftLeaderboardRequest) String() string { func (*ListRoomGiftLeaderboardRequest) ProtoMessage() {} func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7368,7 +7509,7 @@ func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardRequest.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} } func (x *ListRoomGiftLeaderboardRequest) GetMeta() *RequestMeta { @@ -7410,7 +7551,7 @@ type RoomFeedRelatedUser struct { func (x *RoomFeedRelatedUser) Reset() { *x = RoomFeedRelatedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7422,7 +7563,7 @@ func (x *RoomFeedRelatedUser) String() string { func (*RoomFeedRelatedUser) ProtoMessage() {} func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7435,7 +7576,7 @@ func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomFeedRelatedUser.ProtoReflect.Descriptor instead. func (*RoomFeedRelatedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} } func (x *RoomFeedRelatedUser) GetUserId() int64 { @@ -7475,7 +7616,7 @@ type RoomListItem struct { func (x *RoomListItem) Reset() { *x = RoomListItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7487,7 +7628,7 @@ func (x *RoomListItem) String() string { func (*RoomListItem) ProtoMessage() {} func (x *RoomListItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7500,7 +7641,7 @@ func (x *RoomListItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomListItem.ProtoReflect.Descriptor instead. func (*RoomListItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} } func (x *RoomListItem) GetRoomId() string { @@ -7612,7 +7753,7 @@ type ListRoomsResponse struct { func (x *ListRoomsResponse) Reset() { *x = ListRoomsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7624,7 +7765,7 @@ func (x *ListRoomsResponse) String() string { func (*ListRoomsResponse) ProtoMessage() {} func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7637,7 +7778,7 @@ func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsResponse.ProtoReflect.Descriptor instead. func (*ListRoomsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} } func (x *ListRoomsResponse) GetRooms() []*RoomListItem { @@ -7667,7 +7808,7 @@ type RoomGiftLeaderboardItem struct { func (x *RoomGiftLeaderboardItem) Reset() { *x = RoomGiftLeaderboardItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7679,7 +7820,7 @@ func (x *RoomGiftLeaderboardItem) String() string { func (*RoomGiftLeaderboardItem) ProtoMessage() {} func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7692,7 +7833,7 @@ func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomGiftLeaderboardItem.ProtoReflect.Descriptor instead. func (*RoomGiftLeaderboardItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} } func (x *RoomGiftLeaderboardItem) GetRank() int64 { @@ -7738,7 +7879,7 @@ type ListRoomGiftLeaderboardResponse struct { func (x *ListRoomGiftLeaderboardResponse) Reset() { *x = ListRoomGiftLeaderboardResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7750,7 +7891,7 @@ func (x *ListRoomGiftLeaderboardResponse) String() string { func (*ListRoomGiftLeaderboardResponse) ProtoMessage() {} func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7763,7 +7904,7 @@ func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardResponse.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} } func (x *ListRoomGiftLeaderboardResponse) GetItems() []*RoomGiftLeaderboardItem { @@ -7820,7 +7961,7 @@ type GetMyRoomRequest struct { func (x *GetMyRoomRequest) Reset() { *x = GetMyRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7832,7 +7973,7 @@ func (x *GetMyRoomRequest) String() string { func (*GetMyRoomRequest) ProtoMessage() {} func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7845,7 +7986,7 @@ func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomRequest.ProtoReflect.Descriptor instead. func (*GetMyRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} } func (x *GetMyRoomRequest) GetMeta() *RequestMeta { @@ -7875,7 +8016,7 @@ type GetMyRoomResponse struct { func (x *GetMyRoomResponse) Reset() { *x = GetMyRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7887,7 +8028,7 @@ func (x *GetMyRoomResponse) String() string { func (*GetMyRoomResponse) ProtoMessage() {} func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7900,7 +8041,7 @@ func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomResponse.ProtoReflect.Descriptor instead. func (*GetMyRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} } func (x *GetMyRoomResponse) GetHasRoom() bool { @@ -7936,7 +8077,7 @@ type GetCurrentRoomRequest struct { func (x *GetCurrentRoomRequest) Reset() { *x = GetCurrentRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7948,7 +8089,7 @@ func (x *GetCurrentRoomRequest) String() string { func (*GetCurrentRoomRequest) ProtoMessage() {} func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7961,7 +8102,7 @@ func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomRequest.ProtoReflect.Descriptor instead. func (*GetCurrentRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} } func (x *GetCurrentRoomRequest) GetMeta() *RequestMeta { @@ -7997,7 +8138,7 @@ type GetCurrentRoomResponse struct { func (x *GetCurrentRoomResponse) Reset() { *x = GetCurrentRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8009,7 +8150,7 @@ func (x *GetCurrentRoomResponse) String() string { func (*GetCurrentRoomResponse) ProtoMessage() {} func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8022,7 +8163,7 @@ func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomResponse.ProtoReflect.Descriptor instead. func (*GetCurrentRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} } func (x *GetCurrentRoomResponse) GetHasCurrentRoom() bool { @@ -8101,7 +8242,7 @@ type GetRoomSnapshotRequest struct { func (x *GetRoomSnapshotRequest) Reset() { *x = GetRoomSnapshotRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8113,7 +8254,7 @@ func (x *GetRoomSnapshotRequest) String() string { func (*GetRoomSnapshotRequest) ProtoMessage() {} func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8126,7 +8267,7 @@ func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotRequest.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} } func (x *GetRoomSnapshotRequest) GetMeta() *RequestMeta { @@ -8163,7 +8304,7 @@ type GetRoomSnapshotResponse struct { func (x *GetRoomSnapshotResponse) Reset() { *x = GetRoomSnapshotResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8175,7 +8316,7 @@ func (x *GetRoomSnapshotResponse) String() string { func (*GetRoomSnapshotResponse) ProtoMessage() {} func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8188,7 +8329,7 @@ func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotResponse.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} } func (x *GetRoomSnapshotResponse) GetRoom() *RoomSnapshot { @@ -8225,7 +8366,7 @@ type GetRoomTreasureRequest struct { func (x *GetRoomTreasureRequest) Reset() { *x = GetRoomTreasureRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8237,7 +8378,7 @@ func (x *GetRoomTreasureRequest) String() string { func (*GetRoomTreasureRequest) ProtoMessage() {} func (x *GetRoomTreasureRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8250,7 +8391,7 @@ func (x *GetRoomTreasureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomTreasureRequest.ProtoReflect.Descriptor instead. func (*GetRoomTreasureRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} } func (x *GetRoomTreasureRequest) GetMeta() *RequestMeta { @@ -8284,7 +8425,7 @@ type GetRoomTreasureResponse struct { func (x *GetRoomTreasureResponse) Reset() { *x = GetRoomTreasureResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8296,7 +8437,7 @@ func (x *GetRoomTreasureResponse) String() string { func (*GetRoomTreasureResponse) ProtoMessage() {} func (x *GetRoomTreasureResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8309,7 +8450,7 @@ func (x *GetRoomTreasureResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomTreasureResponse.ProtoReflect.Descriptor instead. func (*GetRoomTreasureResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} } func (x *GetRoomTreasureResponse) GetTreasure() *RoomTreasureInfo { @@ -8341,7 +8482,7 @@ type ListRoomOnlineUsersRequest struct { func (x *ListRoomOnlineUsersRequest) Reset() { *x = ListRoomOnlineUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[112] + mi := &file_proto_room_v1_room_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8353,7 +8494,7 @@ func (x *ListRoomOnlineUsersRequest) String() string { func (*ListRoomOnlineUsersRequest) ProtoMessage() {} func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[112] + mi := &file_proto_room_v1_room_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8366,7 +8507,7 @@ func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} } func (x *ListRoomOnlineUsersRequest) GetMeta() *RequestMeta { @@ -8425,7 +8566,7 @@ type ListRoomOnlineUsersResponse struct { func (x *ListRoomOnlineUsersResponse) Reset() { *x = ListRoomOnlineUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[113] + mi := &file_proto_room_v1_room_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8437,7 +8578,7 @@ func (x *ListRoomOnlineUsersResponse) String() string { func (*ListRoomOnlineUsersResponse) ProtoMessage() {} func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[113] + mi := &file_proto_room_v1_room_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8450,7 +8591,7 @@ func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} } func (x *ListRoomOnlineUsersResponse) GetUsers() []*RoomUser { @@ -8511,7 +8652,7 @@ type RoomBannedUser struct { func (x *RoomBannedUser) Reset() { *x = RoomBannedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8523,7 +8664,7 @@ func (x *RoomBannedUser) String() string { func (*RoomBannedUser) ProtoMessage() {} func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8536,7 +8677,7 @@ func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBannedUser.ProtoReflect.Descriptor instead. func (*RoomBannedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} } func (x *RoomBannedUser) GetUserId() int64 { @@ -8595,7 +8736,7 @@ type ListRoomBannedUsersRequest struct { func (x *ListRoomBannedUsersRequest) Reset() { *x = ListRoomBannedUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8607,7 +8748,7 @@ func (x *ListRoomBannedUsersRequest) String() string { func (*ListRoomBannedUsersRequest) ProtoMessage() {} func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8620,7 +8761,7 @@ func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} } func (x *ListRoomBannedUsersRequest) GetMeta() *RequestMeta { @@ -8671,7 +8812,7 @@ type ListRoomBannedUsersResponse struct { func (x *ListRoomBannedUsersResponse) Reset() { *x = ListRoomBannedUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8683,7 +8824,7 @@ func (x *ListRoomBannedUsersResponse) String() string { func (*ListRoomBannedUsersResponse) ProtoMessage() {} func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8696,7 +8837,7 @@ func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} } func (x *ListRoomBannedUsersResponse) GetItems() []*RoomBannedUser { @@ -8747,7 +8888,7 @@ type FollowRoomRequest struct { func (x *FollowRoomRequest) Reset() { *x = FollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8759,7 +8900,7 @@ func (x *FollowRoomRequest) String() string { func (*FollowRoomRequest) ProtoMessage() {} func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8772,7 +8913,7 @@ func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomRequest.ProtoReflect.Descriptor instead. func (*FollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} } func (x *FollowRoomRequest) GetMeta() *RequestMeta { @@ -8808,7 +8949,7 @@ type FollowRoomResponse struct { func (x *FollowRoomResponse) Reset() { *x = FollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8820,7 +8961,7 @@ func (x *FollowRoomResponse) String() string { func (*FollowRoomResponse) ProtoMessage() {} func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8833,7 +8974,7 @@ func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomResponse.ProtoReflect.Descriptor instead. func (*FollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} } func (x *FollowRoomResponse) GetRoomId() string { @@ -8876,7 +9017,7 @@ type UnfollowRoomRequest struct { func (x *UnfollowRoomRequest) Reset() { *x = UnfollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8888,7 +9029,7 @@ func (x *UnfollowRoomRequest) String() string { func (*UnfollowRoomRequest) ProtoMessage() {} func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8901,7 +9042,7 @@ func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomRequest.ProtoReflect.Descriptor instead. func (*UnfollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{121} } func (x *UnfollowRoomRequest) GetMeta() *RequestMeta { @@ -8936,7 +9077,7 @@ type UnfollowRoomResponse struct { func (x *UnfollowRoomResponse) Reset() { *x = UnfollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8948,7 +9089,7 @@ func (x *UnfollowRoomResponse) String() string { func (*UnfollowRoomResponse) ProtoMessage() {} func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8961,7 +9102,7 @@ func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomResponse.ProtoReflect.Descriptor instead. func (*UnfollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{122} } func (x *UnfollowRoomResponse) GetRoomId() string { @@ -9022,7 +9163,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\fjoined_at_ms\x18\x05 \x01(\x03R\n" + "joinedAtMs\x12%\n" + "\x0flast_seen_at_ms\x18\x06 \x01(\x03R\flastSeenAtMs\x12\x19\n" + - "\bis_owner\x18\a \x01(\bR\aisOwner\"\x83\x03\n" + + "\bis_owner\x18\a \x01(\bR\aisOwner\"\xb2\x03\n" + "\tSeatState\x12\x17\n" + "\aseat_no\x18\x01 \x01(\x05R\x06seatNo\x12\x17\n" + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x16\n" + @@ -9035,7 +9176,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\tmic_muted\x18\t \x01(\bR\bmicMuted\x12\x1f\n" + "\vseat_status\x18\n" + " \x01(\tR\n" + - "seatStatus\"|\n" + + "seatStatus\x12-\n" + + "\x13mic_heartbeat_at_ms\x18\v \x01(\x03R\x10micHeartbeatAtMs\"|\n" + "\bRankItem\x12\x17\n" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n" + "\x05score\x18\x02 \x01(\x03R\x05score\x12\x1d\n" + @@ -9462,7 +9604,16 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x1cConfirmMicPublishingResponse\x124\n" + "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x7f\n" + + "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x91\x01\n" + + "\x13MicHeartbeatRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12$\n" + + "\x0emic_session_id\x18\x03 \x01(\tR\fmicSessionId\"\xc5\x01\n" + + "\x14MicHeartbeatResponse\x124\n" + + "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + + "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + + "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12-\n" + + "\x13mic_heartbeat_at_ms\x18\x04 \x01(\x03R\x10micHeartbeatAtMs\"\x7f\n" + "\x11SetMicMuteRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x14\n" + @@ -9739,7 +9890,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x14UnfollowRoomResponse\x12\x17\n" + "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x1a\n" + "\bfollowed\x18\x02 \x01(\bR\bfollowed\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs2\xda\x16\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs2\xb3\x17\n" + "\x12RoomCommandService\x12Q\n" + "\n" + "CreateRoom\x12 .hyapp.room.v1.CreateRoomRequest\x1a!.hyapp.room.v1.CreateRoomResponse\x12f\n" + @@ -9759,7 +9910,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x05MicUp\x12\x1b.hyapp.room.v1.MicUpRequest\x1a\x1c.hyapp.room.v1.MicUpResponse\x12H\n" + "\aMicDown\x12\x1d.hyapp.room.v1.MicDownRequest\x1a\x1e.hyapp.room.v1.MicDownResponse\x12Z\n" + "\rChangeMicSeat\x12#.hyapp.room.v1.ChangeMicSeatRequest\x1a$.hyapp.room.v1.ChangeMicSeatResponse\x12o\n" + - "\x14ConfirmMicPublishing\x12*.hyapp.room.v1.ConfirmMicPublishingRequest\x1a+.hyapp.room.v1.ConfirmMicPublishingResponse\x12Q\n" + + "\x14ConfirmMicPublishing\x12*.hyapp.room.v1.ConfirmMicPublishingRequest\x1a+.hyapp.room.v1.ConfirmMicPublishingResponse\x12W\n" + + "\fMicHeartbeat\x12\".hyapp.room.v1.MicHeartbeatRequest\x1a#.hyapp.room.v1.MicHeartbeatResponse\x12Q\n" + "\n" + "SetMicMute\x12 .hyapp.room.v1.SetMicMuteRequest\x1a!.hyapp.room.v1.SetMicMuteResponse\x12Z\n" + "\rApplyRTCEvent\x12#.hyapp.room.v1.ApplyRTCEventRequest\x1a$.hyapp.room.v1.ApplyRTCEventResponse\x12]\n" + @@ -9807,7 +9959,7 @@ func file_proto_room_v1_room_proto_rawDescGZIP() []byte { return file_proto_room_v1_room_proto_rawDescData } -var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 122) +var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 124) var file_proto_room_v1_room_proto_goTypes = []any{ (*RequestMeta)(nil), // 0: hyapp.room.v1.RequestMeta (*CommandResult)(nil), // 1: hyapp.room.v1.CommandResult @@ -9879,58 +10031,60 @@ var file_proto_room_v1_room_proto_goTypes = []any{ (*ChangeMicSeatResponse)(nil), // 67: hyapp.room.v1.ChangeMicSeatResponse (*ConfirmMicPublishingRequest)(nil), // 68: hyapp.room.v1.ConfirmMicPublishingRequest (*ConfirmMicPublishingResponse)(nil), // 69: hyapp.room.v1.ConfirmMicPublishingResponse - (*SetMicMuteRequest)(nil), // 70: hyapp.room.v1.SetMicMuteRequest - (*SetMicMuteResponse)(nil), // 71: hyapp.room.v1.SetMicMuteResponse - (*ApplyRTCEventRequest)(nil), // 72: hyapp.room.v1.ApplyRTCEventRequest - (*ApplyRTCEventResponse)(nil), // 73: hyapp.room.v1.ApplyRTCEventResponse - (*SetMicSeatLockRequest)(nil), // 74: hyapp.room.v1.SetMicSeatLockRequest - (*SetMicSeatLockResponse)(nil), // 75: hyapp.room.v1.SetMicSeatLockResponse - (*SetChatEnabledRequest)(nil), // 76: hyapp.room.v1.SetChatEnabledRequest - (*SetChatEnabledResponse)(nil), // 77: hyapp.room.v1.SetChatEnabledResponse - (*SetRoomPasswordRequest)(nil), // 78: hyapp.room.v1.SetRoomPasswordRequest - (*SetRoomPasswordResponse)(nil), // 79: hyapp.room.v1.SetRoomPasswordResponse - (*SetRoomAdminRequest)(nil), // 80: hyapp.room.v1.SetRoomAdminRequest - (*SetRoomAdminResponse)(nil), // 81: hyapp.room.v1.SetRoomAdminResponse - (*MuteUserRequest)(nil), // 82: hyapp.room.v1.MuteUserRequest - (*MuteUserResponse)(nil), // 83: hyapp.room.v1.MuteUserResponse - (*KickUserRequest)(nil), // 84: hyapp.room.v1.KickUserRequest - (*KickUserResponse)(nil), // 85: hyapp.room.v1.KickUserResponse - (*UnbanUserRequest)(nil), // 86: hyapp.room.v1.UnbanUserRequest - (*UnbanUserResponse)(nil), // 87: hyapp.room.v1.UnbanUserResponse - (*SystemEvictUserRequest)(nil), // 88: hyapp.room.v1.SystemEvictUserRequest - (*SystemEvictUserResponse)(nil), // 89: hyapp.room.v1.SystemEvictUserResponse - (*SendGiftRequest)(nil), // 90: hyapp.room.v1.SendGiftRequest - (*SendGiftResponse)(nil), // 91: hyapp.room.v1.SendGiftResponse - (*CheckSpeakPermissionRequest)(nil), // 92: hyapp.room.v1.CheckSpeakPermissionRequest - (*CheckSpeakPermissionResponse)(nil), // 93: hyapp.room.v1.CheckSpeakPermissionResponse - (*VerifyRoomPresenceRequest)(nil), // 94: hyapp.room.v1.VerifyRoomPresenceRequest - (*VerifyRoomPresenceResponse)(nil), // 95: hyapp.room.v1.VerifyRoomPresenceResponse - (*ListRoomsRequest)(nil), // 96: hyapp.room.v1.ListRoomsRequest - (*ListRoomFeedsRequest)(nil), // 97: hyapp.room.v1.ListRoomFeedsRequest - (*ListRoomGiftLeaderboardRequest)(nil), // 98: hyapp.room.v1.ListRoomGiftLeaderboardRequest - (*RoomFeedRelatedUser)(nil), // 99: hyapp.room.v1.RoomFeedRelatedUser - (*RoomListItem)(nil), // 100: hyapp.room.v1.RoomListItem - (*ListRoomsResponse)(nil), // 101: hyapp.room.v1.ListRoomsResponse - (*RoomGiftLeaderboardItem)(nil), // 102: hyapp.room.v1.RoomGiftLeaderboardItem - (*ListRoomGiftLeaderboardResponse)(nil), // 103: hyapp.room.v1.ListRoomGiftLeaderboardResponse - (*GetMyRoomRequest)(nil), // 104: hyapp.room.v1.GetMyRoomRequest - (*GetMyRoomResponse)(nil), // 105: hyapp.room.v1.GetMyRoomResponse - (*GetCurrentRoomRequest)(nil), // 106: hyapp.room.v1.GetCurrentRoomRequest - (*GetCurrentRoomResponse)(nil), // 107: hyapp.room.v1.GetCurrentRoomResponse - (*GetRoomSnapshotRequest)(nil), // 108: hyapp.room.v1.GetRoomSnapshotRequest - (*GetRoomSnapshotResponse)(nil), // 109: hyapp.room.v1.GetRoomSnapshotResponse - (*GetRoomTreasureRequest)(nil), // 110: hyapp.room.v1.GetRoomTreasureRequest - (*GetRoomTreasureResponse)(nil), // 111: hyapp.room.v1.GetRoomTreasureResponse - (*ListRoomOnlineUsersRequest)(nil), // 112: hyapp.room.v1.ListRoomOnlineUsersRequest - (*ListRoomOnlineUsersResponse)(nil), // 113: hyapp.room.v1.ListRoomOnlineUsersResponse - (*RoomBannedUser)(nil), // 114: hyapp.room.v1.RoomBannedUser - (*ListRoomBannedUsersRequest)(nil), // 115: hyapp.room.v1.ListRoomBannedUsersRequest - (*ListRoomBannedUsersResponse)(nil), // 116: hyapp.room.v1.ListRoomBannedUsersResponse - (*FollowRoomRequest)(nil), // 117: hyapp.room.v1.FollowRoomRequest - (*FollowRoomResponse)(nil), // 118: hyapp.room.v1.FollowRoomResponse - (*UnfollowRoomRequest)(nil), // 119: hyapp.room.v1.UnfollowRoomRequest - (*UnfollowRoomResponse)(nil), // 120: hyapp.room.v1.UnfollowRoomResponse - nil, // 121: hyapp.room.v1.RoomSnapshot.RoomExtEntry + (*MicHeartbeatRequest)(nil), // 70: hyapp.room.v1.MicHeartbeatRequest + (*MicHeartbeatResponse)(nil), // 71: hyapp.room.v1.MicHeartbeatResponse + (*SetMicMuteRequest)(nil), // 72: hyapp.room.v1.SetMicMuteRequest + (*SetMicMuteResponse)(nil), // 73: hyapp.room.v1.SetMicMuteResponse + (*ApplyRTCEventRequest)(nil), // 74: hyapp.room.v1.ApplyRTCEventRequest + (*ApplyRTCEventResponse)(nil), // 75: hyapp.room.v1.ApplyRTCEventResponse + (*SetMicSeatLockRequest)(nil), // 76: hyapp.room.v1.SetMicSeatLockRequest + (*SetMicSeatLockResponse)(nil), // 77: hyapp.room.v1.SetMicSeatLockResponse + (*SetChatEnabledRequest)(nil), // 78: hyapp.room.v1.SetChatEnabledRequest + (*SetChatEnabledResponse)(nil), // 79: hyapp.room.v1.SetChatEnabledResponse + (*SetRoomPasswordRequest)(nil), // 80: hyapp.room.v1.SetRoomPasswordRequest + (*SetRoomPasswordResponse)(nil), // 81: hyapp.room.v1.SetRoomPasswordResponse + (*SetRoomAdminRequest)(nil), // 82: hyapp.room.v1.SetRoomAdminRequest + (*SetRoomAdminResponse)(nil), // 83: hyapp.room.v1.SetRoomAdminResponse + (*MuteUserRequest)(nil), // 84: hyapp.room.v1.MuteUserRequest + (*MuteUserResponse)(nil), // 85: hyapp.room.v1.MuteUserResponse + (*KickUserRequest)(nil), // 86: hyapp.room.v1.KickUserRequest + (*KickUserResponse)(nil), // 87: hyapp.room.v1.KickUserResponse + (*UnbanUserRequest)(nil), // 88: hyapp.room.v1.UnbanUserRequest + (*UnbanUserResponse)(nil), // 89: hyapp.room.v1.UnbanUserResponse + (*SystemEvictUserRequest)(nil), // 90: hyapp.room.v1.SystemEvictUserRequest + (*SystemEvictUserResponse)(nil), // 91: hyapp.room.v1.SystemEvictUserResponse + (*SendGiftRequest)(nil), // 92: hyapp.room.v1.SendGiftRequest + (*SendGiftResponse)(nil), // 93: hyapp.room.v1.SendGiftResponse + (*CheckSpeakPermissionRequest)(nil), // 94: hyapp.room.v1.CheckSpeakPermissionRequest + (*CheckSpeakPermissionResponse)(nil), // 95: hyapp.room.v1.CheckSpeakPermissionResponse + (*VerifyRoomPresenceRequest)(nil), // 96: hyapp.room.v1.VerifyRoomPresenceRequest + (*VerifyRoomPresenceResponse)(nil), // 97: hyapp.room.v1.VerifyRoomPresenceResponse + (*ListRoomsRequest)(nil), // 98: hyapp.room.v1.ListRoomsRequest + (*ListRoomFeedsRequest)(nil), // 99: hyapp.room.v1.ListRoomFeedsRequest + (*ListRoomGiftLeaderboardRequest)(nil), // 100: hyapp.room.v1.ListRoomGiftLeaderboardRequest + (*RoomFeedRelatedUser)(nil), // 101: hyapp.room.v1.RoomFeedRelatedUser + (*RoomListItem)(nil), // 102: hyapp.room.v1.RoomListItem + (*ListRoomsResponse)(nil), // 103: hyapp.room.v1.ListRoomsResponse + (*RoomGiftLeaderboardItem)(nil), // 104: hyapp.room.v1.RoomGiftLeaderboardItem + (*ListRoomGiftLeaderboardResponse)(nil), // 105: hyapp.room.v1.ListRoomGiftLeaderboardResponse + (*GetMyRoomRequest)(nil), // 106: hyapp.room.v1.GetMyRoomRequest + (*GetMyRoomResponse)(nil), // 107: hyapp.room.v1.GetMyRoomResponse + (*GetCurrentRoomRequest)(nil), // 108: hyapp.room.v1.GetCurrentRoomRequest + (*GetCurrentRoomResponse)(nil), // 109: hyapp.room.v1.GetCurrentRoomResponse + (*GetRoomSnapshotRequest)(nil), // 110: hyapp.room.v1.GetRoomSnapshotRequest + (*GetRoomSnapshotResponse)(nil), // 111: hyapp.room.v1.GetRoomSnapshotResponse + (*GetRoomTreasureRequest)(nil), // 112: hyapp.room.v1.GetRoomTreasureRequest + (*GetRoomTreasureResponse)(nil), // 113: hyapp.room.v1.GetRoomTreasureResponse + (*ListRoomOnlineUsersRequest)(nil), // 114: hyapp.room.v1.ListRoomOnlineUsersRequest + (*ListRoomOnlineUsersResponse)(nil), // 115: hyapp.room.v1.ListRoomOnlineUsersResponse + (*RoomBannedUser)(nil), // 116: hyapp.room.v1.RoomBannedUser + (*ListRoomBannedUsersRequest)(nil), // 117: hyapp.room.v1.ListRoomBannedUsersRequest + (*ListRoomBannedUsersResponse)(nil), // 118: hyapp.room.v1.ListRoomBannedUsersResponse + (*FollowRoomRequest)(nil), // 119: hyapp.room.v1.FollowRoomRequest + (*FollowRoomResponse)(nil), // 120: hyapp.room.v1.FollowRoomResponse + (*UnfollowRoomRequest)(nil), // 121: hyapp.room.v1.UnfollowRoomRequest + (*UnfollowRoomResponse)(nil), // 122: hyapp.room.v1.UnfollowRoomResponse + nil, // 123: hyapp.room.v1.RoomSnapshot.RoomExtEntry } var file_proto_room_v1_room_proto_depIdxs = []int32{ 7, // 0: hyapp.room.v1.RoomTreasureLevel.in_room_rewards:type_name -> hyapp.room.v1.RoomTreasureRewardItem @@ -9960,7 +10114,7 @@ var file_proto_room_v1_room_proto_depIdxs = []int32{ 4, // 24: hyapp.room.v1.RoomSnapshot.mic_seats:type_name -> hyapp.room.v1.SeatState 2, // 25: hyapp.room.v1.RoomSnapshot.online_users:type_name -> hyapp.room.v1.RoomUser 5, // 26: hyapp.room.v1.RoomSnapshot.gift_rank:type_name -> hyapp.room.v1.RankItem - 121, // 27: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry + 123, // 27: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry 10, // 28: hyapp.room.v1.RoomSnapshot.treasure:type_name -> hyapp.room.v1.RoomTreasureState 31, // 29: hyapp.room.v1.RoomSnapshot.ban_states:type_name -> hyapp.room.v1.RoomBanState 0, // 30: hyapp.room.v1.SaveRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta @@ -10014,165 +10168,170 @@ var file_proto_room_v1_room_proto_depIdxs = []int32{ 0, // 78: hyapp.room.v1.ConfirmMicPublishingRequest.meta:type_name -> hyapp.room.v1.RequestMeta 1, // 79: hyapp.room.v1.ConfirmMicPublishingResponse.result:type_name -> hyapp.room.v1.CommandResult 32, // 80: hyapp.room.v1.ConfirmMicPublishingResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 81: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 82: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 83: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 84: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 85: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 86: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 87: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 88: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 89: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 90: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 91: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 92: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 93: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 94: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 95: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 96: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 97: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 98: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 99: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 100: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 101: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 102: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 103: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 104: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 105: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 106: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 107: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 108: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 109: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 110: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 111: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 112: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult - 5, // 113: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem - 32, // 114: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 10, // 115: hyapp.room.v1.SendGiftResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureState - 6, // 116: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 6, // 117: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 0, // 118: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 119: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 99, // 120: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser - 0, // 121: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 100, // 122: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem - 100, // 123: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem - 102, // 124: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem - 0, // 125: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 100, // 126: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem - 0, // 127: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 128: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 32, // 129: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 130: hyapp.room.v1.GetRoomTreasureRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 11, // 131: hyapp.room.v1.GetRoomTreasureResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureInfo - 0, // 132: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 2, // 133: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser - 3, // 134: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser - 0, // 135: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 114, // 136: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser - 0, // 137: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 138: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 40, // 139: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest - 42, // 140: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest - 34, // 141: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest - 38, // 142: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest - 45, // 143: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest - 47, // 144: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest - 49, // 145: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest - 51, // 146: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest - 58, // 147: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest - 60, // 148: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest - 16, // 149: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:input_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest - 21, // 150: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest - 27, // 151: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest - 29, // 152: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest - 62, // 153: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest - 64, // 154: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest - 66, // 155: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest - 68, // 156: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest - 70, // 157: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest - 72, // 158: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest - 74, // 159: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest - 76, // 160: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest - 78, // 161: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest - 80, // 162: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest - 82, // 163: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest - 84, // 164: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest - 86, // 165: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest - 88, // 166: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest - 90, // 167: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest - 117, // 168: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest - 119, // 169: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest - 92, // 170: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest - 94, // 171: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest - 54, // 172: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest - 56, // 173: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest - 14, // 174: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:input_type -> hyapp.room.v1.AdminGetRoomTreasureConfigRequest - 19, // 175: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest - 25, // 176: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest - 96, // 177: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest - 97, // 178: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest - 98, // 179: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest - 104, // 180: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest - 106, // 181: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest - 108, // 182: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest - 36, // 183: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest - 110, // 184: hyapp.room.v1.RoomQueryService.GetRoomTreasure:input_type -> hyapp.room.v1.GetRoomTreasureRequest - 112, // 185: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest - 115, // 186: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest - 41, // 187: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse - 43, // 188: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse - 35, // 189: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse - 39, // 190: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse - 46, // 191: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse - 48, // 192: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse - 50, // 193: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse - 52, // 194: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse - 59, // 195: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse - 61, // 196: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse - 17, // 197: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:output_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse - 22, // 198: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse - 28, // 199: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse - 30, // 200: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse - 63, // 201: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse - 65, // 202: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse - 67, // 203: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse - 69, // 204: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse - 71, // 205: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse - 73, // 206: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse - 75, // 207: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse - 77, // 208: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse - 79, // 209: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse - 81, // 210: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse - 83, // 211: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse - 85, // 212: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse - 87, // 213: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse - 89, // 214: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse - 91, // 215: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse - 118, // 216: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse - 120, // 217: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse - 93, // 218: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse - 95, // 219: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse - 55, // 220: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse - 57, // 221: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse - 15, // 222: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:output_type -> hyapp.room.v1.AdminGetRoomTreasureConfigResponse - 20, // 223: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse - 26, // 224: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse - 101, // 225: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse - 101, // 226: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse - 103, // 227: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse - 105, // 228: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse - 107, // 229: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse - 109, // 230: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse - 37, // 231: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse - 111, // 232: hyapp.room.v1.RoomQueryService.GetRoomTreasure:output_type -> hyapp.room.v1.GetRoomTreasureResponse - 113, // 233: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse - 116, // 234: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse - 187, // [187:235] is the sub-list for method output_type - 139, // [139:187] is the sub-list for method input_type - 139, // [139:139] is the sub-list for extension type_name - 139, // [139:139] is the sub-list for extension extendee - 0, // [0:139] is the sub-list for field type_name + 0, // 81: hyapp.room.v1.MicHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 82: hyapp.room.v1.MicHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 83: hyapp.room.v1.MicHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 84: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 85: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 86: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 87: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 88: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 89: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 90: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 91: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 92: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 93: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 94: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 95: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 96: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 97: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 98: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 99: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 100: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 101: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 102: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 103: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 104: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 105: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 106: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 107: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 108: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 109: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 110: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 111: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 112: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 32, // 113: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 114: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 115: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult + 5, // 116: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem + 32, // 117: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 10, // 118: hyapp.room.v1.SendGiftResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureState + 6, // 119: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 6, // 120: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 0, // 121: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 122: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 101, // 123: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser + 0, // 124: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 102, // 125: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem + 102, // 126: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem + 104, // 127: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem + 0, // 128: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 102, // 129: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem + 0, // 130: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 131: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 32, // 132: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 133: hyapp.room.v1.GetRoomTreasureRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 11, // 134: hyapp.room.v1.GetRoomTreasureResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureInfo + 0, // 135: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 2, // 136: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser + 3, // 137: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser + 0, // 138: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 116, // 139: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser + 0, // 140: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 141: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 40, // 142: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest + 42, // 143: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest + 34, // 144: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest + 38, // 145: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest + 45, // 146: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest + 47, // 147: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest + 49, // 148: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest + 51, // 149: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest + 58, // 150: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest + 60, // 151: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest + 16, // 152: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:input_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest + 21, // 153: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest + 27, // 154: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest + 29, // 155: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest + 62, // 156: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest + 64, // 157: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest + 66, // 158: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest + 68, // 159: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest + 70, // 160: hyapp.room.v1.RoomCommandService.MicHeartbeat:input_type -> hyapp.room.v1.MicHeartbeatRequest + 72, // 161: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest + 74, // 162: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest + 76, // 163: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest + 78, // 164: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest + 80, // 165: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest + 82, // 166: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest + 84, // 167: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest + 86, // 168: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest + 88, // 169: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest + 90, // 170: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest + 92, // 171: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest + 119, // 172: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest + 121, // 173: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest + 94, // 174: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest + 96, // 175: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest + 54, // 176: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest + 56, // 177: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest + 14, // 178: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:input_type -> hyapp.room.v1.AdminGetRoomTreasureConfigRequest + 19, // 179: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest + 25, // 180: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest + 98, // 181: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest + 99, // 182: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest + 100, // 183: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest + 106, // 184: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest + 108, // 185: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest + 110, // 186: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest + 36, // 187: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest + 112, // 188: hyapp.room.v1.RoomQueryService.GetRoomTreasure:input_type -> hyapp.room.v1.GetRoomTreasureRequest + 114, // 189: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest + 117, // 190: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest + 41, // 191: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse + 43, // 192: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse + 35, // 193: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse + 39, // 194: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse + 46, // 195: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse + 48, // 196: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse + 50, // 197: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse + 52, // 198: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse + 59, // 199: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse + 61, // 200: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse + 17, // 201: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:output_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse + 22, // 202: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse + 28, // 203: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse + 30, // 204: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse + 63, // 205: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse + 65, // 206: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse + 67, // 207: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse + 69, // 208: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse + 71, // 209: hyapp.room.v1.RoomCommandService.MicHeartbeat:output_type -> hyapp.room.v1.MicHeartbeatResponse + 73, // 210: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse + 75, // 211: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse + 77, // 212: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse + 79, // 213: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse + 81, // 214: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse + 83, // 215: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse + 85, // 216: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse + 87, // 217: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse + 89, // 218: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse + 91, // 219: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse + 93, // 220: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse + 120, // 221: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse + 122, // 222: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse + 95, // 223: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse + 97, // 224: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse + 55, // 225: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse + 57, // 226: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse + 15, // 227: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:output_type -> hyapp.room.v1.AdminGetRoomTreasureConfigResponse + 20, // 228: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse + 26, // 229: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse + 103, // 230: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse + 103, // 231: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse + 105, // 232: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse + 107, // 233: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse + 109, // 234: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse + 111, // 235: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse + 37, // 236: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse + 113, // 237: hyapp.room.v1.RoomQueryService.GetRoomTreasure:output_type -> hyapp.room.v1.GetRoomTreasureResponse + 115, // 238: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse + 118, // 239: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse + 191, // [191:240] is the sub-list for method output_type + 142, // [142:191] is the sub-list for method input_type + 142, // [142:142] is the sub-list for extension type_name + 142, // [142:142] is the sub-list for extension extendee + 0, // [0:142] is the sub-list for field type_name } func init() { file_proto_room_v1_room_proto_init() } @@ -10188,7 +10347,7 @@ func file_proto_room_v1_room_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_room_v1_room_proto_rawDesc), len(file_proto_room_v1_room_proto_rawDesc)), NumEnums: 0, - NumMessages: 122, + NumMessages: 124, NumExtensions: 0, NumServices: 3, }, diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index e5461030..216a684f 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -65,6 +65,8 @@ message SeatState { bool mic_muted = 9; // seat_status 是服务端派生的展示状态:empty/locked/occupied/publishing/muted。 string seat_status = 10; + // mic_heartbeat_at_ms 是当前 mic_session 最近一次服务端接受麦上心跳的 UTC epoch ms。 + int64 mic_heartbeat_at_ms = 11; } // RankItem 表达房间内本地礼物榜项目。 @@ -632,6 +634,23 @@ message ConfirmMicPublishingResponse { RoomSnapshot room = 3; } +// MicHeartbeatRequest 刷新当前 publishing 麦位会话的服务端麦上心跳。 +message MicHeartbeatRequest { + RequestMeta meta = 1; + // target_user_id 为空时默认刷新 actor_user_id 自己的麦上会话。 + int64 target_user_id = 2; + // mic_session_id 必须匹配当前麦位上的会话,避免旧心跳续住新会话。 + string mic_session_id = 3; +} + +// MicHeartbeatResponse 返回刷新后的麦位和房间快照。 +message MicHeartbeatResponse { + CommandResult result = 1; + int32 seat_no = 2; + RoomSnapshot room = 3; + int64 mic_heartbeat_at_ms = 4; +} + // SetMicMuteRequest 修改麦位上的服务端可见静音态。 message SetMicMuteRequest { RequestMeta meta = 1; @@ -1089,6 +1108,7 @@ service RoomCommandService { rpc MicDown(MicDownRequest) returns (MicDownResponse); rpc ChangeMicSeat(ChangeMicSeatRequest) returns (ChangeMicSeatResponse); rpc ConfirmMicPublishing(ConfirmMicPublishingRequest) returns (ConfirmMicPublishingResponse); + rpc MicHeartbeat(MicHeartbeatRequest) returns (MicHeartbeatResponse); rpc SetMicMute(SetMicMuteRequest) returns (SetMicMuteResponse); rpc ApplyRTCEvent(ApplyRTCEventRequest) returns (ApplyRTCEventResponse); rpc SetMicSeatLock(SetMicSeatLockRequest) returns (SetMicSeatLockResponse); diff --git a/api/proto/room/v1/room_grpc.pb.go b/api/proto/room/v1/room_grpc.pb.go index 67fbc782..0f0a7068 100644 --- a/api/proto/room/v1/room_grpc.pb.go +++ b/api/proto/room/v1/room_grpc.pb.go @@ -37,6 +37,7 @@ const ( RoomCommandService_MicDown_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicDown" RoomCommandService_ChangeMicSeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/ChangeMicSeat" RoomCommandService_ConfirmMicPublishing_FullMethodName = "/hyapp.room.v1.RoomCommandService/ConfirmMicPublishing" + RoomCommandService_MicHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicHeartbeat" RoomCommandService_SetMicMute_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicMute" RoomCommandService_ApplyRTCEvent_FullMethodName = "/hyapp.room.v1.RoomCommandService/ApplyRTCEvent" RoomCommandService_SetMicSeatLock_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicSeatLock" @@ -76,6 +77,7 @@ type RoomCommandServiceClient interface { MicDown(ctx context.Context, in *MicDownRequest, opts ...grpc.CallOption) (*MicDownResponse, error) ChangeMicSeat(ctx context.Context, in *ChangeMicSeatRequest, opts ...grpc.CallOption) (*ChangeMicSeatResponse, error) ConfirmMicPublishing(ctx context.Context, in *ConfirmMicPublishingRequest, opts ...grpc.CallOption) (*ConfirmMicPublishingResponse, error) + MicHeartbeat(ctx context.Context, in *MicHeartbeatRequest, opts ...grpc.CallOption) (*MicHeartbeatResponse, error) SetMicMute(ctx context.Context, in *SetMicMuteRequest, opts ...grpc.CallOption) (*SetMicMuteResponse, error) ApplyRTCEvent(ctx context.Context, in *ApplyRTCEventRequest, opts ...grpc.CallOption) (*ApplyRTCEventResponse, error) SetMicSeatLock(ctx context.Context, in *SetMicSeatLockRequest, opts ...grpc.CallOption) (*SetMicSeatLockResponse, error) @@ -279,6 +281,16 @@ func (c *roomCommandServiceClient) ConfirmMicPublishing(ctx context.Context, in return out, nil } +func (c *roomCommandServiceClient) MicHeartbeat(ctx context.Context, in *MicHeartbeatRequest, opts ...grpc.CallOption) (*MicHeartbeatResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MicHeartbeatResponse) + err := c.cc.Invoke(ctx, RoomCommandService_MicHeartbeat_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *roomCommandServiceClient) SetMicMute(ctx context.Context, in *SetMicMuteRequest, opts ...grpc.CallOption) (*SetMicMuteResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetMicMuteResponse) @@ -433,6 +445,7 @@ type RoomCommandServiceServer interface { MicDown(context.Context, *MicDownRequest) (*MicDownResponse, error) ChangeMicSeat(context.Context, *ChangeMicSeatRequest) (*ChangeMicSeatResponse, error) ConfirmMicPublishing(context.Context, *ConfirmMicPublishingRequest) (*ConfirmMicPublishingResponse, error) + MicHeartbeat(context.Context, *MicHeartbeatRequest) (*MicHeartbeatResponse, error) SetMicMute(context.Context, *SetMicMuteRequest) (*SetMicMuteResponse, error) ApplyRTCEvent(context.Context, *ApplyRTCEventRequest) (*ApplyRTCEventResponse, error) SetMicSeatLock(context.Context, *SetMicSeatLockRequest) (*SetMicSeatLockResponse, error) @@ -510,6 +523,9 @@ func (UnimplementedRoomCommandServiceServer) ChangeMicSeat(context.Context, *Cha func (UnimplementedRoomCommandServiceServer) ConfirmMicPublishing(context.Context, *ConfirmMicPublishingRequest) (*ConfirmMicPublishingResponse, error) { return nil, status.Error(codes.Unimplemented, "method ConfirmMicPublishing not implemented") } +func (UnimplementedRoomCommandServiceServer) MicHeartbeat(context.Context, *MicHeartbeatRequest) (*MicHeartbeatResponse, error) { + return nil, status.Error(codes.Unimplemented, "method MicHeartbeat not implemented") +} func (UnimplementedRoomCommandServiceServer) SetMicMute(context.Context, *SetMicMuteRequest) (*SetMicMuteResponse, error) { return nil, status.Error(codes.Unimplemented, "method SetMicMute not implemented") } @@ -894,6 +910,24 @@ func _RoomCommandService_ConfirmMicPublishing_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _RoomCommandService_MicHeartbeat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MicHeartbeatRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoomCommandServiceServer).MicHeartbeat(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RoomCommandService_MicHeartbeat_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoomCommandServiceServer).MicHeartbeat(ctx, req.(*MicHeartbeatRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _RoomCommandService_SetMicMute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetMicMuteRequest) if err := dec(in); err != nil { @@ -1207,6 +1241,10 @@ var RoomCommandService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ConfirmMicPublishing", Handler: _RoomCommandService_ConfirmMicPublishing_Handler, }, + { + MethodName: "MicHeartbeat", + Handler: _RoomCommandService_MicHeartbeat_Handler, + }, { MethodName: "SetMicMute", Handler: _RoomCommandService_SetMicMute_Handler, diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index 2db31bd1..533d6dc2 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -803,6 +803,570 @@ func (x *GetBalancesResponse) GetBalances() []*AssetBalance { return nil } +type HostSalaryPolicyLevel struct { + state protoimpl.MessageState `protogen:"open.v1"` + LevelNo int32 `protobuf:"varint,1,opt,name=level_no,json=levelNo,proto3" json:"level_no,omitempty"` + RequiredDiamonds int64 `protobuf:"varint,2,opt,name=required_diamonds,json=requiredDiamonds,proto3" json:"required_diamonds,omitempty"` + HostSalaryUsdMinor int64 `protobuf:"varint,3,opt,name=host_salary_usd_minor,json=hostSalaryUsdMinor,proto3" json:"host_salary_usd_minor,omitempty"` + HostCoinReward int64 `protobuf:"varint,4,opt,name=host_coin_reward,json=hostCoinReward,proto3" json:"host_coin_reward,omitempty"` + AgencySalaryUsdMinor int64 `protobuf:"varint,5,opt,name=agency_salary_usd_minor,json=agencySalaryUsdMinor,proto3" json:"agency_salary_usd_minor,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HostSalaryPolicyLevel) Reset() { + *x = HostSalaryPolicyLevel{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HostSalaryPolicyLevel) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostSalaryPolicyLevel) ProtoMessage() {} + +func (x *HostSalaryPolicyLevel) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[9] + 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 HostSalaryPolicyLevel.ProtoReflect.Descriptor instead. +func (*HostSalaryPolicyLevel) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{9} +} + +func (x *HostSalaryPolicyLevel) GetLevelNo() int32 { + if x != nil { + return x.LevelNo + } + return 0 +} + +func (x *HostSalaryPolicyLevel) GetRequiredDiamonds() int64 { + if x != nil { + return x.RequiredDiamonds + } + return 0 +} + +func (x *HostSalaryPolicyLevel) GetHostSalaryUsdMinor() int64 { + if x != nil { + return x.HostSalaryUsdMinor + } + return 0 +} + +func (x *HostSalaryPolicyLevel) GetHostCoinReward() int64 { + if x != nil { + return x.HostCoinReward + } + return 0 +} + +func (x *HostSalaryPolicyLevel) GetAgencySalaryUsdMinor() int64 { + if x != nil { + return x.AgencySalaryUsdMinor + } + return 0 +} + +func (x *HostSalaryPolicyLevel) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *HostSalaryPolicyLevel) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +type HostSalaryPolicy struct { + state protoimpl.MessageState `protogen:"open.v1"` + PolicyId uint64 `protobuf:"varint,1,opt,name=policy_id,json=policyId,proto3" json:"policy_id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + SettlementMode string `protobuf:"bytes,5,opt,name=settlement_mode,json=settlementMode,proto3" json:"settlement_mode,omitempty"` + SettlementTriggerMode string `protobuf:"bytes,6,opt,name=settlement_trigger_mode,json=settlementTriggerMode,proto3" json:"settlement_trigger_mode,omitempty"` + GiftCoinToDiamondRatio string `protobuf:"bytes,7,opt,name=gift_coin_to_diamond_ratio,json=giftCoinToDiamondRatio,proto3" json:"gift_coin_to_diamond_ratio,omitempty"` + ResidualDiamondToUsdRate string `protobuf:"bytes,8,opt,name=residual_diamond_to_usd_rate,json=residualDiamondToUsdRate,proto3" json:"residual_diamond_to_usd_rate,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,9,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,10,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + Levels []*HostSalaryPolicyLevel `protobuf:"bytes,11,rep,name=levels,proto3" json:"levels,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HostSalaryPolicy) Reset() { + *x = HostSalaryPolicy{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HostSalaryPolicy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostSalaryPolicy) ProtoMessage() {} + +func (x *HostSalaryPolicy) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[10] + 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 HostSalaryPolicy.ProtoReflect.Descriptor instead. +func (*HostSalaryPolicy) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{10} +} + +func (x *HostSalaryPolicy) GetPolicyId() uint64 { + if x != nil { + return x.PolicyId + } + return 0 +} + +func (x *HostSalaryPolicy) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *HostSalaryPolicy) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *HostSalaryPolicy) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *HostSalaryPolicy) GetSettlementMode() string { + if x != nil { + return x.SettlementMode + } + return "" +} + +func (x *HostSalaryPolicy) GetSettlementTriggerMode() string { + if x != nil { + return x.SettlementTriggerMode + } + return "" +} + +func (x *HostSalaryPolicy) GetGiftCoinToDiamondRatio() string { + if x != nil { + return x.GiftCoinToDiamondRatio + } + return "" +} + +func (x *HostSalaryPolicy) GetResidualDiamondToUsdRate() string { + if x != nil { + return x.ResidualDiamondToUsdRate + } + return "" +} + +func (x *HostSalaryPolicy) GetEffectiveFromMs() int64 { + if x != nil { + return x.EffectiveFromMs + } + return 0 +} + +func (x *HostSalaryPolicy) GetEffectiveToMs() int64 { + if x != nil { + return x.EffectiveToMs + } + return 0 +} + +func (x *HostSalaryPolicy) GetLevels() []*HostSalaryPolicyLevel { + if x != nil { + return x.Levels + } + return nil +} + +type GetActiveHostSalaryPolicyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + SettlementMode string `protobuf:"bytes,4,opt,name=settlement_mode,json=settlementMode,proto3" json:"settlement_mode,omitempty"` + SettlementTriggerMode string `protobuf:"bytes,5,opt,name=settlement_trigger_mode,json=settlementTriggerMode,proto3" json:"settlement_trigger_mode,omitempty"` + NowMs int64 `protobuf:"varint,6,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetActiveHostSalaryPolicyRequest) Reset() { + *x = GetActiveHostSalaryPolicyRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetActiveHostSalaryPolicyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetActiveHostSalaryPolicyRequest) ProtoMessage() {} + +func (x *GetActiveHostSalaryPolicyRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[11] + 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 GetActiveHostSalaryPolicyRequest.ProtoReflect.Descriptor instead. +func (*GetActiveHostSalaryPolicyRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{11} +} + +func (x *GetActiveHostSalaryPolicyRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *GetActiveHostSalaryPolicyRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *GetActiveHostSalaryPolicyRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *GetActiveHostSalaryPolicyRequest) GetSettlementMode() string { + if x != nil { + return x.SettlementMode + } + return "" +} + +func (x *GetActiveHostSalaryPolicyRequest) GetSettlementTriggerMode() string { + if x != nil { + return x.SettlementTriggerMode + } + return "" +} + +func (x *GetActiveHostSalaryPolicyRequest) GetNowMs() int64 { + if x != nil { + return x.NowMs + } + return 0 +} + +type GetActiveHostSalaryPolicyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` + Policy *HostSalaryPolicy `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetActiveHostSalaryPolicyResponse) Reset() { + *x = GetActiveHostSalaryPolicyResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetActiveHostSalaryPolicyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetActiveHostSalaryPolicyResponse) ProtoMessage() {} + +func (x *GetActiveHostSalaryPolicyResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[12] + 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 GetActiveHostSalaryPolicyResponse.ProtoReflect.Descriptor instead. +func (*GetActiveHostSalaryPolicyResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{12} +} + +func (x *GetActiveHostSalaryPolicyResponse) GetFound() bool { + if x != nil { + return x.Found + } + return false +} + +func (x *GetActiveHostSalaryPolicyResponse) GetPolicy() *HostSalaryPolicy { + if x != nil { + return x.Policy + } + return nil +} + +type HostSalaryProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + HostUserId int64 `protobuf:"varint,1,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` + CycleKey string `protobuf:"bytes,2,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + AgencyOwnerUserId int64 `protobuf:"varint,4,opt,name=agency_owner_user_id,json=agencyOwnerUserId,proto3" json:"agency_owner_user_id,omitempty"` + TotalDiamonds int64 `protobuf:"varint,5,opt,name=total_diamonds,json=totalDiamonds,proto3" json:"total_diamonds,omitempty"` + GiftDiamondTotal int64 `protobuf:"varint,6,opt,name=gift_diamond_total,json=giftDiamondTotal,proto3" json:"gift_diamond_total,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HostSalaryProgress) Reset() { + *x = HostSalaryProgress{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HostSalaryProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HostSalaryProgress) ProtoMessage() {} + +func (x *HostSalaryProgress) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[13] + 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 HostSalaryProgress.ProtoReflect.Descriptor instead. +func (*HostSalaryProgress) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{13} +} + +func (x *HostSalaryProgress) GetHostUserId() int64 { + if x != nil { + return x.HostUserId + } + return 0 +} + +func (x *HostSalaryProgress) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *HostSalaryProgress) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *HostSalaryProgress) GetAgencyOwnerUserId() int64 { + if x != nil { + return x.AgencyOwnerUserId + } + return 0 +} + +func (x *HostSalaryProgress) GetTotalDiamonds() int64 { + if x != nil { + return x.TotalDiamonds + } + return 0 +} + +func (x *HostSalaryProgress) GetGiftDiamondTotal() int64 { + if x != nil { + return x.GiftDiamondTotal + } + return 0 +} + +func (x *HostSalaryProgress) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +type GetHostSalaryProgressRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + HostUserId int64 `protobuf:"varint,3,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` + CycleKey string `protobuf:"bytes,4,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + NowMs int64 `protobuf:"varint,5,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetHostSalaryProgressRequest) Reset() { + *x = GetHostSalaryProgressRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetHostSalaryProgressRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetHostSalaryProgressRequest) ProtoMessage() {} + +func (x *GetHostSalaryProgressRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[14] + 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 GetHostSalaryProgressRequest.ProtoReflect.Descriptor instead. +func (*GetHostSalaryProgressRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{14} +} + +func (x *GetHostSalaryProgressRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *GetHostSalaryProgressRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *GetHostSalaryProgressRequest) GetHostUserId() int64 { + if x != nil { + return x.HostUserId + } + return 0 +} + +func (x *GetHostSalaryProgressRequest) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *GetHostSalaryProgressRequest) GetNowMs() int64 { + if x != nil { + return x.NowMs + } + return 0 +} + +type GetHostSalaryProgressResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Progress *HostSalaryProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetHostSalaryProgressResponse) Reset() { + *x = GetHostSalaryProgressResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetHostSalaryProgressResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetHostSalaryProgressResponse) ProtoMessage() {} + +func (x *GetHostSalaryProgressResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[15] + 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 GetHostSalaryProgressResponse.ProtoReflect.Descriptor instead. +func (*GetHostSalaryProgressResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{15} +} + +func (x *GetHostSalaryProgressResponse) GetProgress() *HostSalaryProgress { + if x != nil { + return x.Progress + } + return nil +} + // AdminCreditAssetRequest 是后台手动入账/调账的最小审计命令。 type AdminCreditAssetRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -820,7 +1384,7 @@ type AdminCreditAssetRequest struct { func (x *AdminCreditAssetRequest) Reset() { *x = AdminCreditAssetRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[9] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -832,7 +1396,7 @@ func (x *AdminCreditAssetRequest) String() string { func (*AdminCreditAssetRequest) ProtoMessage() {} func (x *AdminCreditAssetRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[9] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -845,7 +1409,7 @@ func (x *AdminCreditAssetRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCreditAssetRequest.ProtoReflect.Descriptor instead. func (*AdminCreditAssetRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{9} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{16} } func (x *AdminCreditAssetRequest) GetCommandId() string { @@ -914,7 +1478,7 @@ type AdminCreditAssetResponse struct { func (x *AdminCreditAssetResponse) Reset() { *x = AdminCreditAssetResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[10] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -926,7 +1490,7 @@ func (x *AdminCreditAssetResponse) String() string { func (*AdminCreditAssetResponse) ProtoMessage() {} func (x *AdminCreditAssetResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[10] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -939,7 +1503,7 @@ func (x *AdminCreditAssetResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCreditAssetResponse.ProtoReflect.Descriptor instead. func (*AdminCreditAssetResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{10} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{17} } func (x *AdminCreditAssetResponse) GetTransactionId() string { @@ -976,7 +1540,7 @@ type AdminCreditCoinSellerStockRequest struct { func (x *AdminCreditCoinSellerStockRequest) Reset() { *x = AdminCreditCoinSellerStockRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[11] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -988,7 +1552,7 @@ func (x *AdminCreditCoinSellerStockRequest) String() string { func (*AdminCreditCoinSellerStockRequest) ProtoMessage() {} func (x *AdminCreditCoinSellerStockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[11] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1001,7 +1565,7 @@ func (x *AdminCreditCoinSellerStockRequest) ProtoReflect() protoreflect.Message // Deprecated: Use AdminCreditCoinSellerStockRequest.ProtoReflect.Descriptor instead. func (*AdminCreditCoinSellerStockRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{11} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{18} } func (x *AdminCreditCoinSellerStockRequest) GetCommandId() string { @@ -1098,7 +1662,7 @@ type AdminCreditCoinSellerStockResponse struct { func (x *AdminCreditCoinSellerStockResponse) Reset() { *x = AdminCreditCoinSellerStockResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[12] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1110,7 +1674,7 @@ func (x *AdminCreditCoinSellerStockResponse) String() string { func (*AdminCreditCoinSellerStockResponse) ProtoMessage() {} func (x *AdminCreditCoinSellerStockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[12] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1123,7 +1687,7 @@ func (x *AdminCreditCoinSellerStockResponse) ProtoReflect() protoreflect.Message // Deprecated: Use AdminCreditCoinSellerStockResponse.ProtoReflect.Descriptor instead. func (*AdminCreditCoinSellerStockResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{12} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{19} } func (x *AdminCreditCoinSellerStockResponse) GetTransactionId() string { @@ -1207,7 +1771,7 @@ type TransferCoinFromSellerRequest struct { func (x *TransferCoinFromSellerRequest) Reset() { *x = TransferCoinFromSellerRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[13] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1219,7 +1783,7 @@ func (x *TransferCoinFromSellerRequest) String() string { func (*TransferCoinFromSellerRequest) ProtoMessage() {} func (x *TransferCoinFromSellerRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[13] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1232,7 +1796,7 @@ func (x *TransferCoinFromSellerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TransferCoinFromSellerRequest.ProtoReflect.Descriptor instead. func (*TransferCoinFromSellerRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{13} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{20} } func (x *TransferCoinFromSellerRequest) GetCommandId() string { @@ -1310,7 +1874,7 @@ type TransferCoinFromSellerResponse struct { func (x *TransferCoinFromSellerResponse) Reset() { *x = TransferCoinFromSellerResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[14] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1322,7 +1886,7 @@ func (x *TransferCoinFromSellerResponse) String() string { func (*TransferCoinFromSellerResponse) ProtoMessage() {} func (x *TransferCoinFromSellerResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[14] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1335,7 +1899,7 @@ func (x *TransferCoinFromSellerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TransferCoinFromSellerResponse.ProtoReflect.Descriptor instead. func (*TransferCoinFromSellerResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{14} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{21} } func (x *TransferCoinFromSellerResponse) GetTransactionId() string { @@ -1441,7 +2005,7 @@ type Resource struct { func (x *Resource) Reset() { *x = Resource{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[15] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1453,7 +2017,7 @@ func (x *Resource) String() string { func (*Resource) ProtoMessage() {} func (x *Resource) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[15] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1466,7 +2030,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message { // Deprecated: Use Resource.ProtoReflect.Descriptor instead. func (*Resource) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{15} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{22} } func (x *Resource) GetAppCode() string { @@ -1657,7 +2221,7 @@ type ResourceGroupItem struct { func (x *ResourceGroupItem) Reset() { *x = ResourceGroupItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[16] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1669,7 +2233,7 @@ func (x *ResourceGroupItem) String() string { func (*ResourceGroupItem) ProtoMessage() {} func (x *ResourceGroupItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[16] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1682,7 +2246,7 @@ func (x *ResourceGroupItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupItem.ProtoReflect.Descriptor instead. func (*ResourceGroupItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{16} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{23} } func (x *ResourceGroupItem) GetGroupItemId() int64 { @@ -1789,7 +2353,7 @@ type ResourceGroup struct { func (x *ResourceGroup) Reset() { *x = ResourceGroup{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[17] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1801,7 +2365,7 @@ func (x *ResourceGroup) String() string { func (*ResourceGroup) ProtoMessage() {} func (x *ResourceGroup) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[17] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1814,7 +2378,7 @@ func (x *ResourceGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroup.ProtoReflect.Descriptor instead. func (*ResourceGroup) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{17} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{24} } func (x *ResourceGroup) GetAppCode() string { @@ -1931,7 +2495,7 @@ type GiftConfig struct { func (x *GiftConfig) Reset() { *x = GiftConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[18] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1943,7 +2507,7 @@ func (x *GiftConfig) String() string { func (*GiftConfig) ProtoMessage() {} func (x *GiftConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[18] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1956,7 +2520,7 @@ func (x *GiftConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftConfig.ProtoReflect.Descriptor instead. func (*GiftConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{18} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{25} } func (x *GiftConfig) GetAppCode() string { @@ -2131,7 +2695,7 @@ type GiftTypeConfig struct { func (x *GiftTypeConfig) Reset() { *x = GiftTypeConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[19] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2143,7 +2707,7 @@ func (x *GiftTypeConfig) String() string { func (*GiftTypeConfig) ProtoMessage() {} func (x *GiftTypeConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[19] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2156,7 +2720,7 @@ func (x *GiftTypeConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftTypeConfig.ProtoReflect.Descriptor instead. func (*GiftTypeConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{19} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{26} } func (x *GiftTypeConfig) GetAppCode() string { @@ -2252,7 +2816,7 @@ type ResourceShopItem struct { func (x *ResourceShopItem) Reset() { *x = ResourceShopItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[20] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2264,7 +2828,7 @@ func (x *ResourceShopItem) String() string { func (*ResourceShopItem) ProtoMessage() {} func (x *ResourceShopItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[20] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2277,7 +2841,7 @@ func (x *ResourceShopItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItem.ProtoReflect.Descriptor instead. func (*ResourceShopItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{20} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{27} } func (x *ResourceShopItem) GetAppCode() string { @@ -2407,7 +2971,7 @@ type UserResourceEntitlement struct { func (x *UserResourceEntitlement) Reset() { *x = UserResourceEntitlement{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[21] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2419,7 +2983,7 @@ func (x *UserResourceEntitlement) String() string { func (*UserResourceEntitlement) ProtoMessage() {} func (x *UserResourceEntitlement) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[21] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2432,7 +2996,7 @@ func (x *UserResourceEntitlement) ProtoReflect() protoreflect.Message { // Deprecated: Use UserResourceEntitlement.ProtoReflect.Descriptor instead. func (*UserResourceEntitlement) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{21} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{28} } func (x *UserResourceEntitlement) GetAppCode() string { @@ -2551,7 +3115,7 @@ type ResourceGrantItem struct { func (x *ResourceGrantItem) Reset() { *x = ResourceGrantItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2563,7 +3127,7 @@ func (x *ResourceGrantItem) String() string { func (*ResourceGrantItem) ProtoMessage() {} func (x *ResourceGrantItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2576,7 +3140,7 @@ func (x *ResourceGrantItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrantItem.ProtoReflect.Descriptor instead. func (*ResourceGrantItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{22} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{29} } func (x *ResourceGrantItem) GetGrantItemId() int64 { @@ -2670,7 +3234,7 @@ type ResourceGrant struct { func (x *ResourceGrant) Reset() { *x = ResourceGrant{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2682,7 +3246,7 @@ func (x *ResourceGrant) String() string { func (*ResourceGrant) ProtoMessage() {} func (x *ResourceGrant) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2695,7 +3259,7 @@ func (x *ResourceGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrant.ProtoReflect.Descriptor instead. func (*ResourceGrant) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{23} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{30} } func (x *ResourceGrant) GetAppCode() string { @@ -2804,7 +3368,7 @@ type ResourceGroupItemInput struct { func (x *ResourceGroupItemInput) Reset() { *x = ResourceGroupItemInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2816,7 +3380,7 @@ func (x *ResourceGroupItemInput) String() string { func (*ResourceGroupItemInput) ProtoMessage() {} func (x *ResourceGroupItemInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2829,7 +3393,7 @@ func (x *ResourceGroupItemInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupItemInput.ProtoReflect.Descriptor instead. func (*ResourceGroupItemInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{24} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{31} } func (x *ResourceGroupItemInput) GetResourceId() int64 { @@ -2898,7 +3462,7 @@ type ListResourcesRequest struct { func (x *ListResourcesRequest) Reset() { *x = ListResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2910,7 +3474,7 @@ func (x *ListResourcesRequest) String() string { func (*ListResourcesRequest) ProtoMessage() {} func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2923,7 +3487,7 @@ func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesRequest.ProtoReflect.Descriptor instead. func (*ListResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{25} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{32} } func (x *ListResourcesRequest) GetRequestId() string { @@ -2999,7 +3563,7 @@ type ListResourcesResponse struct { func (x *ListResourcesResponse) Reset() { *x = ListResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3011,7 +3575,7 @@ func (x *ListResourcesResponse) String() string { func (*ListResourcesResponse) ProtoMessage() {} func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3024,7 +3588,7 @@ func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesResponse.ProtoReflect.Descriptor instead. func (*ListResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{26} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{33} } func (x *ListResourcesResponse) GetResources() []*Resource { @@ -3052,7 +3616,7 @@ type GetResourceRequest struct { func (x *GetResourceRequest) Reset() { *x = GetResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3064,7 +3628,7 @@ func (x *GetResourceRequest) String() string { func (*GetResourceRequest) ProtoMessage() {} func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3077,7 +3641,7 @@ func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceRequest.ProtoReflect.Descriptor instead. func (*GetResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{27} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{34} } func (x *GetResourceRequest) GetRequestId() string { @@ -3110,7 +3674,7 @@ type GetResourceResponse struct { func (x *GetResourceResponse) Reset() { *x = GetResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3122,7 +3686,7 @@ func (x *GetResourceResponse) String() string { func (*GetResourceResponse) ProtoMessage() {} func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3135,7 +3699,7 @@ func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceResponse.ProtoReflect.Descriptor instead. func (*GetResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{28} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{35} } func (x *GetResourceResponse) GetResource() *Resource { @@ -3174,7 +3738,7 @@ type CreateResourceRequest struct { func (x *CreateResourceRequest) Reset() { *x = CreateResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3186,7 +3750,7 @@ func (x *CreateResourceRequest) String() string { func (*CreateResourceRequest) ProtoMessage() {} func (x *CreateResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3199,7 +3763,7 @@ func (x *CreateResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateResourceRequest.ProtoReflect.Descriptor instead. func (*CreateResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{29} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{36} } func (x *CreateResourceRequest) GetRequestId() string { @@ -3379,7 +3943,7 @@ type UpdateResourceRequest struct { func (x *UpdateResourceRequest) Reset() { *x = UpdateResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3391,7 +3955,7 @@ func (x *UpdateResourceRequest) String() string { func (*UpdateResourceRequest) ProtoMessage() {} func (x *UpdateResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3404,7 +3968,7 @@ func (x *UpdateResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourceRequest.ProtoReflect.Descriptor instead. func (*UpdateResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{30} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{37} } func (x *UpdateResourceRequest) GetRequestId() string { @@ -3574,7 +4138,7 @@ type SetResourceStatusRequest struct { func (x *SetResourceStatusRequest) Reset() { *x = SetResourceStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3586,7 +4150,7 @@ func (x *SetResourceStatusRequest) String() string { func (*SetResourceStatusRequest) ProtoMessage() {} func (x *SetResourceStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3599,7 +4163,7 @@ func (x *SetResourceStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{31} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{38} } func (x *SetResourceStatusRequest) GetRequestId() string { @@ -3646,7 +4210,7 @@ type ResourceResponse struct { func (x *ResourceResponse) Reset() { *x = ResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3658,7 +4222,7 @@ func (x *ResourceResponse) String() string { func (*ResourceResponse) ProtoMessage() {} func (x *ResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3671,7 +4235,7 @@ func (x *ResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceResponse.ProtoReflect.Descriptor instead. func (*ResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{32} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{39} } func (x *ResourceResponse) GetResource() *Resource { @@ -3696,7 +4260,7 @@ type ListResourceGroupsRequest struct { func (x *ListResourceGroupsRequest) Reset() { *x = ListResourceGroupsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3708,7 +4272,7 @@ func (x *ListResourceGroupsRequest) String() string { func (*ListResourceGroupsRequest) ProtoMessage() {} func (x *ListResourceGroupsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3721,7 +4285,7 @@ func (x *ListResourceGroupsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGroupsRequest.ProtoReflect.Descriptor instead. func (*ListResourceGroupsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{33} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{40} } func (x *ListResourceGroupsRequest) GetRequestId() string { @@ -3783,7 +4347,7 @@ type ListResourceGroupsResponse struct { func (x *ListResourceGroupsResponse) Reset() { *x = ListResourceGroupsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3795,7 +4359,7 @@ func (x *ListResourceGroupsResponse) String() string { func (*ListResourceGroupsResponse) ProtoMessage() {} func (x *ListResourceGroupsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3808,7 +4372,7 @@ func (x *ListResourceGroupsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGroupsResponse.ProtoReflect.Descriptor instead. func (*ListResourceGroupsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{34} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{41} } func (x *ListResourceGroupsResponse) GetGroups() []*ResourceGroup { @@ -3836,7 +4400,7 @@ type GetResourceGroupRequest struct { func (x *GetResourceGroupRequest) Reset() { *x = GetResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3848,7 +4412,7 @@ func (x *GetResourceGroupRequest) String() string { func (*GetResourceGroupRequest) ProtoMessage() {} func (x *GetResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3861,7 +4425,7 @@ func (x *GetResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceGroupRequest.ProtoReflect.Descriptor instead. func (*GetResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{35} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{42} } func (x *GetResourceGroupRequest) GetRequestId() string { @@ -3894,7 +4458,7 @@ type GetResourceGroupResponse struct { func (x *GetResourceGroupResponse) Reset() { *x = GetResourceGroupResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3906,7 +4470,7 @@ func (x *GetResourceGroupResponse) String() string { func (*GetResourceGroupResponse) ProtoMessage() {} func (x *GetResourceGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3919,7 +4483,7 @@ func (x *GetResourceGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceGroupResponse.ProtoReflect.Descriptor instead. func (*GetResourceGroupResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{36} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{43} } func (x *GetResourceGroupResponse) GetGroup() *ResourceGroup { @@ -3946,7 +4510,7 @@ type CreateResourceGroupRequest struct { func (x *CreateResourceGroupRequest) Reset() { *x = CreateResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3958,7 +4522,7 @@ func (x *CreateResourceGroupRequest) String() string { func (*CreateResourceGroupRequest) ProtoMessage() {} func (x *CreateResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3971,7 +4535,7 @@ func (x *CreateResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateResourceGroupRequest.ProtoReflect.Descriptor instead. func (*CreateResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{37} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{44} } func (x *CreateResourceGroupRequest) GetRequestId() string { @@ -4055,7 +4619,7 @@ type UpdateResourceGroupRequest struct { func (x *UpdateResourceGroupRequest) Reset() { *x = UpdateResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4067,7 +4631,7 @@ func (x *UpdateResourceGroupRequest) String() string { func (*UpdateResourceGroupRequest) ProtoMessage() {} func (x *UpdateResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4080,7 +4644,7 @@ func (x *UpdateResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourceGroupRequest.ProtoReflect.Descriptor instead. func (*UpdateResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{38} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{45} } func (x *UpdateResourceGroupRequest) GetRequestId() string { @@ -4166,7 +4730,7 @@ type SetResourceGroupStatusRequest struct { func (x *SetResourceGroupStatusRequest) Reset() { *x = SetResourceGroupStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4178,7 +4742,7 @@ func (x *SetResourceGroupStatusRequest) String() string { func (*SetResourceGroupStatusRequest) ProtoMessage() {} func (x *SetResourceGroupStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4191,7 +4755,7 @@ func (x *SetResourceGroupStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceGroupStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceGroupStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{39} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{46} } func (x *SetResourceGroupStatusRequest) GetRequestId() string { @@ -4238,7 +4802,7 @@ type ResourceGroupResponse struct { func (x *ResourceGroupResponse) Reset() { *x = ResourceGroupResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4250,7 +4814,7 @@ func (x *ResourceGroupResponse) String() string { func (*ResourceGroupResponse) ProtoMessage() {} func (x *ResourceGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4263,7 +4827,7 @@ func (x *ResourceGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupResponse.ProtoReflect.Descriptor instead. func (*ResourceGroupResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{40} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{47} } func (x *ResourceGroupResponse) GetGroup() *ResourceGroup { @@ -4290,7 +4854,7 @@ type ListGiftConfigsRequest struct { func (x *ListGiftConfigsRequest) Reset() { *x = ListGiftConfigsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4302,7 +4866,7 @@ func (x *ListGiftConfigsRequest) String() string { func (*ListGiftConfigsRequest) ProtoMessage() {} func (x *ListGiftConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4315,7 +4879,7 @@ func (x *ListGiftConfigsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftConfigsRequest.ProtoReflect.Descriptor instead. func (*ListGiftConfigsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{41} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{48} } func (x *ListGiftConfigsRequest) GetRequestId() string { @@ -4391,7 +4955,7 @@ type ListGiftConfigsResponse struct { func (x *ListGiftConfigsResponse) Reset() { *x = ListGiftConfigsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4403,7 +4967,7 @@ func (x *ListGiftConfigsResponse) String() string { func (*ListGiftConfigsResponse) ProtoMessage() {} func (x *ListGiftConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4416,7 +4980,7 @@ func (x *ListGiftConfigsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftConfigsResponse.ProtoReflect.Descriptor instead. func (*ListGiftConfigsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{42} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{49} } func (x *ListGiftConfigsResponse) GetGifts() []*GiftConfig { @@ -4445,7 +5009,7 @@ type ListGiftTypeConfigsRequest struct { func (x *ListGiftTypeConfigsRequest) Reset() { *x = ListGiftTypeConfigsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4457,7 +5021,7 @@ func (x *ListGiftTypeConfigsRequest) String() string { func (*ListGiftTypeConfigsRequest) ProtoMessage() {} func (x *ListGiftTypeConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4470,7 +5034,7 @@ func (x *ListGiftTypeConfigsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftTypeConfigsRequest.ProtoReflect.Descriptor instead. func (*ListGiftTypeConfigsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{43} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{50} } func (x *ListGiftTypeConfigsRequest) GetRequestId() string { @@ -4510,7 +5074,7 @@ type ListGiftTypeConfigsResponse struct { func (x *ListGiftTypeConfigsResponse) Reset() { *x = ListGiftTypeConfigsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4522,7 +5086,7 @@ func (x *ListGiftTypeConfigsResponse) String() string { func (*ListGiftTypeConfigsResponse) ProtoMessage() {} func (x *ListGiftTypeConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4535,7 +5099,7 @@ func (x *ListGiftTypeConfigsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftTypeConfigsResponse.ProtoReflect.Descriptor instead. func (*ListGiftTypeConfigsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{44} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{51} } func (x *ListGiftTypeConfigsResponse) GetGiftTypes() []*GiftTypeConfig { @@ -4561,7 +5125,7 @@ type UpsertGiftTypeConfigRequest struct { func (x *UpsertGiftTypeConfigRequest) Reset() { *x = UpsertGiftTypeConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4573,7 +5137,7 @@ func (x *UpsertGiftTypeConfigRequest) String() string { func (*UpsertGiftTypeConfigRequest) ProtoMessage() {} func (x *UpsertGiftTypeConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4586,7 +5150,7 @@ func (x *UpsertGiftTypeConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertGiftTypeConfigRequest.ProtoReflect.Descriptor instead. func (*UpsertGiftTypeConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{45} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{52} } func (x *UpsertGiftTypeConfigRequest) GetRequestId() string { @@ -4654,7 +5218,7 @@ type GiftTypeConfigResponse struct { func (x *GiftTypeConfigResponse) Reset() { *x = GiftTypeConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4666,7 +5230,7 @@ func (x *GiftTypeConfigResponse) String() string { func (*GiftTypeConfigResponse) ProtoMessage() {} func (x *GiftTypeConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4679,7 +5243,7 @@ func (x *GiftTypeConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftTypeConfigResponse.ProtoReflect.Descriptor instead. func (*GiftTypeConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{46} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{53} } func (x *GiftTypeConfigResponse) GetGiftType() *GiftTypeConfig { @@ -4717,7 +5281,7 @@ type CreateGiftConfigRequest struct { func (x *CreateGiftConfigRequest) Reset() { *x = CreateGiftConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4729,7 +5293,7 @@ func (x *CreateGiftConfigRequest) String() string { func (*CreateGiftConfigRequest) ProtoMessage() {} func (x *CreateGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4742,7 +5306,7 @@ func (x *CreateGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateGiftConfigRequest.ProtoReflect.Descriptor instead. func (*CreateGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{47} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{54} } func (x *CreateGiftConfigRequest) GetRequestId() string { @@ -4913,7 +5477,7 @@ type UpdateGiftConfigRequest struct { func (x *UpdateGiftConfigRequest) Reset() { *x = UpdateGiftConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4925,7 +5489,7 @@ func (x *UpdateGiftConfigRequest) String() string { func (*UpdateGiftConfigRequest) ProtoMessage() {} func (x *UpdateGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4938,7 +5502,7 @@ func (x *UpdateGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateGiftConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{48} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{55} } func (x *UpdateGiftConfigRequest) GetRequestId() string { @@ -5094,7 +5658,7 @@ type SetGiftConfigStatusRequest struct { func (x *SetGiftConfigStatusRequest) Reset() { *x = SetGiftConfigStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5106,7 +5670,7 @@ func (x *SetGiftConfigStatusRequest) String() string { func (*SetGiftConfigStatusRequest) ProtoMessage() {} func (x *SetGiftConfigStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5119,7 +5683,7 @@ func (x *SetGiftConfigStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetGiftConfigStatusRequest.ProtoReflect.Descriptor instead. func (*SetGiftConfigStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{49} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{56} } func (x *SetGiftConfigStatusRequest) GetRequestId() string { @@ -5166,7 +5730,7 @@ type GiftConfigResponse struct { func (x *GiftConfigResponse) Reset() { *x = GiftConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5178,7 +5742,7 @@ func (x *GiftConfigResponse) String() string { func (*GiftConfigResponse) ProtoMessage() {} func (x *GiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5191,7 +5755,7 @@ func (x *GiftConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftConfigResponse.ProtoReflect.Descriptor instead. func (*GiftConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{50} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{57} } func (x *GiftConfigResponse) GetGift() *GiftConfig { @@ -5218,7 +5782,7 @@ type GrantResourceRequest struct { func (x *GrantResourceRequest) Reset() { *x = GrantResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5230,7 +5794,7 @@ func (x *GrantResourceRequest) String() string { func (*GrantResourceRequest) ProtoMessage() {} func (x *GrantResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5243,7 +5807,7 @@ func (x *GrantResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantResourceRequest.ProtoReflect.Descriptor instead. func (*GrantResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{51} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{58} } func (x *GrantResourceRequest) GetCommandId() string { @@ -5324,7 +5888,7 @@ type GrantResourceGroupRequest struct { func (x *GrantResourceGroupRequest) Reset() { *x = GrantResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5336,7 +5900,7 @@ func (x *GrantResourceGroupRequest) String() string { func (*GrantResourceGroupRequest) ProtoMessage() {} func (x *GrantResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5349,7 +5913,7 @@ func (x *GrantResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantResourceGroupRequest.ProtoReflect.Descriptor instead. func (*GrantResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{52} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{59} } func (x *GrantResourceGroupRequest) GetCommandId() string { @@ -5410,7 +5974,7 @@ type ResourceGrantResponse struct { func (x *ResourceGrantResponse) Reset() { *x = ResourceGrantResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5422,7 +5986,7 @@ func (x *ResourceGrantResponse) String() string { func (*ResourceGrantResponse) ProtoMessage() {} func (x *ResourceGrantResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5435,7 +5999,7 @@ func (x *ResourceGrantResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrantResponse.ProtoReflect.Descriptor instead. func (*ResourceGrantResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{53} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{60} } func (x *ResourceGrantResponse) GetGrant() *ResourceGrant { @@ -5458,7 +6022,7 @@ type ListUserResourcesRequest struct { func (x *ListUserResourcesRequest) Reset() { *x = ListUserResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5470,7 +6034,7 @@ func (x *ListUserResourcesRequest) String() string { func (*ListUserResourcesRequest) ProtoMessage() {} func (x *ListUserResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5483,7 +6047,7 @@ func (x *ListUserResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserResourcesRequest.ProtoReflect.Descriptor instead. func (*ListUserResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{54} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{61} } func (x *ListUserResourcesRequest) GetRequestId() string { @@ -5530,7 +6094,7 @@ type ListUserResourcesResponse struct { func (x *ListUserResourcesResponse) Reset() { *x = ListUserResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5542,7 +6106,7 @@ func (x *ListUserResourcesResponse) String() string { func (*ListUserResourcesResponse) ProtoMessage() {} func (x *ListUserResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5555,7 +6119,7 @@ func (x *ListUserResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserResourcesResponse.ProtoReflect.Descriptor instead. func (*ListUserResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{55} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{62} } func (x *ListUserResourcesResponse) GetResources() []*UserResourceEntitlement { @@ -5578,7 +6142,7 @@ type EquipUserResourceRequest struct { func (x *EquipUserResourceRequest) Reset() { *x = EquipUserResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5590,7 +6154,7 @@ func (x *EquipUserResourceRequest) String() string { func (*EquipUserResourceRequest) ProtoMessage() {} func (x *EquipUserResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5603,7 +6167,7 @@ func (x *EquipUserResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EquipUserResourceRequest.ProtoReflect.Descriptor instead. func (*EquipUserResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{56} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{63} } func (x *EquipUserResourceRequest) GetRequestId() string { @@ -5650,7 +6214,7 @@ type EquipUserResourceResponse struct { func (x *EquipUserResourceResponse) Reset() { *x = EquipUserResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5662,7 +6226,7 @@ func (x *EquipUserResourceResponse) String() string { func (*EquipUserResourceResponse) ProtoMessage() {} func (x *EquipUserResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5675,7 +6239,7 @@ func (x *EquipUserResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EquipUserResourceResponse.ProtoReflect.Descriptor instead. func (*EquipUserResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{57} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{64} } func (x *EquipUserResourceResponse) GetResource() *UserResourceEntitlement { @@ -5697,7 +6261,7 @@ type UnequipUserResourceRequest struct { func (x *UnequipUserResourceRequest) Reset() { *x = UnequipUserResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5709,7 +6273,7 @@ func (x *UnequipUserResourceRequest) String() string { func (*UnequipUserResourceRequest) ProtoMessage() {} func (x *UnequipUserResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5722,7 +6286,7 @@ func (x *UnequipUserResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnequipUserResourceRequest.ProtoReflect.Descriptor instead. func (*UnequipUserResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{58} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{65} } func (x *UnequipUserResourceRequest) GetRequestId() string { @@ -5764,7 +6328,7 @@ type UnequipUserResourceResponse struct { func (x *UnequipUserResourceResponse) Reset() { *x = UnequipUserResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5776,7 +6340,7 @@ func (x *UnequipUserResourceResponse) String() string { func (*UnequipUserResourceResponse) ProtoMessage() {} func (x *UnequipUserResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5789,7 +6353,7 @@ func (x *UnequipUserResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnequipUserResourceResponse.ProtoReflect.Descriptor instead. func (*UnequipUserResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{59} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{66} } func (x *UnequipUserResourceResponse) GetResourceType() string { @@ -5825,7 +6389,7 @@ type BatchGetUserEquippedResourcesRequest struct { func (x *BatchGetUserEquippedResourcesRequest) Reset() { *x = BatchGetUserEquippedResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5837,7 +6401,7 @@ func (x *BatchGetUserEquippedResourcesRequest) String() string { func (*BatchGetUserEquippedResourcesRequest) ProtoMessage() {} func (x *BatchGetUserEquippedResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5850,7 +6414,7 @@ func (x *BatchGetUserEquippedResourcesRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use BatchGetUserEquippedResourcesRequest.ProtoReflect.Descriptor instead. func (*BatchGetUserEquippedResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{60} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{67} } func (x *BatchGetUserEquippedResourcesRequest) GetRequestId() string { @@ -5891,7 +6455,7 @@ type UserEquippedResources struct { func (x *UserEquippedResources) Reset() { *x = UserEquippedResources{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5903,7 +6467,7 @@ func (x *UserEquippedResources) String() string { func (*UserEquippedResources) ProtoMessage() {} func (x *UserEquippedResources) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5916,7 +6480,7 @@ func (x *UserEquippedResources) ProtoReflect() protoreflect.Message { // Deprecated: Use UserEquippedResources.ProtoReflect.Descriptor instead. func (*UserEquippedResources) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{61} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{68} } func (x *UserEquippedResources) GetUserId() int64 { @@ -5942,7 +6506,7 @@ type BatchGetUserEquippedResourcesResponse struct { func (x *BatchGetUserEquippedResourcesResponse) Reset() { *x = BatchGetUserEquippedResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5954,7 +6518,7 @@ func (x *BatchGetUserEquippedResourcesResponse) String() string { func (*BatchGetUserEquippedResourcesResponse) ProtoMessage() {} func (x *BatchGetUserEquippedResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5967,7 +6531,7 @@ func (x *BatchGetUserEquippedResourcesResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use BatchGetUserEquippedResourcesResponse.ProtoReflect.Descriptor instead. func (*BatchGetUserEquippedResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{62} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{69} } func (x *BatchGetUserEquippedResourcesResponse) GetUsers() []*UserEquippedResources { @@ -5991,7 +6555,7 @@ type ListResourceGrantsRequest struct { func (x *ListResourceGrantsRequest) Reset() { *x = ListResourceGrantsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6003,7 +6567,7 @@ func (x *ListResourceGrantsRequest) String() string { func (*ListResourceGrantsRequest) ProtoMessage() {} func (x *ListResourceGrantsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6016,7 +6580,7 @@ func (x *ListResourceGrantsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGrantsRequest.ProtoReflect.Descriptor instead. func (*ListResourceGrantsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{63} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{70} } func (x *ListResourceGrantsRequest) GetRequestId() string { @@ -6071,7 +6635,7 @@ type ListResourceGrantsResponse struct { func (x *ListResourceGrantsResponse) Reset() { *x = ListResourceGrantsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6083,7 +6647,7 @@ func (x *ListResourceGrantsResponse) String() string { func (*ListResourceGrantsResponse) ProtoMessage() {} func (x *ListResourceGrantsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6096,7 +6660,7 @@ func (x *ListResourceGrantsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGrantsResponse.ProtoReflect.Descriptor instead. func (*ListResourceGrantsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{64} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{71} } func (x *ListResourceGrantsResponse) GetGrants() []*ResourceGrant { @@ -6128,7 +6692,7 @@ type ResourceShopItemInput struct { func (x *ResourceShopItemInput) Reset() { *x = ResourceShopItemInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6140,7 +6704,7 @@ func (x *ResourceShopItemInput) String() string { func (*ResourceShopItemInput) ProtoMessage() {} func (x *ResourceShopItemInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6153,7 +6717,7 @@ func (x *ResourceShopItemInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItemInput.ProtoReflect.Descriptor instead. func (*ResourceShopItemInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{65} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{72} } func (x *ResourceShopItemInput) GetShopItemId() int64 { @@ -6221,7 +6785,7 @@ type ListResourceShopItemsRequest struct { func (x *ListResourceShopItemsRequest) Reset() { *x = ListResourceShopItemsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6233,7 +6797,7 @@ func (x *ListResourceShopItemsRequest) String() string { func (*ListResourceShopItemsRequest) ProtoMessage() {} func (x *ListResourceShopItemsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6246,7 +6810,7 @@ func (x *ListResourceShopItemsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceShopItemsRequest.ProtoReflect.Descriptor instead. func (*ListResourceShopItemsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{66} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{73} } func (x *ListResourceShopItemsRequest) GetRequestId() string { @@ -6315,7 +6879,7 @@ type ListResourceShopItemsResponse struct { func (x *ListResourceShopItemsResponse) Reset() { *x = ListResourceShopItemsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6327,7 +6891,7 @@ func (x *ListResourceShopItemsResponse) String() string { func (*ListResourceShopItemsResponse) ProtoMessage() {} func (x *ListResourceShopItemsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6340,7 +6904,7 @@ func (x *ListResourceShopItemsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceShopItemsResponse.ProtoReflect.Descriptor instead. func (*ListResourceShopItemsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{67} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{74} } func (x *ListResourceShopItemsResponse) GetItems() []*ResourceShopItem { @@ -6369,7 +6933,7 @@ type UpsertResourceShopItemsRequest struct { func (x *UpsertResourceShopItemsRequest) Reset() { *x = UpsertResourceShopItemsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6381,7 +6945,7 @@ func (x *UpsertResourceShopItemsRequest) String() string { func (*UpsertResourceShopItemsRequest) ProtoMessage() {} func (x *UpsertResourceShopItemsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6394,7 +6958,7 @@ func (x *UpsertResourceShopItemsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertResourceShopItemsRequest.ProtoReflect.Descriptor instead. func (*UpsertResourceShopItemsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{68} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{75} } func (x *UpsertResourceShopItemsRequest) GetRequestId() string { @@ -6434,7 +6998,7 @@ type UpsertResourceShopItemsResponse struct { func (x *UpsertResourceShopItemsResponse) Reset() { *x = UpsertResourceShopItemsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6446,7 +7010,7 @@ func (x *UpsertResourceShopItemsResponse) String() string { func (*UpsertResourceShopItemsResponse) ProtoMessage() {} func (x *UpsertResourceShopItemsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6459,7 +7023,7 @@ func (x *UpsertResourceShopItemsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertResourceShopItemsResponse.ProtoReflect.Descriptor instead. func (*UpsertResourceShopItemsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{69} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{76} } func (x *UpsertResourceShopItemsResponse) GetItems() []*ResourceShopItem { @@ -6482,7 +7046,7 @@ type SetResourceShopItemStatusRequest struct { func (x *SetResourceShopItemStatusRequest) Reset() { *x = SetResourceShopItemStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6494,7 +7058,7 @@ func (x *SetResourceShopItemStatusRequest) String() string { func (*SetResourceShopItemStatusRequest) ProtoMessage() {} func (x *SetResourceShopItemStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6507,7 +7071,7 @@ func (x *SetResourceShopItemStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceShopItemStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceShopItemStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{70} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{77} } func (x *SetResourceShopItemStatusRequest) GetRequestId() string { @@ -6554,7 +7118,7 @@ type ResourceShopItemResponse struct { func (x *ResourceShopItemResponse) Reset() { *x = ResourceShopItemResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6566,7 +7130,7 @@ func (x *ResourceShopItemResponse) String() string { func (*ResourceShopItemResponse) ProtoMessage() {} func (x *ResourceShopItemResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6579,7 +7143,7 @@ func (x *ResourceShopItemResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItemResponse.ProtoReflect.Descriptor instead. func (*ResourceShopItemResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{71} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{78} } func (x *ResourceShopItemResponse) GetItem() *ResourceShopItem { @@ -6601,7 +7165,7 @@ type PurchaseResourceShopItemRequest struct { func (x *PurchaseResourceShopItemRequest) Reset() { *x = PurchaseResourceShopItemRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6613,7 +7177,7 @@ func (x *PurchaseResourceShopItemRequest) String() string { func (*PurchaseResourceShopItemRequest) ProtoMessage() {} func (x *PurchaseResourceShopItemRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6626,7 +7190,7 @@ func (x *PurchaseResourceShopItemRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseResourceShopItemRequest.ProtoReflect.Descriptor instead. func (*PurchaseResourceShopItemRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{72} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{79} } func (x *PurchaseResourceShopItemRequest) GetCommandId() string { @@ -6672,7 +7236,7 @@ type PurchaseResourceShopItemResponse struct { func (x *PurchaseResourceShopItemResponse) Reset() { *x = PurchaseResourceShopItemResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6684,7 +7248,7 @@ func (x *PurchaseResourceShopItemResponse) String() string { func (*PurchaseResourceShopItemResponse) ProtoMessage() {} func (x *PurchaseResourceShopItemResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6697,7 +7261,7 @@ func (x *PurchaseResourceShopItemResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseResourceShopItemResponse.ProtoReflect.Descriptor instead. func (*PurchaseResourceShopItemResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{73} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{80} } func (x *PurchaseResourceShopItemResponse) GetOrderId() string { @@ -6775,7 +7339,7 @@ type RechargeBill struct { func (x *RechargeBill) Reset() { *x = RechargeBill{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6787,7 +7351,7 @@ func (x *RechargeBill) String() string { func (*RechargeBill) ProtoMessage() {} func (x *RechargeBill) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6800,7 +7364,7 @@ func (x *RechargeBill) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBill.ProtoReflect.Descriptor instead. func (*RechargeBill) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{74} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{81} } func (x *RechargeBill) GetAppCode() string { @@ -6949,7 +7513,7 @@ type ListRechargeBillsRequest struct { func (x *ListRechargeBillsRequest) Reset() { *x = ListRechargeBillsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6961,7 +7525,7 @@ func (x *ListRechargeBillsRequest) String() string { func (*ListRechargeBillsRequest) ProtoMessage() {} func (x *ListRechargeBillsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6974,7 +7538,7 @@ func (x *ListRechargeBillsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeBillsRequest.ProtoReflect.Descriptor instead. func (*ListRechargeBillsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{75} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{82} } func (x *ListRechargeBillsRequest) GetRequestId() string { @@ -7071,7 +7635,7 @@ type ListRechargeBillsResponse struct { func (x *ListRechargeBillsResponse) Reset() { *x = ListRechargeBillsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7083,7 +7647,7 @@ func (x *ListRechargeBillsResponse) String() string { func (*ListRechargeBillsResponse) ProtoMessage() {} func (x *ListRechargeBillsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7096,7 +7660,7 @@ func (x *ListRechargeBillsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeBillsResponse.ProtoReflect.Descriptor instead. func (*ListRechargeBillsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{76} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{83} } func (x *ListRechargeBillsResponse) GetBills() []*RechargeBill { @@ -7124,7 +7688,7 @@ type WalletFeatureFlags struct { func (x *WalletFeatureFlags) Reset() { *x = WalletFeatureFlags{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7136,7 +7700,7 @@ func (x *WalletFeatureFlags) String() string { func (*WalletFeatureFlags) ProtoMessage() {} func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7149,7 +7713,7 @@ func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletFeatureFlags.ProtoReflect.Descriptor instead. func (*WalletFeatureFlags) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{77} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{84} } func (x *WalletFeatureFlags) GetRechargeEnabled() bool { @@ -7177,7 +7741,7 @@ type GetWalletOverviewRequest struct { func (x *GetWalletOverviewRequest) Reset() { *x = GetWalletOverviewRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7189,7 +7753,7 @@ func (x *GetWalletOverviewRequest) String() string { func (*GetWalletOverviewRequest) ProtoMessage() {} func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7202,7 +7766,7 @@ func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewRequest.ProtoReflect.Descriptor instead. func (*GetWalletOverviewRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{78} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{85} } func (x *GetWalletOverviewRequest) GetRequestId() string { @@ -7236,7 +7800,7 @@ type GetWalletOverviewResponse struct { func (x *GetWalletOverviewResponse) Reset() { *x = GetWalletOverviewResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7248,7 +7812,7 @@ func (x *GetWalletOverviewResponse) String() string { func (*GetWalletOverviewResponse) ProtoMessage() {} func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7261,7 +7825,7 @@ func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewResponse.ProtoReflect.Descriptor instead. func (*GetWalletOverviewResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{79} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{86} } func (x *GetWalletOverviewResponse) GetBalances() []*AssetBalance { @@ -7289,7 +7853,7 @@ type WalletValueSummary struct { func (x *WalletValueSummary) Reset() { *x = WalletValueSummary{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7301,7 +7865,7 @@ func (x *WalletValueSummary) String() string { func (*WalletValueSummary) ProtoMessage() {} func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7314,7 +7878,7 @@ func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletValueSummary.ProtoReflect.Descriptor instead. func (*WalletValueSummary) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{80} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{87} } func (x *WalletValueSummary) GetCoinAmount() int64 { @@ -7342,7 +7906,7 @@ type GetWalletValueSummaryRequest struct { func (x *GetWalletValueSummaryRequest) Reset() { *x = GetWalletValueSummaryRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7354,7 +7918,7 @@ func (x *GetWalletValueSummaryRequest) String() string { func (*GetWalletValueSummaryRequest) ProtoMessage() {} func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7367,7 +7931,7 @@ func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryRequest.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{81} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{88} } func (x *GetWalletValueSummaryRequest) GetRequestId() string { @@ -7400,7 +7964,7 @@ type GetWalletValueSummaryResponse struct { func (x *GetWalletValueSummaryResponse) Reset() { *x = GetWalletValueSummaryResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7412,7 +7976,7 @@ func (x *GetWalletValueSummaryResponse) String() string { func (*GetWalletValueSummaryResponse) ProtoMessage() {} func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7425,7 +7989,7 @@ func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryResponse.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{82} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{89} } func (x *GetWalletValueSummaryResponse) GetSummary() *WalletValueSummary { @@ -7462,7 +8026,7 @@ type GiftWallItem struct { func (x *GiftWallItem) Reset() { *x = GiftWallItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7474,7 +8038,7 @@ func (x *GiftWallItem) String() string { func (*GiftWallItem) ProtoMessage() {} func (x *GiftWallItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7487,7 +8051,7 @@ func (x *GiftWallItem) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftWallItem.ProtoReflect.Descriptor instead. func (*GiftWallItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{83} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{90} } func (x *GiftWallItem) GetGiftId() string { @@ -7627,7 +8191,7 @@ type GetUserGiftWallRequest struct { func (x *GetUserGiftWallRequest) Reset() { *x = GetUserGiftWallRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7639,7 +8203,7 @@ func (x *GetUserGiftWallRequest) String() string { func (*GetUserGiftWallRequest) ProtoMessage() {} func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7652,7 +8216,7 @@ func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallRequest.ProtoReflect.Descriptor instead. func (*GetUserGiftWallRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{84} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{91} } func (x *GetUserGiftWallRequest) GetRequestId() string { @@ -7692,7 +8256,7 @@ type GetUserGiftWallResponse struct { func (x *GetUserGiftWallResponse) Reset() { *x = GetUserGiftWallResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7704,7 +8268,7 @@ func (x *GetUserGiftWallResponse) String() string { func (*GetUserGiftWallResponse) ProtoMessage() {} func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7717,7 +8281,7 @@ func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallResponse.ProtoReflect.Descriptor instead. func (*GetUserGiftWallResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{85} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{92} } func (x *GetUserGiftWallResponse) GetItems() []*GiftWallItem { @@ -7806,7 +8370,7 @@ type RechargeProduct struct { func (x *RechargeProduct) Reset() { *x = RechargeProduct{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7818,7 +8382,7 @@ func (x *RechargeProduct) String() string { func (*RechargeProduct) ProtoMessage() {} func (x *RechargeProduct) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7831,7 +8395,7 @@ func (x *RechargeProduct) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProduct.ProtoReflect.Descriptor instead. func (*RechargeProduct) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{86} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{93} } func (x *RechargeProduct) GetProductId() int64 { @@ -7995,7 +8559,7 @@ type ListRechargeProductsRequest struct { func (x *ListRechargeProductsRequest) Reset() { *x = ListRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8007,7 +8571,7 @@ func (x *ListRechargeProductsRequest) String() string { func (*ListRechargeProductsRequest) ProtoMessage() {} func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8020,7 +8584,7 @@ func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{87} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{94} } func (x *ListRechargeProductsRequest) GetRequestId() string { @@ -8068,7 +8632,7 @@ type ListRechargeProductsResponse struct { func (x *ListRechargeProductsResponse) Reset() { *x = ListRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8080,7 +8644,7 @@ func (x *ListRechargeProductsResponse) String() string { func (*ListRechargeProductsResponse) ProtoMessage() {} func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8093,7 +8657,7 @@ func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{88} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} } func (x *ListRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -8129,7 +8693,7 @@ type ConfirmGooglePaymentRequest struct { func (x *ConfirmGooglePaymentRequest) Reset() { *x = ConfirmGooglePaymentRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8141,7 +8705,7 @@ func (x *ConfirmGooglePaymentRequest) String() string { func (*ConfirmGooglePaymentRequest) ProtoMessage() {} func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8154,7 +8718,7 @@ func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentRequest.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{89} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} } func (x *ConfirmGooglePaymentRequest) GetRequestId() string { @@ -8251,7 +8815,7 @@ type ConfirmGooglePaymentResponse struct { func (x *ConfirmGooglePaymentResponse) Reset() { *x = ConfirmGooglePaymentResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8263,7 +8827,7 @@ func (x *ConfirmGooglePaymentResponse) String() string { func (*ConfirmGooglePaymentResponse) ProtoMessage() {} func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8276,7 +8840,7 @@ func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentResponse.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{90} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} } func (x *ConfirmGooglePaymentResponse) GetPaymentOrderId() string { @@ -8359,7 +8923,7 @@ type ListAdminRechargeProductsRequest struct { func (x *ListAdminRechargeProductsRequest) Reset() { *x = ListAdminRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8371,7 +8935,7 @@ func (x *ListAdminRechargeProductsRequest) String() string { func (*ListAdminRechargeProductsRequest) ProtoMessage() {} func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8384,7 +8948,7 @@ func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{91} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} } func (x *ListAdminRechargeProductsRequest) GetRequestId() string { @@ -8453,7 +9017,7 @@ type ListAdminRechargeProductsResponse struct { func (x *ListAdminRechargeProductsResponse) Reset() { *x = ListAdminRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8465,7 +9029,7 @@ func (x *ListAdminRechargeProductsResponse) String() string { func (*ListAdminRechargeProductsResponse) ProtoMessage() {} func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8478,7 +9042,7 @@ func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListAdminRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{92} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} } func (x *ListAdminRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -8514,7 +9078,7 @@ type CreateRechargeProductRequest struct { func (x *CreateRechargeProductRequest) Reset() { *x = CreateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8526,7 +9090,7 @@ func (x *CreateRechargeProductRequest) String() string { func (*CreateRechargeProductRequest) ProtoMessage() {} func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8539,7 +9103,7 @@ func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*CreateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{93} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} } func (x *CreateRechargeProductRequest) GetRequestId() string { @@ -8631,7 +9195,7 @@ type UpdateRechargeProductRequest struct { func (x *UpdateRechargeProductRequest) Reset() { *x = UpdateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8643,7 +9207,7 @@ func (x *UpdateRechargeProductRequest) String() string { func (*UpdateRechargeProductRequest) ProtoMessage() {} func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8656,7 +9220,7 @@ func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*UpdateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{94} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} } func (x *UpdateRechargeProductRequest) GetRequestId() string { @@ -8748,7 +9312,7 @@ type DeleteRechargeProductRequest struct { func (x *DeleteRechargeProductRequest) Reset() { *x = DeleteRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8760,7 +9324,7 @@ func (x *DeleteRechargeProductRequest) String() string { func (*DeleteRechargeProductRequest) ProtoMessage() {} func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8773,7 +9337,7 @@ func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductRequest.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} } func (x *DeleteRechargeProductRequest) GetRequestId() string { @@ -8813,7 +9377,7 @@ type RechargeProductResponse struct { func (x *RechargeProductResponse) Reset() { *x = RechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8825,7 +9389,7 @@ func (x *RechargeProductResponse) String() string { func (*RechargeProductResponse) ProtoMessage() {} func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8838,7 +9402,7 @@ func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProductResponse.ProtoReflect.Descriptor instead. func (*RechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} } func (x *RechargeProductResponse) GetProduct() *RechargeProduct { @@ -8857,7 +9421,7 @@ type DeleteRechargeProductResponse struct { func (x *DeleteRechargeProductResponse) Reset() { *x = DeleteRechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8869,7 +9433,7 @@ func (x *DeleteRechargeProductResponse) String() string { func (*DeleteRechargeProductResponse) ProtoMessage() {} func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8882,7 +9446,7 @@ func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductResponse.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} } func (x *DeleteRechargeProductResponse) GetDeleted() bool { @@ -8906,7 +9470,7 @@ type DiamondExchangeRule struct { func (x *DiamondExchangeRule) Reset() { *x = DiamondExchangeRule{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8918,7 +9482,7 @@ func (x *DiamondExchangeRule) String() string { func (*DiamondExchangeRule) ProtoMessage() {} func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8931,7 +9495,7 @@ func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { // Deprecated: Use DiamondExchangeRule.ProtoReflect.Descriptor instead. func (*DiamondExchangeRule) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} } func (x *DiamondExchangeRule) GetExchangeType() string { @@ -8987,7 +9551,7 @@ type GetDiamondExchangeConfigRequest struct { func (x *GetDiamondExchangeConfigRequest) Reset() { *x = GetDiamondExchangeConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8999,7 +9563,7 @@ func (x *GetDiamondExchangeConfigRequest) String() string { func (*GetDiamondExchangeConfigRequest) ProtoMessage() {} func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9012,7 +9576,7 @@ func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigRequest.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} } func (x *GetDiamondExchangeConfigRequest) GetRequestId() string { @@ -9045,7 +9609,7 @@ type GetDiamondExchangeConfigResponse struct { func (x *GetDiamondExchangeConfigResponse) Reset() { *x = GetDiamondExchangeConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9057,7 +9621,7 @@ func (x *GetDiamondExchangeConfigResponse) String() string { func (*GetDiamondExchangeConfigResponse) ProtoMessage() {} func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9070,7 +9634,7 @@ func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigResponse.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} } func (x *GetDiamondExchangeConfigResponse) GetRules() []*DiamondExchangeRule { @@ -9100,7 +9664,7 @@ type WalletTransaction struct { func (x *WalletTransaction) Reset() { *x = WalletTransaction{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9112,7 +9676,7 @@ func (x *WalletTransaction) String() string { func (*WalletTransaction) ProtoMessage() {} func (x *WalletTransaction) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9125,7 +9689,7 @@ func (x *WalletTransaction) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletTransaction.ProtoReflect.Descriptor instead. func (*WalletTransaction) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} } func (x *WalletTransaction) GetEntryId() int64 { @@ -9219,7 +9783,7 @@ type ListWalletTransactionsRequest struct { func (x *ListWalletTransactionsRequest) Reset() { *x = ListWalletTransactionsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9231,7 +9795,7 @@ func (x *ListWalletTransactionsRequest) String() string { func (*ListWalletTransactionsRequest) ProtoMessage() {} func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9244,7 +9808,7 @@ func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsRequest.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} } func (x *ListWalletTransactionsRequest) GetRequestId() string { @@ -9299,7 +9863,7 @@ type ListWalletTransactionsResponse struct { func (x *ListWalletTransactionsResponse) Reset() { *x = ListWalletTransactionsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9311,7 +9875,7 @@ func (x *ListWalletTransactionsResponse) String() string { func (*ListWalletTransactionsResponse) ProtoMessage() {} func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9324,7 +9888,7 @@ func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsResponse.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} } func (x *ListWalletTransactionsResponse) GetTransactions() []*WalletTransaction { @@ -9358,7 +9922,7 @@ type VipRewardItem struct { func (x *VipRewardItem) Reset() { *x = VipRewardItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9370,7 +9934,7 @@ func (x *VipRewardItem) String() string { func (*VipRewardItem) ProtoMessage() {} func (x *VipRewardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9383,7 +9947,7 @@ func (x *VipRewardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use VipRewardItem.ProtoReflect.Descriptor instead. func (*VipRewardItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} } func (x *VipRewardItem) GetResourceId() int64 { @@ -9472,7 +10036,7 @@ type VipLevel struct { func (x *VipLevel) Reset() { *x = VipLevel{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9484,7 +10048,7 @@ func (x *VipLevel) String() string { func (*VipLevel) ProtoMessage() {} func (x *VipLevel) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9497,7 +10061,7 @@ func (x *VipLevel) ProtoReflect() protoreflect.Message { // Deprecated: Use VipLevel.ProtoReflect.Descriptor instead. func (*VipLevel) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} } func (x *VipLevel) GetLevel() int32 { @@ -9620,7 +10184,7 @@ type UserVip struct { func (x *UserVip) Reset() { *x = UserVip{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9632,7 +10196,7 @@ func (x *UserVip) String() string { func (*UserVip) ProtoMessage() {} func (x *UserVip) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9645,7 +10209,7 @@ func (x *UserVip) ProtoReflect() protoreflect.Message { // Deprecated: Use UserVip.ProtoReflect.Descriptor instead. func (*UserVip) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} } func (x *UserVip) GetUserId() int64 { @@ -9708,7 +10272,7 @@ type ListVipPackagesRequest struct { func (x *ListVipPackagesRequest) Reset() { *x = ListVipPackagesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9720,7 +10284,7 @@ func (x *ListVipPackagesRequest) String() string { func (*ListVipPackagesRequest) ProtoMessage() {} func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9733,7 +10297,7 @@ func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesRequest.ProtoReflect.Descriptor instead. func (*ListVipPackagesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} } func (x *ListVipPackagesRequest) GetRequestId() string { @@ -9767,7 +10331,7 @@ type ListVipPackagesResponse struct { func (x *ListVipPackagesResponse) Reset() { *x = ListVipPackagesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9779,7 +10343,7 @@ func (x *ListVipPackagesResponse) String() string { func (*ListVipPackagesResponse) ProtoMessage() {} func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9792,7 +10356,7 @@ func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesResponse.ProtoReflect.Descriptor instead. func (*ListVipPackagesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} } func (x *ListVipPackagesResponse) GetCurrentVip() *UserVip { @@ -9820,7 +10384,7 @@ type GetMyVipRequest struct { func (x *GetMyVipRequest) Reset() { *x = GetMyVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9832,7 +10396,7 @@ func (x *GetMyVipRequest) String() string { func (*GetMyVipRequest) ProtoMessage() {} func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9845,7 +10409,7 @@ func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipRequest.ProtoReflect.Descriptor instead. func (*GetMyVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} } func (x *GetMyVipRequest) GetRequestId() string { @@ -9878,7 +10442,7 @@ type GetMyVipResponse struct { func (x *GetMyVipResponse) Reset() { *x = GetMyVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9890,7 +10454,7 @@ func (x *GetMyVipResponse) String() string { func (*GetMyVipResponse) ProtoMessage() {} func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9903,7 +10467,7 @@ func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipResponse.ProtoReflect.Descriptor instead. func (*GetMyVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} } func (x *GetMyVipResponse) GetVip() *UserVip { @@ -9925,7 +10489,7 @@ type PurchaseVipRequest struct { func (x *PurchaseVipRequest) Reset() { *x = PurchaseVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9937,7 +10501,7 @@ func (x *PurchaseVipRequest) String() string { func (*PurchaseVipRequest) ProtoMessage() {} func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9950,7 +10514,7 @@ func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipRequest.ProtoReflect.Descriptor instead. func (*PurchaseVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} } func (x *PurchaseVipRequest) GetCommandId() string { @@ -9995,7 +10559,7 @@ type PurchaseVipResponse struct { func (x *PurchaseVipResponse) Reset() { *x = PurchaseVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10007,7 +10571,7 @@ func (x *PurchaseVipResponse) String() string { func (*PurchaseVipResponse) ProtoMessage() {} func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10020,7 +10584,7 @@ func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipResponse.ProtoReflect.Descriptor instead. func (*PurchaseVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} } func (x *PurchaseVipResponse) GetOrderId() string { @@ -10080,7 +10644,7 @@ type GrantVipRequest struct { func (x *GrantVipRequest) Reset() { *x = GrantVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10092,7 +10656,7 @@ func (x *GrantVipRequest) String() string { func (*GrantVipRequest) ProtoMessage() {} func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10105,7 +10669,7 @@ func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipRequest.ProtoReflect.Descriptor instead. func (*GrantVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} } func (x *GrantVipRequest) GetCommandId() string { @@ -10169,7 +10733,7 @@ type GrantVipResponse struct { func (x *GrantVipResponse) Reset() { *x = GrantVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10181,7 +10745,7 @@ func (x *GrantVipResponse) String() string { func (*GrantVipResponse) ProtoMessage() {} func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10194,7 +10758,7 @@ func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipResponse.ProtoReflect.Descriptor instead. func (*GrantVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} } func (x *GrantVipResponse) GetTransactionId() string { @@ -10241,7 +10805,7 @@ type AdminVipLevelInput struct { func (x *AdminVipLevelInput) Reset() { *x = AdminVipLevelInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10253,7 +10817,7 @@ func (x *AdminVipLevelInput) String() string { func (*AdminVipLevelInput) ProtoMessage() {} func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10266,7 +10830,7 @@ func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminVipLevelInput.ProtoReflect.Descriptor instead. func (*AdminVipLevelInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} } func (x *AdminVipLevelInput) GetLevel() int32 { @@ -10335,7 +10899,7 @@ type ListAdminVipLevelsRequest struct { func (x *ListAdminVipLevelsRequest) Reset() { *x = ListAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10347,7 +10911,7 @@ func (x *ListAdminVipLevelsRequest) String() string { func (*ListAdminVipLevelsRequest) ProtoMessage() {} func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10360,7 +10924,7 @@ func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} } func (x *ListAdminVipLevelsRequest) GetRequestId() string { @@ -10387,7 +10951,7 @@ type ListAdminVipLevelsResponse struct { func (x *ListAdminVipLevelsResponse) Reset() { *x = ListAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10399,7 +10963,7 @@ func (x *ListAdminVipLevelsResponse) String() string { func (*ListAdminVipLevelsResponse) ProtoMessage() {} func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10412,7 +10976,7 @@ func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} } func (x *ListAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -10441,7 +11005,7 @@ type UpdateAdminVipLevelsRequest struct { func (x *UpdateAdminVipLevelsRequest) Reset() { *x = UpdateAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10453,7 +11017,7 @@ func (x *UpdateAdminVipLevelsRequest) String() string { func (*UpdateAdminVipLevelsRequest) ProtoMessage() {} func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10466,7 +11030,7 @@ func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} } func (x *UpdateAdminVipLevelsRequest) GetRequestId() string { @@ -10507,7 +11071,7 @@ type UpdateAdminVipLevelsResponse struct { func (x *UpdateAdminVipLevelsResponse) Reset() { *x = UpdateAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10519,7 +11083,7 @@ func (x *UpdateAdminVipLevelsResponse) String() string { func (*UpdateAdminVipLevelsResponse) ProtoMessage() {} func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10532,7 +11096,7 @@ func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} } func (x *UpdateAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -10566,7 +11130,7 @@ type CreditTaskRewardRequest struct { func (x *CreditTaskRewardRequest) Reset() { *x = CreditTaskRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10578,7 +11142,7 @@ func (x *CreditTaskRewardRequest) String() string { func (*CreditTaskRewardRequest) ProtoMessage() {} func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10591,7 +11155,7 @@ func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardRequest.ProtoReflect.Descriptor instead. func (*CreditTaskRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} } func (x *CreditTaskRewardRequest) GetCommandId() string { @@ -10663,7 +11227,7 @@ type CreditTaskRewardResponse struct { func (x *CreditTaskRewardResponse) Reset() { *x = CreditTaskRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10675,7 +11239,7 @@ func (x *CreditTaskRewardResponse) String() string { func (*CreditTaskRewardResponse) ProtoMessage() {} func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10688,7 +11252,7 @@ func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardResponse.ProtoReflect.Descriptor instead. func (*CreditTaskRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} } func (x *CreditTaskRewardResponse) GetTransactionId() string { @@ -10738,7 +11302,7 @@ type CreditLuckyGiftRewardRequest struct { func (x *CreditLuckyGiftRewardRequest) Reset() { *x = CreditLuckyGiftRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10750,7 +11314,7 @@ func (x *CreditLuckyGiftRewardRequest) String() string { func (*CreditLuckyGiftRewardRequest) ProtoMessage() {} func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10763,7 +11327,7 @@ func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardRequest.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} } func (x *CreditLuckyGiftRewardRequest) GetCommandId() string { @@ -10849,7 +11413,7 @@ type CreditLuckyGiftRewardResponse struct { func (x *CreditLuckyGiftRewardResponse) Reset() { *x = CreditLuckyGiftRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10861,7 +11425,7 @@ func (x *CreditLuckyGiftRewardResponse) String() string { func (*CreditLuckyGiftRewardResponse) ProtoMessage() {} func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10874,7 +11438,7 @@ func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardResponse.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} } func (x *CreditLuckyGiftRewardResponse) GetTransactionId() string { @@ -10926,7 +11490,7 @@ type ApplyGameCoinChangeRequest struct { func (x *ApplyGameCoinChangeRequest) Reset() { *x = ApplyGameCoinChangeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10938,7 +11502,7 @@ func (x *ApplyGameCoinChangeRequest) String() string { func (*ApplyGameCoinChangeRequest) ProtoMessage() {} func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10951,7 +11515,7 @@ func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeRequest.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} } func (x *ApplyGameCoinChangeRequest) GetRequestId() string { @@ -11050,7 +11614,7 @@ type ApplyGameCoinChangeResponse struct { func (x *ApplyGameCoinChangeResponse) Reset() { *x = ApplyGameCoinChangeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11062,7 +11626,7 @@ func (x *ApplyGameCoinChangeResponse) String() string { func (*ApplyGameCoinChangeResponse) ProtoMessage() {} func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11075,7 +11639,7 @@ func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeResponse.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} } func (x *ApplyGameCoinChangeResponse) GetWalletTransactionId() string { @@ -11118,7 +11682,7 @@ type RedPacketConfig struct { func (x *RedPacketConfig) Reset() { *x = RedPacketConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11130,7 +11694,7 @@ func (x *RedPacketConfig) String() string { func (*RedPacketConfig) ProtoMessage() {} func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11143,7 +11707,7 @@ func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketConfig.ProtoReflect.Descriptor instead. func (*RedPacketConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} } func (x *RedPacketConfig) GetAppCode() string { @@ -11242,7 +11806,7 @@ type RedPacketClaim struct { func (x *RedPacketClaim) Reset() { *x = RedPacketClaim{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11254,7 +11818,7 @@ func (x *RedPacketClaim) String() string { func (*RedPacketClaim) ProtoMessage() {} func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11267,7 +11831,7 @@ func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketClaim.ProtoReflect.Descriptor instead. func (*RedPacketClaim) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} } func (x *RedPacketClaim) GetAppCode() string { @@ -11377,7 +11941,7 @@ type RedPacket struct { func (x *RedPacket) Reset() { *x = RedPacket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11389,7 +11953,7 @@ func (x *RedPacket) String() string { func (*RedPacket) ProtoMessage() {} func (x *RedPacket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11402,7 +11966,7 @@ func (x *RedPacket) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacket.ProtoReflect.Descriptor instead. func (*RedPacket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} } func (x *RedPacket) GetAppCode() string { @@ -11569,7 +12133,7 @@ type GetRedPacketConfigRequest struct { func (x *GetRedPacketConfigRequest) Reset() { *x = GetRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11581,7 +12145,7 @@ func (x *GetRedPacketConfigRequest) String() string { func (*GetRedPacketConfigRequest) ProtoMessage() {} func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11594,7 +12158,7 @@ func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} } func (x *GetRedPacketConfigRequest) GetRequestId() string { @@ -11621,7 +12185,7 @@ type GetRedPacketConfigResponse struct { func (x *GetRedPacketConfigResponse) Reset() { *x = GetRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11633,7 +12197,7 @@ func (x *GetRedPacketConfigResponse) String() string { func (*GetRedPacketConfigResponse) ProtoMessage() {} func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11646,7 +12210,7 @@ func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} } func (x *GetRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -11681,7 +12245,7 @@ type UpdateRedPacketConfigRequest struct { func (x *UpdateRedPacketConfigRequest) Reset() { *x = UpdateRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11693,7 +12257,7 @@ func (x *UpdateRedPacketConfigRequest) String() string { func (*UpdateRedPacketConfigRequest) ProtoMessage() {} func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11706,7 +12270,7 @@ func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} } func (x *UpdateRedPacketConfigRequest) GetRequestId() string { @@ -11789,7 +12353,7 @@ type UpdateRedPacketConfigResponse struct { func (x *UpdateRedPacketConfigResponse) Reset() { *x = UpdateRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11801,7 +12365,7 @@ func (x *UpdateRedPacketConfigResponse) String() string { func (*UpdateRedPacketConfigResponse) ProtoMessage() {} func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11814,7 +12378,7 @@ func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} } func (x *UpdateRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -11848,7 +12412,7 @@ type CreateRedPacketRequest struct { func (x *CreateRedPacketRequest) Reset() { *x = CreateRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11860,7 +12424,7 @@ func (x *CreateRedPacketRequest) String() string { func (*CreateRedPacketRequest) ProtoMessage() {} func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11873,7 +12437,7 @@ func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketRequest.ProtoReflect.Descriptor instead. func (*CreateRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} } func (x *CreateRedPacketRequest) GetRequestId() string { @@ -11950,7 +12514,7 @@ type CreateRedPacketResponse struct { func (x *CreateRedPacketResponse) Reset() { *x = CreateRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11962,7 +12526,7 @@ func (x *CreateRedPacketResponse) String() string { func (*CreateRedPacketResponse) ProtoMessage() {} func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11975,7 +12539,7 @@ func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketResponse.ProtoReflect.Descriptor instead. func (*CreateRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} } func (x *CreateRedPacketResponse) GetPacket() *RedPacket { @@ -12012,7 +12576,7 @@ type ClaimRedPacketRequest struct { func (x *ClaimRedPacketRequest) Reset() { *x = ClaimRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12024,7 +12588,7 @@ func (x *ClaimRedPacketRequest) String() string { func (*ClaimRedPacketRequest) ProtoMessage() {} func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12037,7 +12601,7 @@ func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketRequest.ProtoReflect.Descriptor instead. func (*ClaimRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} } func (x *ClaimRedPacketRequest) GetRequestId() string { @@ -12087,7 +12651,7 @@ type ClaimRedPacketResponse struct { func (x *ClaimRedPacketResponse) Reset() { *x = ClaimRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12099,7 +12663,7 @@ func (x *ClaimRedPacketResponse) String() string { func (*ClaimRedPacketResponse) ProtoMessage() {} func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12112,7 +12676,7 @@ func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketResponse.ProtoReflect.Descriptor instead. func (*ClaimRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} } func (x *ClaimRedPacketResponse) GetClaim() *RedPacketClaim { @@ -12163,7 +12727,7 @@ type ListRedPacketsRequest struct { func (x *ListRedPacketsRequest) Reset() { *x = ListRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12175,7 +12739,7 @@ func (x *ListRedPacketsRequest) String() string { func (*ListRedPacketsRequest) ProtoMessage() {} func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12188,7 +12752,7 @@ func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ListRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} } func (x *ListRedPacketsRequest) GetRequestId() string { @@ -12286,7 +12850,7 @@ type ListRedPacketsResponse struct { func (x *ListRedPacketsResponse) Reset() { *x = ListRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12298,7 +12862,7 @@ func (x *ListRedPacketsResponse) String() string { func (*ListRedPacketsResponse) ProtoMessage() {} func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12311,7 +12875,7 @@ func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ListRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} } func (x *ListRedPacketsResponse) GetPackets() []*RedPacket { @@ -12348,7 +12912,7 @@ type GetRedPacketRequest struct { func (x *GetRedPacketRequest) Reset() { *x = GetRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12360,7 +12924,7 @@ func (x *GetRedPacketRequest) String() string { func (*GetRedPacketRequest) ProtoMessage() {} func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12373,7 +12937,7 @@ func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} } func (x *GetRedPacketRequest) GetRequestId() string { @@ -12421,7 +12985,7 @@ type GetRedPacketResponse struct { func (x *GetRedPacketResponse) Reset() { *x = GetRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12433,7 +12997,7 @@ func (x *GetRedPacketResponse) String() string { func (*GetRedPacketResponse) ProtoMessage() {} func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12446,7 +13010,7 @@ func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} } func (x *GetRedPacketResponse) GetPacket() *RedPacket { @@ -12474,7 +13038,7 @@ type ExpireRedPacketsRequest struct { func (x *ExpireRedPacketsRequest) Reset() { *x = ExpireRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12486,7 +13050,7 @@ func (x *ExpireRedPacketsRequest) String() string { func (*ExpireRedPacketsRequest) ProtoMessage() {} func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12499,7 +13063,7 @@ func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} } func (x *ExpireRedPacketsRequest) GetRequestId() string { @@ -12534,7 +13098,7 @@ type ExpireRedPacketsResponse struct { func (x *ExpireRedPacketsResponse) Reset() { *x = ExpireRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12546,7 +13110,7 @@ func (x *ExpireRedPacketsResponse) String() string { func (*ExpireRedPacketsResponse) ProtoMessage() {} func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12559,7 +13123,7 @@ func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} } func (x *ExpireRedPacketsResponse) GetExpiredCount() int32 { @@ -12595,7 +13159,7 @@ type RetryRedPacketRefundRequest struct { func (x *RetryRedPacketRefundRequest) Reset() { *x = RetryRedPacketRefundRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12607,7 +13171,7 @@ func (x *RetryRedPacketRefundRequest) String() string { func (*RetryRedPacketRefundRequest) ProtoMessage() {} func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12620,7 +13184,7 @@ func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundRequest.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} } func (x *RetryRedPacketRefundRequest) GetRequestId() string { @@ -12662,7 +13226,7 @@ type RetryRedPacketRefundResponse struct { func (x *RetryRedPacketRefundResponse) Reset() { *x = RetryRedPacketRefundResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12674,7 +13238,7 @@ func (x *RetryRedPacketRefundResponse) String() string { func (*RetryRedPacketRefundResponse) ProtoMessage() {} func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12687,7 +13251,7 @@ func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundResponse.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} } func (x *RetryRedPacketRefundResponse) GetPacket() *RedPacket { @@ -12726,7 +13290,7 @@ type CronBatchRequest struct { func (x *CronBatchRequest) Reset() { *x = CronBatchRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12738,7 +13302,7 @@ func (x *CronBatchRequest) String() string { func (*CronBatchRequest) ProtoMessage() {} func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12751,7 +13315,7 @@ func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchRequest.ProtoReflect.Descriptor instead. func (*CronBatchRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} } func (x *CronBatchRequest) GetRequestId() string { @@ -12810,7 +13374,7 @@ type CronBatchResponse struct { func (x *CronBatchResponse) Reset() { *x = CronBatchResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12822,7 +13386,7 @@ func (x *CronBatchResponse) String() string { func (*CronBatchResponse) ProtoMessage() {} func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12835,7 +13399,7 @@ func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchResponse.ProtoReflect.Descriptor instead. func (*CronBatchResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} } func (x *CronBatchResponse) GetClaimedCount() int32 { @@ -12955,7 +13519,59 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "assetTypes\x12\x19\n" + "\bapp_code\x18\x04 \x01(\tR\aappCode\"P\n" + "\x13GetBalancesResponse\x129\n" + - "\bbalances\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\bbalances\"\x95\x02\n" + + "\bbalances\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\bbalances\"\xaa\x02\n" + + "\x15HostSalaryPolicyLevel\x12\x19\n" + + "\blevel_no\x18\x01 \x01(\x05R\alevelNo\x12+\n" + + "\x11required_diamonds\x18\x02 \x01(\x03R\x10requiredDiamonds\x121\n" + + "\x15host_salary_usd_minor\x18\x03 \x01(\x03R\x12hostSalaryUsdMinor\x12(\n" + + "\x10host_coin_reward\x18\x04 \x01(\x03R\x0ehostCoinReward\x125\n" + + "\x17agency_salary_usd_minor\x18\x05 \x01(\x03R\x14agencySalaryUsdMinor\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\a \x01(\x05R\tsortOrder\"\xe9\x03\n" + + "\x10HostSalaryPolicy\x12\x1b\n" + + "\tpolicy_id\x18\x01 \x01(\x04R\bpolicyId\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12'\n" + + "\x0fsettlement_mode\x18\x05 \x01(\tR\x0esettlementMode\x126\n" + + "\x17settlement_trigger_mode\x18\x06 \x01(\tR\x15settlementTriggerMode\x12:\n" + + "\x1agift_coin_to_diamond_ratio\x18\a \x01(\tR\x16giftCoinToDiamondRatio\x12>\n" + + "\x1cresidual_diamond_to_usd_rate\x18\b \x01(\tR\x18residualDiamondToUsdRate\x12*\n" + + "\x11effective_from_ms\x18\t \x01(\x03R\x0feffectiveFromMs\x12&\n" + + "\x0feffective_to_ms\x18\n" + + " \x01(\x03R\reffectiveToMs\x12>\n" + + "\x06levels\x18\v \x03(\v2&.hyapp.wallet.v1.HostSalaryPolicyLevelR\x06levels\"\xf1\x01\n" + + " GetActiveHostSalaryPolicyRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12'\n" + + "\x0fsettlement_mode\x18\x04 \x01(\tR\x0esettlementMode\x126\n" + + "\x17settlement_trigger_mode\x18\x05 \x01(\tR\x15settlementTriggerMode\x12\x15\n" + + "\x06now_ms\x18\x06 \x01(\x03R\x05nowMs\"t\n" + + "!GetActiveHostSalaryPolicyResponse\x12\x14\n" + + "\x05found\x18\x01 \x01(\bR\x05found\x129\n" + + "\x06policy\x18\x02 \x01(\v2!.hyapp.wallet.v1.HostSalaryPolicyR\x06policy\"\x9a\x02\n" + + "\x12HostSalaryProgress\x12 \n" + + "\fhost_user_id\x18\x01 \x01(\x03R\n" + + "hostUserId\x12\x1b\n" + + "\tcycle_key\x18\x02 \x01(\tR\bcycleKey\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12/\n" + + "\x14agency_owner_user_id\x18\x04 \x01(\x03R\x11agencyOwnerUserId\x12%\n" + + "\x0etotal_diamonds\x18\x05 \x01(\x03R\rtotalDiamonds\x12,\n" + + "\x12gift_diamond_total\x18\x06 \x01(\x03R\x10giftDiamondTotal\x12\"\n" + + "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\"\xae\x01\n" + + "\x1cGetHostSalaryProgressRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12 \n" + + "\fhost_user_id\x18\x03 \x01(\x03R\n" + + "hostUserId\x12\x1b\n" + + "\tcycle_key\x18\x04 \x01(\tR\bcycleKey\x12\x15\n" + + "\x06now_ms\x18\x05 \x01(\x03R\x05nowMs\"`\n" + + "\x1dGetHostSalaryProgressResponse\x12?\n" + + "\bprogress\x18\x01 \x01(\v2#.hyapp.wallet.v1.HostSalaryProgressR\bprogress\"\x95\x02\n" + "\x17AdminCreditAssetRequest\x12\x1d\n" + "\n" + "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + @@ -14205,11 +14821,13 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x11WalletCronService\x12n\n" + "%ProcessHostSalaryDailySettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12r\n" + ")ProcessHostSalaryHalfMonthSettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12g\n" + - "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\xe54\n" + + "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\xe26\n" + "\rWalletService\x12R\n" + "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12a\n" + "\x0eBatchDebitGift\x12&.hyapp.wallet.v1.BatchDebitGiftRequest\x1a'.hyapp.wallet.v1.BatchDebitGiftResponse\x12X\n" + - "\vGetBalances\x12#.hyapp.wallet.v1.GetBalancesRequest\x1a$.hyapp.wallet.v1.GetBalancesResponse\x12g\n" + + "\vGetBalances\x12#.hyapp.wallet.v1.GetBalancesRequest\x1a$.hyapp.wallet.v1.GetBalancesResponse\x12\x82\x01\n" + + "\x19GetActiveHostSalaryPolicy\x121.hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest\x1a2.hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse\x12v\n" + + "\x15GetHostSalaryProgress\x12-.hyapp.wallet.v1.GetHostSalaryProgressRequest\x1a..hyapp.wallet.v1.GetHostSalaryProgressResponse\x12g\n" + "\x10AdminCreditAsset\x12(.hyapp.wallet.v1.AdminCreditAssetRequest\x1a).hyapp.wallet.v1.AdminCreditAssetResponse\x12\x85\x01\n" + "\x1aAdminCreditCoinSellerStock\x122.hyapp.wallet.v1.AdminCreditCoinSellerStockRequest\x1a3.hyapp.wallet.v1.AdminCreditCoinSellerStockResponse\x12y\n" + "\x16TransferCoinFromSeller\x12..hyapp.wallet.v1.TransferCoinFromSellerRequest\x1a/.hyapp.wallet.v1.TransferCoinFromSellerResponse\x12^\n" + @@ -14282,7 +14900,7 @@ func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 147) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 154) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest (*DebitGiftResponse)(nil), // 1: hyapp.wallet.v1.DebitGiftResponse @@ -14293,144 +14911,151 @@ var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*AssetBalance)(nil), // 6: hyapp.wallet.v1.AssetBalance (*GetBalancesRequest)(nil), // 7: hyapp.wallet.v1.GetBalancesRequest (*GetBalancesResponse)(nil), // 8: hyapp.wallet.v1.GetBalancesResponse - (*AdminCreditAssetRequest)(nil), // 9: hyapp.wallet.v1.AdminCreditAssetRequest - (*AdminCreditAssetResponse)(nil), // 10: hyapp.wallet.v1.AdminCreditAssetResponse - (*AdminCreditCoinSellerStockRequest)(nil), // 11: hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - (*AdminCreditCoinSellerStockResponse)(nil), // 12: hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - (*TransferCoinFromSellerRequest)(nil), // 13: hyapp.wallet.v1.TransferCoinFromSellerRequest - (*TransferCoinFromSellerResponse)(nil), // 14: hyapp.wallet.v1.TransferCoinFromSellerResponse - (*Resource)(nil), // 15: hyapp.wallet.v1.Resource - (*ResourceGroupItem)(nil), // 16: hyapp.wallet.v1.ResourceGroupItem - (*ResourceGroup)(nil), // 17: hyapp.wallet.v1.ResourceGroup - (*GiftConfig)(nil), // 18: hyapp.wallet.v1.GiftConfig - (*GiftTypeConfig)(nil), // 19: hyapp.wallet.v1.GiftTypeConfig - (*ResourceShopItem)(nil), // 20: hyapp.wallet.v1.ResourceShopItem - (*UserResourceEntitlement)(nil), // 21: hyapp.wallet.v1.UserResourceEntitlement - (*ResourceGrantItem)(nil), // 22: hyapp.wallet.v1.ResourceGrantItem - (*ResourceGrant)(nil), // 23: hyapp.wallet.v1.ResourceGrant - (*ResourceGroupItemInput)(nil), // 24: hyapp.wallet.v1.ResourceGroupItemInput - (*ListResourcesRequest)(nil), // 25: hyapp.wallet.v1.ListResourcesRequest - (*ListResourcesResponse)(nil), // 26: hyapp.wallet.v1.ListResourcesResponse - (*GetResourceRequest)(nil), // 27: hyapp.wallet.v1.GetResourceRequest - (*GetResourceResponse)(nil), // 28: hyapp.wallet.v1.GetResourceResponse - (*CreateResourceRequest)(nil), // 29: hyapp.wallet.v1.CreateResourceRequest - (*UpdateResourceRequest)(nil), // 30: hyapp.wallet.v1.UpdateResourceRequest - (*SetResourceStatusRequest)(nil), // 31: hyapp.wallet.v1.SetResourceStatusRequest - (*ResourceResponse)(nil), // 32: hyapp.wallet.v1.ResourceResponse - (*ListResourceGroupsRequest)(nil), // 33: hyapp.wallet.v1.ListResourceGroupsRequest - (*ListResourceGroupsResponse)(nil), // 34: hyapp.wallet.v1.ListResourceGroupsResponse - (*GetResourceGroupRequest)(nil), // 35: hyapp.wallet.v1.GetResourceGroupRequest - (*GetResourceGroupResponse)(nil), // 36: hyapp.wallet.v1.GetResourceGroupResponse - (*CreateResourceGroupRequest)(nil), // 37: hyapp.wallet.v1.CreateResourceGroupRequest - (*UpdateResourceGroupRequest)(nil), // 38: hyapp.wallet.v1.UpdateResourceGroupRequest - (*SetResourceGroupStatusRequest)(nil), // 39: hyapp.wallet.v1.SetResourceGroupStatusRequest - (*ResourceGroupResponse)(nil), // 40: hyapp.wallet.v1.ResourceGroupResponse - (*ListGiftConfigsRequest)(nil), // 41: hyapp.wallet.v1.ListGiftConfigsRequest - (*ListGiftConfigsResponse)(nil), // 42: hyapp.wallet.v1.ListGiftConfigsResponse - (*ListGiftTypeConfigsRequest)(nil), // 43: hyapp.wallet.v1.ListGiftTypeConfigsRequest - (*ListGiftTypeConfigsResponse)(nil), // 44: hyapp.wallet.v1.ListGiftTypeConfigsResponse - (*UpsertGiftTypeConfigRequest)(nil), // 45: hyapp.wallet.v1.UpsertGiftTypeConfigRequest - (*GiftTypeConfigResponse)(nil), // 46: hyapp.wallet.v1.GiftTypeConfigResponse - (*CreateGiftConfigRequest)(nil), // 47: hyapp.wallet.v1.CreateGiftConfigRequest - (*UpdateGiftConfigRequest)(nil), // 48: hyapp.wallet.v1.UpdateGiftConfigRequest - (*SetGiftConfigStatusRequest)(nil), // 49: hyapp.wallet.v1.SetGiftConfigStatusRequest - (*GiftConfigResponse)(nil), // 50: hyapp.wallet.v1.GiftConfigResponse - (*GrantResourceRequest)(nil), // 51: hyapp.wallet.v1.GrantResourceRequest - (*GrantResourceGroupRequest)(nil), // 52: hyapp.wallet.v1.GrantResourceGroupRequest - (*ResourceGrantResponse)(nil), // 53: hyapp.wallet.v1.ResourceGrantResponse - (*ListUserResourcesRequest)(nil), // 54: hyapp.wallet.v1.ListUserResourcesRequest - (*ListUserResourcesResponse)(nil), // 55: hyapp.wallet.v1.ListUserResourcesResponse - (*EquipUserResourceRequest)(nil), // 56: hyapp.wallet.v1.EquipUserResourceRequest - (*EquipUserResourceResponse)(nil), // 57: hyapp.wallet.v1.EquipUserResourceResponse - (*UnequipUserResourceRequest)(nil), // 58: hyapp.wallet.v1.UnequipUserResourceRequest - (*UnequipUserResourceResponse)(nil), // 59: hyapp.wallet.v1.UnequipUserResourceResponse - (*BatchGetUserEquippedResourcesRequest)(nil), // 60: hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - (*UserEquippedResources)(nil), // 61: hyapp.wallet.v1.UserEquippedResources - (*BatchGetUserEquippedResourcesResponse)(nil), // 62: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - (*ListResourceGrantsRequest)(nil), // 63: hyapp.wallet.v1.ListResourceGrantsRequest - (*ListResourceGrantsResponse)(nil), // 64: hyapp.wallet.v1.ListResourceGrantsResponse - (*ResourceShopItemInput)(nil), // 65: hyapp.wallet.v1.ResourceShopItemInput - (*ListResourceShopItemsRequest)(nil), // 66: hyapp.wallet.v1.ListResourceShopItemsRequest - (*ListResourceShopItemsResponse)(nil), // 67: hyapp.wallet.v1.ListResourceShopItemsResponse - (*UpsertResourceShopItemsRequest)(nil), // 68: hyapp.wallet.v1.UpsertResourceShopItemsRequest - (*UpsertResourceShopItemsResponse)(nil), // 69: hyapp.wallet.v1.UpsertResourceShopItemsResponse - (*SetResourceShopItemStatusRequest)(nil), // 70: hyapp.wallet.v1.SetResourceShopItemStatusRequest - (*ResourceShopItemResponse)(nil), // 71: hyapp.wallet.v1.ResourceShopItemResponse - (*PurchaseResourceShopItemRequest)(nil), // 72: hyapp.wallet.v1.PurchaseResourceShopItemRequest - (*PurchaseResourceShopItemResponse)(nil), // 73: hyapp.wallet.v1.PurchaseResourceShopItemResponse - (*RechargeBill)(nil), // 74: hyapp.wallet.v1.RechargeBill - (*ListRechargeBillsRequest)(nil), // 75: hyapp.wallet.v1.ListRechargeBillsRequest - (*ListRechargeBillsResponse)(nil), // 76: hyapp.wallet.v1.ListRechargeBillsResponse - (*WalletFeatureFlags)(nil), // 77: hyapp.wallet.v1.WalletFeatureFlags - (*GetWalletOverviewRequest)(nil), // 78: hyapp.wallet.v1.GetWalletOverviewRequest - (*GetWalletOverviewResponse)(nil), // 79: hyapp.wallet.v1.GetWalletOverviewResponse - (*WalletValueSummary)(nil), // 80: hyapp.wallet.v1.WalletValueSummary - (*GetWalletValueSummaryRequest)(nil), // 81: hyapp.wallet.v1.GetWalletValueSummaryRequest - (*GetWalletValueSummaryResponse)(nil), // 82: hyapp.wallet.v1.GetWalletValueSummaryResponse - (*GiftWallItem)(nil), // 83: hyapp.wallet.v1.GiftWallItem - (*GetUserGiftWallRequest)(nil), // 84: hyapp.wallet.v1.GetUserGiftWallRequest - (*GetUserGiftWallResponse)(nil), // 85: hyapp.wallet.v1.GetUserGiftWallResponse - (*RechargeProduct)(nil), // 86: hyapp.wallet.v1.RechargeProduct - (*ListRechargeProductsRequest)(nil), // 87: hyapp.wallet.v1.ListRechargeProductsRequest - (*ListRechargeProductsResponse)(nil), // 88: hyapp.wallet.v1.ListRechargeProductsResponse - (*ConfirmGooglePaymentRequest)(nil), // 89: hyapp.wallet.v1.ConfirmGooglePaymentRequest - (*ConfirmGooglePaymentResponse)(nil), // 90: hyapp.wallet.v1.ConfirmGooglePaymentResponse - (*ListAdminRechargeProductsRequest)(nil), // 91: hyapp.wallet.v1.ListAdminRechargeProductsRequest - (*ListAdminRechargeProductsResponse)(nil), // 92: hyapp.wallet.v1.ListAdminRechargeProductsResponse - (*CreateRechargeProductRequest)(nil), // 93: hyapp.wallet.v1.CreateRechargeProductRequest - (*UpdateRechargeProductRequest)(nil), // 94: hyapp.wallet.v1.UpdateRechargeProductRequest - (*DeleteRechargeProductRequest)(nil), // 95: hyapp.wallet.v1.DeleteRechargeProductRequest - (*RechargeProductResponse)(nil), // 96: hyapp.wallet.v1.RechargeProductResponse - (*DeleteRechargeProductResponse)(nil), // 97: hyapp.wallet.v1.DeleteRechargeProductResponse - (*DiamondExchangeRule)(nil), // 98: hyapp.wallet.v1.DiamondExchangeRule - (*GetDiamondExchangeConfigRequest)(nil), // 99: hyapp.wallet.v1.GetDiamondExchangeConfigRequest - (*GetDiamondExchangeConfigResponse)(nil), // 100: hyapp.wallet.v1.GetDiamondExchangeConfigResponse - (*WalletTransaction)(nil), // 101: hyapp.wallet.v1.WalletTransaction - (*ListWalletTransactionsRequest)(nil), // 102: hyapp.wallet.v1.ListWalletTransactionsRequest - (*ListWalletTransactionsResponse)(nil), // 103: hyapp.wallet.v1.ListWalletTransactionsResponse - (*VipRewardItem)(nil), // 104: hyapp.wallet.v1.VipRewardItem - (*VipLevel)(nil), // 105: hyapp.wallet.v1.VipLevel - (*UserVip)(nil), // 106: hyapp.wallet.v1.UserVip - (*ListVipPackagesRequest)(nil), // 107: hyapp.wallet.v1.ListVipPackagesRequest - (*ListVipPackagesResponse)(nil), // 108: hyapp.wallet.v1.ListVipPackagesResponse - (*GetMyVipRequest)(nil), // 109: hyapp.wallet.v1.GetMyVipRequest - (*GetMyVipResponse)(nil), // 110: hyapp.wallet.v1.GetMyVipResponse - (*PurchaseVipRequest)(nil), // 111: hyapp.wallet.v1.PurchaseVipRequest - (*PurchaseVipResponse)(nil), // 112: hyapp.wallet.v1.PurchaseVipResponse - (*GrantVipRequest)(nil), // 113: hyapp.wallet.v1.GrantVipRequest - (*GrantVipResponse)(nil), // 114: hyapp.wallet.v1.GrantVipResponse - (*AdminVipLevelInput)(nil), // 115: hyapp.wallet.v1.AdminVipLevelInput - (*ListAdminVipLevelsRequest)(nil), // 116: hyapp.wallet.v1.ListAdminVipLevelsRequest - (*ListAdminVipLevelsResponse)(nil), // 117: hyapp.wallet.v1.ListAdminVipLevelsResponse - (*UpdateAdminVipLevelsRequest)(nil), // 118: hyapp.wallet.v1.UpdateAdminVipLevelsRequest - (*UpdateAdminVipLevelsResponse)(nil), // 119: hyapp.wallet.v1.UpdateAdminVipLevelsResponse - (*CreditTaskRewardRequest)(nil), // 120: hyapp.wallet.v1.CreditTaskRewardRequest - (*CreditTaskRewardResponse)(nil), // 121: hyapp.wallet.v1.CreditTaskRewardResponse - (*CreditLuckyGiftRewardRequest)(nil), // 122: hyapp.wallet.v1.CreditLuckyGiftRewardRequest - (*CreditLuckyGiftRewardResponse)(nil), // 123: hyapp.wallet.v1.CreditLuckyGiftRewardResponse - (*ApplyGameCoinChangeRequest)(nil), // 124: hyapp.wallet.v1.ApplyGameCoinChangeRequest - (*ApplyGameCoinChangeResponse)(nil), // 125: hyapp.wallet.v1.ApplyGameCoinChangeResponse - (*RedPacketConfig)(nil), // 126: hyapp.wallet.v1.RedPacketConfig - (*RedPacketClaim)(nil), // 127: hyapp.wallet.v1.RedPacketClaim - (*RedPacket)(nil), // 128: hyapp.wallet.v1.RedPacket - (*GetRedPacketConfigRequest)(nil), // 129: hyapp.wallet.v1.GetRedPacketConfigRequest - (*GetRedPacketConfigResponse)(nil), // 130: hyapp.wallet.v1.GetRedPacketConfigResponse - (*UpdateRedPacketConfigRequest)(nil), // 131: hyapp.wallet.v1.UpdateRedPacketConfigRequest - (*UpdateRedPacketConfigResponse)(nil), // 132: hyapp.wallet.v1.UpdateRedPacketConfigResponse - (*CreateRedPacketRequest)(nil), // 133: hyapp.wallet.v1.CreateRedPacketRequest - (*CreateRedPacketResponse)(nil), // 134: hyapp.wallet.v1.CreateRedPacketResponse - (*ClaimRedPacketRequest)(nil), // 135: hyapp.wallet.v1.ClaimRedPacketRequest - (*ClaimRedPacketResponse)(nil), // 136: hyapp.wallet.v1.ClaimRedPacketResponse - (*ListRedPacketsRequest)(nil), // 137: hyapp.wallet.v1.ListRedPacketsRequest - (*ListRedPacketsResponse)(nil), // 138: hyapp.wallet.v1.ListRedPacketsResponse - (*GetRedPacketRequest)(nil), // 139: hyapp.wallet.v1.GetRedPacketRequest - (*GetRedPacketResponse)(nil), // 140: hyapp.wallet.v1.GetRedPacketResponse - (*ExpireRedPacketsRequest)(nil), // 141: hyapp.wallet.v1.ExpireRedPacketsRequest - (*ExpireRedPacketsResponse)(nil), // 142: hyapp.wallet.v1.ExpireRedPacketsResponse - (*RetryRedPacketRefundRequest)(nil), // 143: hyapp.wallet.v1.RetryRedPacketRefundRequest - (*RetryRedPacketRefundResponse)(nil), // 144: hyapp.wallet.v1.RetryRedPacketRefundResponse - (*CronBatchRequest)(nil), // 145: hyapp.wallet.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 146: hyapp.wallet.v1.CronBatchResponse + (*HostSalaryPolicyLevel)(nil), // 9: hyapp.wallet.v1.HostSalaryPolicyLevel + (*HostSalaryPolicy)(nil), // 10: hyapp.wallet.v1.HostSalaryPolicy + (*GetActiveHostSalaryPolicyRequest)(nil), // 11: hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + (*GetActiveHostSalaryPolicyResponse)(nil), // 12: hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + (*HostSalaryProgress)(nil), // 13: hyapp.wallet.v1.HostSalaryProgress + (*GetHostSalaryProgressRequest)(nil), // 14: hyapp.wallet.v1.GetHostSalaryProgressRequest + (*GetHostSalaryProgressResponse)(nil), // 15: hyapp.wallet.v1.GetHostSalaryProgressResponse + (*AdminCreditAssetRequest)(nil), // 16: hyapp.wallet.v1.AdminCreditAssetRequest + (*AdminCreditAssetResponse)(nil), // 17: hyapp.wallet.v1.AdminCreditAssetResponse + (*AdminCreditCoinSellerStockRequest)(nil), // 18: hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + (*AdminCreditCoinSellerStockResponse)(nil), // 19: hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + (*TransferCoinFromSellerRequest)(nil), // 20: hyapp.wallet.v1.TransferCoinFromSellerRequest + (*TransferCoinFromSellerResponse)(nil), // 21: hyapp.wallet.v1.TransferCoinFromSellerResponse + (*Resource)(nil), // 22: hyapp.wallet.v1.Resource + (*ResourceGroupItem)(nil), // 23: hyapp.wallet.v1.ResourceGroupItem + (*ResourceGroup)(nil), // 24: hyapp.wallet.v1.ResourceGroup + (*GiftConfig)(nil), // 25: hyapp.wallet.v1.GiftConfig + (*GiftTypeConfig)(nil), // 26: hyapp.wallet.v1.GiftTypeConfig + (*ResourceShopItem)(nil), // 27: hyapp.wallet.v1.ResourceShopItem + (*UserResourceEntitlement)(nil), // 28: hyapp.wallet.v1.UserResourceEntitlement + (*ResourceGrantItem)(nil), // 29: hyapp.wallet.v1.ResourceGrantItem + (*ResourceGrant)(nil), // 30: hyapp.wallet.v1.ResourceGrant + (*ResourceGroupItemInput)(nil), // 31: hyapp.wallet.v1.ResourceGroupItemInput + (*ListResourcesRequest)(nil), // 32: hyapp.wallet.v1.ListResourcesRequest + (*ListResourcesResponse)(nil), // 33: hyapp.wallet.v1.ListResourcesResponse + (*GetResourceRequest)(nil), // 34: hyapp.wallet.v1.GetResourceRequest + (*GetResourceResponse)(nil), // 35: hyapp.wallet.v1.GetResourceResponse + (*CreateResourceRequest)(nil), // 36: hyapp.wallet.v1.CreateResourceRequest + (*UpdateResourceRequest)(nil), // 37: hyapp.wallet.v1.UpdateResourceRequest + (*SetResourceStatusRequest)(nil), // 38: hyapp.wallet.v1.SetResourceStatusRequest + (*ResourceResponse)(nil), // 39: hyapp.wallet.v1.ResourceResponse + (*ListResourceGroupsRequest)(nil), // 40: hyapp.wallet.v1.ListResourceGroupsRequest + (*ListResourceGroupsResponse)(nil), // 41: hyapp.wallet.v1.ListResourceGroupsResponse + (*GetResourceGroupRequest)(nil), // 42: hyapp.wallet.v1.GetResourceGroupRequest + (*GetResourceGroupResponse)(nil), // 43: hyapp.wallet.v1.GetResourceGroupResponse + (*CreateResourceGroupRequest)(nil), // 44: hyapp.wallet.v1.CreateResourceGroupRequest + (*UpdateResourceGroupRequest)(nil), // 45: hyapp.wallet.v1.UpdateResourceGroupRequest + (*SetResourceGroupStatusRequest)(nil), // 46: hyapp.wallet.v1.SetResourceGroupStatusRequest + (*ResourceGroupResponse)(nil), // 47: hyapp.wallet.v1.ResourceGroupResponse + (*ListGiftConfigsRequest)(nil), // 48: hyapp.wallet.v1.ListGiftConfigsRequest + (*ListGiftConfigsResponse)(nil), // 49: hyapp.wallet.v1.ListGiftConfigsResponse + (*ListGiftTypeConfigsRequest)(nil), // 50: hyapp.wallet.v1.ListGiftTypeConfigsRequest + (*ListGiftTypeConfigsResponse)(nil), // 51: hyapp.wallet.v1.ListGiftTypeConfigsResponse + (*UpsertGiftTypeConfigRequest)(nil), // 52: hyapp.wallet.v1.UpsertGiftTypeConfigRequest + (*GiftTypeConfigResponse)(nil), // 53: hyapp.wallet.v1.GiftTypeConfigResponse + (*CreateGiftConfigRequest)(nil), // 54: hyapp.wallet.v1.CreateGiftConfigRequest + (*UpdateGiftConfigRequest)(nil), // 55: hyapp.wallet.v1.UpdateGiftConfigRequest + (*SetGiftConfigStatusRequest)(nil), // 56: hyapp.wallet.v1.SetGiftConfigStatusRequest + (*GiftConfigResponse)(nil), // 57: hyapp.wallet.v1.GiftConfigResponse + (*GrantResourceRequest)(nil), // 58: hyapp.wallet.v1.GrantResourceRequest + (*GrantResourceGroupRequest)(nil), // 59: hyapp.wallet.v1.GrantResourceGroupRequest + (*ResourceGrantResponse)(nil), // 60: hyapp.wallet.v1.ResourceGrantResponse + (*ListUserResourcesRequest)(nil), // 61: hyapp.wallet.v1.ListUserResourcesRequest + (*ListUserResourcesResponse)(nil), // 62: hyapp.wallet.v1.ListUserResourcesResponse + (*EquipUserResourceRequest)(nil), // 63: hyapp.wallet.v1.EquipUserResourceRequest + (*EquipUserResourceResponse)(nil), // 64: hyapp.wallet.v1.EquipUserResourceResponse + (*UnequipUserResourceRequest)(nil), // 65: hyapp.wallet.v1.UnequipUserResourceRequest + (*UnequipUserResourceResponse)(nil), // 66: hyapp.wallet.v1.UnequipUserResourceResponse + (*BatchGetUserEquippedResourcesRequest)(nil), // 67: hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + (*UserEquippedResources)(nil), // 68: hyapp.wallet.v1.UserEquippedResources + (*BatchGetUserEquippedResourcesResponse)(nil), // 69: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + (*ListResourceGrantsRequest)(nil), // 70: hyapp.wallet.v1.ListResourceGrantsRequest + (*ListResourceGrantsResponse)(nil), // 71: hyapp.wallet.v1.ListResourceGrantsResponse + (*ResourceShopItemInput)(nil), // 72: hyapp.wallet.v1.ResourceShopItemInput + (*ListResourceShopItemsRequest)(nil), // 73: hyapp.wallet.v1.ListResourceShopItemsRequest + (*ListResourceShopItemsResponse)(nil), // 74: hyapp.wallet.v1.ListResourceShopItemsResponse + (*UpsertResourceShopItemsRequest)(nil), // 75: hyapp.wallet.v1.UpsertResourceShopItemsRequest + (*UpsertResourceShopItemsResponse)(nil), // 76: hyapp.wallet.v1.UpsertResourceShopItemsResponse + (*SetResourceShopItemStatusRequest)(nil), // 77: hyapp.wallet.v1.SetResourceShopItemStatusRequest + (*ResourceShopItemResponse)(nil), // 78: hyapp.wallet.v1.ResourceShopItemResponse + (*PurchaseResourceShopItemRequest)(nil), // 79: hyapp.wallet.v1.PurchaseResourceShopItemRequest + (*PurchaseResourceShopItemResponse)(nil), // 80: hyapp.wallet.v1.PurchaseResourceShopItemResponse + (*RechargeBill)(nil), // 81: hyapp.wallet.v1.RechargeBill + (*ListRechargeBillsRequest)(nil), // 82: hyapp.wallet.v1.ListRechargeBillsRequest + (*ListRechargeBillsResponse)(nil), // 83: hyapp.wallet.v1.ListRechargeBillsResponse + (*WalletFeatureFlags)(nil), // 84: hyapp.wallet.v1.WalletFeatureFlags + (*GetWalletOverviewRequest)(nil), // 85: hyapp.wallet.v1.GetWalletOverviewRequest + (*GetWalletOverviewResponse)(nil), // 86: hyapp.wallet.v1.GetWalletOverviewResponse + (*WalletValueSummary)(nil), // 87: hyapp.wallet.v1.WalletValueSummary + (*GetWalletValueSummaryRequest)(nil), // 88: hyapp.wallet.v1.GetWalletValueSummaryRequest + (*GetWalletValueSummaryResponse)(nil), // 89: hyapp.wallet.v1.GetWalletValueSummaryResponse + (*GiftWallItem)(nil), // 90: hyapp.wallet.v1.GiftWallItem + (*GetUserGiftWallRequest)(nil), // 91: hyapp.wallet.v1.GetUserGiftWallRequest + (*GetUserGiftWallResponse)(nil), // 92: hyapp.wallet.v1.GetUserGiftWallResponse + (*RechargeProduct)(nil), // 93: hyapp.wallet.v1.RechargeProduct + (*ListRechargeProductsRequest)(nil), // 94: hyapp.wallet.v1.ListRechargeProductsRequest + (*ListRechargeProductsResponse)(nil), // 95: hyapp.wallet.v1.ListRechargeProductsResponse + (*ConfirmGooglePaymentRequest)(nil), // 96: hyapp.wallet.v1.ConfirmGooglePaymentRequest + (*ConfirmGooglePaymentResponse)(nil), // 97: hyapp.wallet.v1.ConfirmGooglePaymentResponse + (*ListAdminRechargeProductsRequest)(nil), // 98: hyapp.wallet.v1.ListAdminRechargeProductsRequest + (*ListAdminRechargeProductsResponse)(nil), // 99: hyapp.wallet.v1.ListAdminRechargeProductsResponse + (*CreateRechargeProductRequest)(nil), // 100: hyapp.wallet.v1.CreateRechargeProductRequest + (*UpdateRechargeProductRequest)(nil), // 101: hyapp.wallet.v1.UpdateRechargeProductRequest + (*DeleteRechargeProductRequest)(nil), // 102: hyapp.wallet.v1.DeleteRechargeProductRequest + (*RechargeProductResponse)(nil), // 103: hyapp.wallet.v1.RechargeProductResponse + (*DeleteRechargeProductResponse)(nil), // 104: hyapp.wallet.v1.DeleteRechargeProductResponse + (*DiamondExchangeRule)(nil), // 105: hyapp.wallet.v1.DiamondExchangeRule + (*GetDiamondExchangeConfigRequest)(nil), // 106: hyapp.wallet.v1.GetDiamondExchangeConfigRequest + (*GetDiamondExchangeConfigResponse)(nil), // 107: hyapp.wallet.v1.GetDiamondExchangeConfigResponse + (*WalletTransaction)(nil), // 108: hyapp.wallet.v1.WalletTransaction + (*ListWalletTransactionsRequest)(nil), // 109: hyapp.wallet.v1.ListWalletTransactionsRequest + (*ListWalletTransactionsResponse)(nil), // 110: hyapp.wallet.v1.ListWalletTransactionsResponse + (*VipRewardItem)(nil), // 111: hyapp.wallet.v1.VipRewardItem + (*VipLevel)(nil), // 112: hyapp.wallet.v1.VipLevel + (*UserVip)(nil), // 113: hyapp.wallet.v1.UserVip + (*ListVipPackagesRequest)(nil), // 114: hyapp.wallet.v1.ListVipPackagesRequest + (*ListVipPackagesResponse)(nil), // 115: hyapp.wallet.v1.ListVipPackagesResponse + (*GetMyVipRequest)(nil), // 116: hyapp.wallet.v1.GetMyVipRequest + (*GetMyVipResponse)(nil), // 117: hyapp.wallet.v1.GetMyVipResponse + (*PurchaseVipRequest)(nil), // 118: hyapp.wallet.v1.PurchaseVipRequest + (*PurchaseVipResponse)(nil), // 119: hyapp.wallet.v1.PurchaseVipResponse + (*GrantVipRequest)(nil), // 120: hyapp.wallet.v1.GrantVipRequest + (*GrantVipResponse)(nil), // 121: hyapp.wallet.v1.GrantVipResponse + (*AdminVipLevelInput)(nil), // 122: hyapp.wallet.v1.AdminVipLevelInput + (*ListAdminVipLevelsRequest)(nil), // 123: hyapp.wallet.v1.ListAdminVipLevelsRequest + (*ListAdminVipLevelsResponse)(nil), // 124: hyapp.wallet.v1.ListAdminVipLevelsResponse + (*UpdateAdminVipLevelsRequest)(nil), // 125: hyapp.wallet.v1.UpdateAdminVipLevelsRequest + (*UpdateAdminVipLevelsResponse)(nil), // 126: hyapp.wallet.v1.UpdateAdminVipLevelsResponse + (*CreditTaskRewardRequest)(nil), // 127: hyapp.wallet.v1.CreditTaskRewardRequest + (*CreditTaskRewardResponse)(nil), // 128: hyapp.wallet.v1.CreditTaskRewardResponse + (*CreditLuckyGiftRewardRequest)(nil), // 129: hyapp.wallet.v1.CreditLuckyGiftRewardRequest + (*CreditLuckyGiftRewardResponse)(nil), // 130: hyapp.wallet.v1.CreditLuckyGiftRewardResponse + (*ApplyGameCoinChangeRequest)(nil), // 131: hyapp.wallet.v1.ApplyGameCoinChangeRequest + (*ApplyGameCoinChangeResponse)(nil), // 132: hyapp.wallet.v1.ApplyGameCoinChangeResponse + (*RedPacketConfig)(nil), // 133: hyapp.wallet.v1.RedPacketConfig + (*RedPacketClaim)(nil), // 134: hyapp.wallet.v1.RedPacketClaim + (*RedPacket)(nil), // 135: hyapp.wallet.v1.RedPacket + (*GetRedPacketConfigRequest)(nil), // 136: hyapp.wallet.v1.GetRedPacketConfigRequest + (*GetRedPacketConfigResponse)(nil), // 137: hyapp.wallet.v1.GetRedPacketConfigResponse + (*UpdateRedPacketConfigRequest)(nil), // 138: hyapp.wallet.v1.UpdateRedPacketConfigRequest + (*UpdateRedPacketConfigResponse)(nil), // 139: hyapp.wallet.v1.UpdateRedPacketConfigResponse + (*CreateRedPacketRequest)(nil), // 140: hyapp.wallet.v1.CreateRedPacketRequest + (*CreateRedPacketResponse)(nil), // 141: hyapp.wallet.v1.CreateRedPacketResponse + (*ClaimRedPacketRequest)(nil), // 142: hyapp.wallet.v1.ClaimRedPacketRequest + (*ClaimRedPacketResponse)(nil), // 143: hyapp.wallet.v1.ClaimRedPacketResponse + (*ListRedPacketsRequest)(nil), // 144: hyapp.wallet.v1.ListRedPacketsRequest + (*ListRedPacketsResponse)(nil), // 145: hyapp.wallet.v1.ListRedPacketsResponse + (*GetRedPacketRequest)(nil), // 146: hyapp.wallet.v1.GetRedPacketRequest + (*GetRedPacketResponse)(nil), // 147: hyapp.wallet.v1.GetRedPacketResponse + (*ExpireRedPacketsRequest)(nil), // 148: hyapp.wallet.v1.ExpireRedPacketsRequest + (*ExpireRedPacketsResponse)(nil), // 149: hyapp.wallet.v1.ExpireRedPacketsResponse + (*RetryRedPacketRefundRequest)(nil), // 150: hyapp.wallet.v1.RetryRedPacketRefundRequest + (*RetryRedPacketRefundResponse)(nil), // 151: hyapp.wallet.v1.RetryRedPacketRefundResponse + (*CronBatchRequest)(nil), // 152: hyapp.wallet.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 153: hyapp.wallet.v1.CronBatchResponse } var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 2, // 0: hyapp.wallet.v1.BatchDebitGiftRequest.targets:type_name -> hyapp.wallet.v1.DebitGiftTarget @@ -14438,207 +15063,214 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 1, // 2: hyapp.wallet.v1.BatchDebitGiftResponse.aggregate:type_name -> hyapp.wallet.v1.DebitGiftResponse 4, // 3: hyapp.wallet.v1.BatchDebitGiftResponse.receipts:type_name -> hyapp.wallet.v1.BatchDebitGiftReceipt 6, // 4: hyapp.wallet.v1.GetBalancesResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance - 6, // 5: hyapp.wallet.v1.AdminCreditAssetResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 15, // 6: hyapp.wallet.v1.ResourceGroupItem.resource:type_name -> hyapp.wallet.v1.Resource - 16, // 7: hyapp.wallet.v1.ResourceGroup.items:type_name -> hyapp.wallet.v1.ResourceGroupItem - 15, // 8: hyapp.wallet.v1.GiftConfig.resource:type_name -> hyapp.wallet.v1.Resource - 15, // 9: hyapp.wallet.v1.ResourceShopItem.resource:type_name -> hyapp.wallet.v1.Resource - 15, // 10: hyapp.wallet.v1.UserResourceEntitlement.resource:type_name -> hyapp.wallet.v1.Resource - 22, // 11: hyapp.wallet.v1.ResourceGrant.items:type_name -> hyapp.wallet.v1.ResourceGrantItem - 15, // 12: hyapp.wallet.v1.ListResourcesResponse.resources:type_name -> hyapp.wallet.v1.Resource - 15, // 13: hyapp.wallet.v1.GetResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource - 15, // 14: hyapp.wallet.v1.ResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource - 17, // 15: hyapp.wallet.v1.ListResourceGroupsResponse.groups:type_name -> hyapp.wallet.v1.ResourceGroup - 17, // 16: hyapp.wallet.v1.GetResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup - 24, // 17: hyapp.wallet.v1.CreateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput - 24, // 18: hyapp.wallet.v1.UpdateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput - 17, // 19: hyapp.wallet.v1.ResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup - 18, // 20: hyapp.wallet.v1.ListGiftConfigsResponse.gifts:type_name -> hyapp.wallet.v1.GiftConfig - 19, // 21: hyapp.wallet.v1.ListGiftTypeConfigsResponse.gift_types:type_name -> hyapp.wallet.v1.GiftTypeConfig - 19, // 22: hyapp.wallet.v1.GiftTypeConfigResponse.gift_type:type_name -> hyapp.wallet.v1.GiftTypeConfig - 18, // 23: hyapp.wallet.v1.GiftConfigResponse.gift:type_name -> hyapp.wallet.v1.GiftConfig - 23, // 24: hyapp.wallet.v1.ResourceGrantResponse.grant:type_name -> hyapp.wallet.v1.ResourceGrant - 21, // 25: hyapp.wallet.v1.ListUserResourcesResponse.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 21, // 26: hyapp.wallet.v1.EquipUserResourceResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 21, // 27: hyapp.wallet.v1.UserEquippedResources.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 61, // 28: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse.users:type_name -> hyapp.wallet.v1.UserEquippedResources - 23, // 29: hyapp.wallet.v1.ListResourceGrantsResponse.grants:type_name -> hyapp.wallet.v1.ResourceGrant - 20, // 30: hyapp.wallet.v1.ListResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem - 65, // 31: hyapp.wallet.v1.UpsertResourceShopItemsRequest.items:type_name -> hyapp.wallet.v1.ResourceShopItemInput - 20, // 32: hyapp.wallet.v1.UpsertResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem - 20, // 33: hyapp.wallet.v1.ResourceShopItemResponse.item:type_name -> hyapp.wallet.v1.ResourceShopItem - 20, // 34: hyapp.wallet.v1.PurchaseResourceShopItemResponse.shop_item:type_name -> hyapp.wallet.v1.ResourceShopItem - 21, // 35: hyapp.wallet.v1.PurchaseResourceShopItemResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 6, // 36: hyapp.wallet.v1.PurchaseResourceShopItemResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 74, // 37: hyapp.wallet.v1.ListRechargeBillsResponse.bills:type_name -> hyapp.wallet.v1.RechargeBill - 6, // 38: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance - 77, // 39: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags - 80, // 40: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary - 15, // 41: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource - 83, // 42: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem - 86, // 43: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 6, // 44: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 86, // 45: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 86, // 46: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct - 98, // 47: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule - 101, // 48: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction - 104, // 49: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 106, // 50: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip - 105, // 51: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel - 106, // 52: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 106, // 53: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 104, // 54: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 106, // 55: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 104, // 56: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 105, // 57: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 115, // 58: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput - 105, // 59: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 6, // 60: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 6, // 61: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 127, // 62: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 126, // 63: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 126, // 64: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 128, // 65: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 127, // 66: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 128, // 67: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 128, // 68: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 128, // 69: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 128, // 70: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 145, // 71: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 145, // 72: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 145, // 73: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 0, // 74: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 3, // 75: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest - 7, // 76: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 9, // 77: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 11, // 78: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 13, // 79: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 25, // 80: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 27, // 81: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 29, // 82: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 30, // 83: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 31, // 84: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 33, // 85: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 35, // 86: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 37, // 87: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 38, // 88: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 39, // 89: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 41, // 90: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 43, // 91: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 47, // 92: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 48, // 93: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 49, // 94: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 45, // 95: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 51, // 96: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 52, // 97: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 54, // 98: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 56, // 99: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 58, // 100: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest - 60, // 101: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - 63, // 102: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 66, // 103: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 68, // 104: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 70, // 105: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 72, // 106: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 75, // 107: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 78, // 108: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 81, // 109: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 84, // 110: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 87, // 111: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 89, // 112: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 91, // 113: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 93, // 114: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 94, // 115: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 95, // 116: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 99, // 117: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 102, // 118: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 107, // 119: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 109, // 120: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 111, // 121: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 113, // 122: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 116, // 123: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 118, // 124: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 120, // 125: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 122, // 126: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 124, // 127: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 129, // 128: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 131, // 129: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 133, // 130: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 135, // 131: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 137, // 132: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 139, // 133: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 141, // 134: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 143, // 135: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 146, // 136: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 146, // 137: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 146, // 138: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 1, // 139: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 5, // 140: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse - 8, // 141: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 10, // 142: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 12, // 143: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 14, // 144: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 26, // 145: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 28, // 146: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 32, // 147: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 32, // 148: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 32, // 149: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 34, // 150: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 36, // 151: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 40, // 152: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 40, // 153: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 40, // 154: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 42, // 155: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 44, // 156: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 50, // 157: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 50, // 158: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 50, // 159: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 46, // 160: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 53, // 161: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 53, // 162: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 55, // 163: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 57, // 164: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 59, // 165: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse - 62, // 166: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - 64, // 167: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 67, // 168: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 69, // 169: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 71, // 170: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 73, // 171: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 76, // 172: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 79, // 173: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 82, // 174: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 85, // 175: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 88, // 176: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 90, // 177: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 92, // 178: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 96, // 179: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 96, // 180: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 97, // 181: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 100, // 182: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 103, // 183: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 108, // 184: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 110, // 185: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 112, // 186: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 114, // 187: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 117, // 188: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 119, // 189: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 121, // 190: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 123, // 191: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 125, // 192: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 130, // 193: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 132, // 194: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 134, // 195: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 136, // 196: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 138, // 197: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 140, // 198: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 142, // 199: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 144, // 200: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 136, // [136:201] is the sub-list for method output_type - 71, // [71:136] is the sub-list for method input_type - 71, // [71:71] is the sub-list for extension type_name - 71, // [71:71] is the sub-list for extension extendee - 0, // [0:71] is the sub-list for field type_name + 9, // 5: hyapp.wallet.v1.HostSalaryPolicy.levels:type_name -> hyapp.wallet.v1.HostSalaryPolicyLevel + 10, // 6: hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse.policy:type_name -> hyapp.wallet.v1.HostSalaryPolicy + 13, // 7: hyapp.wallet.v1.GetHostSalaryProgressResponse.progress:type_name -> hyapp.wallet.v1.HostSalaryProgress + 6, // 8: hyapp.wallet.v1.AdminCreditAssetResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 22, // 9: hyapp.wallet.v1.ResourceGroupItem.resource:type_name -> hyapp.wallet.v1.Resource + 23, // 10: hyapp.wallet.v1.ResourceGroup.items:type_name -> hyapp.wallet.v1.ResourceGroupItem + 22, // 11: hyapp.wallet.v1.GiftConfig.resource:type_name -> hyapp.wallet.v1.Resource + 22, // 12: hyapp.wallet.v1.ResourceShopItem.resource:type_name -> hyapp.wallet.v1.Resource + 22, // 13: hyapp.wallet.v1.UserResourceEntitlement.resource:type_name -> hyapp.wallet.v1.Resource + 29, // 14: hyapp.wallet.v1.ResourceGrant.items:type_name -> hyapp.wallet.v1.ResourceGrantItem + 22, // 15: hyapp.wallet.v1.ListResourcesResponse.resources:type_name -> hyapp.wallet.v1.Resource + 22, // 16: hyapp.wallet.v1.GetResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource + 22, // 17: hyapp.wallet.v1.ResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource + 24, // 18: hyapp.wallet.v1.ListResourceGroupsResponse.groups:type_name -> hyapp.wallet.v1.ResourceGroup + 24, // 19: hyapp.wallet.v1.GetResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup + 31, // 20: hyapp.wallet.v1.CreateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput + 31, // 21: hyapp.wallet.v1.UpdateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput + 24, // 22: hyapp.wallet.v1.ResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup + 25, // 23: hyapp.wallet.v1.ListGiftConfigsResponse.gifts:type_name -> hyapp.wallet.v1.GiftConfig + 26, // 24: hyapp.wallet.v1.ListGiftTypeConfigsResponse.gift_types:type_name -> hyapp.wallet.v1.GiftTypeConfig + 26, // 25: hyapp.wallet.v1.GiftTypeConfigResponse.gift_type:type_name -> hyapp.wallet.v1.GiftTypeConfig + 25, // 26: hyapp.wallet.v1.GiftConfigResponse.gift:type_name -> hyapp.wallet.v1.GiftConfig + 30, // 27: hyapp.wallet.v1.ResourceGrantResponse.grant:type_name -> hyapp.wallet.v1.ResourceGrant + 28, // 28: hyapp.wallet.v1.ListUserResourcesResponse.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 28, // 29: hyapp.wallet.v1.EquipUserResourceResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 28, // 30: hyapp.wallet.v1.UserEquippedResources.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 68, // 31: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse.users:type_name -> hyapp.wallet.v1.UserEquippedResources + 30, // 32: hyapp.wallet.v1.ListResourceGrantsResponse.grants:type_name -> hyapp.wallet.v1.ResourceGrant + 27, // 33: hyapp.wallet.v1.ListResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem + 72, // 34: hyapp.wallet.v1.UpsertResourceShopItemsRequest.items:type_name -> hyapp.wallet.v1.ResourceShopItemInput + 27, // 35: hyapp.wallet.v1.UpsertResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem + 27, // 36: hyapp.wallet.v1.ResourceShopItemResponse.item:type_name -> hyapp.wallet.v1.ResourceShopItem + 27, // 37: hyapp.wallet.v1.PurchaseResourceShopItemResponse.shop_item:type_name -> hyapp.wallet.v1.ResourceShopItem + 28, // 38: hyapp.wallet.v1.PurchaseResourceShopItemResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 6, // 39: hyapp.wallet.v1.PurchaseResourceShopItemResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 81, // 40: hyapp.wallet.v1.ListRechargeBillsResponse.bills:type_name -> hyapp.wallet.v1.RechargeBill + 6, // 41: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance + 84, // 42: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags + 87, // 43: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary + 22, // 44: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource + 90, // 45: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem + 93, // 46: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 6, // 47: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 93, // 48: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 93, // 49: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct + 105, // 50: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule + 108, // 51: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction + 111, // 52: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 113, // 53: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip + 112, // 54: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel + 113, // 55: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 113, // 56: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 111, // 57: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 113, // 58: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 111, // 59: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 112, // 60: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 122, // 61: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput + 112, // 62: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 6, // 63: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 6, // 64: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 134, // 65: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 133, // 66: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 133, // 67: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 135, // 68: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 134, // 69: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 135, // 70: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 135, // 71: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 135, // 72: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 135, // 73: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 152, // 74: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 152, // 75: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 152, // 76: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 0, // 77: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 3, // 78: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest + 7, // 79: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 11, // 80: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + 14, // 81: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest + 16, // 82: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 18, // 83: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 20, // 84: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 32, // 85: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 34, // 86: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 36, // 87: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 37, // 88: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 38, // 89: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 40, // 90: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 42, // 91: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 44, // 92: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 45, // 93: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 46, // 94: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 48, // 95: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 50, // 96: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 54, // 97: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 55, // 98: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 56, // 99: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 52, // 100: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 58, // 101: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 59, // 102: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 61, // 103: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 63, // 104: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 65, // 105: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest + 67, // 106: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + 70, // 107: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 73, // 108: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 75, // 109: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 77, // 110: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 79, // 111: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 82, // 112: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 85, // 113: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 88, // 114: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 91, // 115: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 94, // 116: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 96, // 117: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 98, // 118: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 100, // 119: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 101, // 120: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 102, // 121: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 106, // 122: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 109, // 123: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 114, // 124: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 116, // 125: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 118, // 126: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 120, // 127: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 123, // 128: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 125, // 129: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 127, // 130: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 129, // 131: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 131, // 132: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 136, // 133: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 138, // 134: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 140, // 135: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 142, // 136: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 144, // 137: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 146, // 138: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 148, // 139: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 150, // 140: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 153, // 141: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 153, // 142: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 153, // 143: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 1, // 144: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 5, // 145: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse + 8, // 146: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 12, // 147: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + 15, // 148: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse + 17, // 149: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 19, // 150: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 21, // 151: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 33, // 152: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 35, // 153: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 39, // 154: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 39, // 155: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 39, // 156: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 41, // 157: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 43, // 158: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 47, // 159: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 47, // 160: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 47, // 161: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 49, // 162: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 51, // 163: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 57, // 164: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 57, // 165: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 57, // 166: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 53, // 167: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 60, // 168: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 60, // 169: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 62, // 170: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 64, // 171: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 66, // 172: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse + 69, // 173: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + 71, // 174: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 74, // 175: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 76, // 176: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 78, // 177: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 80, // 178: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 83, // 179: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 86, // 180: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 89, // 181: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 92, // 182: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 95, // 183: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 97, // 184: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 99, // 185: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 103, // 186: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 103, // 187: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 104, // 188: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 107, // 189: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 110, // 190: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 115, // 191: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 117, // 192: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 119, // 193: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 121, // 194: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 124, // 195: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 126, // 196: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 128, // 197: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 130, // 198: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 132, // 199: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 137, // 200: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 139, // 201: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 141, // 202: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 143, // 203: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 145, // 204: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 147, // 205: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 149, // 206: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 151, // 207: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 141, // [141:208] is the sub-list for method output_type + 74, // [74:141] is the sub-list for method input_type + 74, // [74:74] is the sub-list for extension type_name + 74, // [74:74] is the sub-list for extension extendee + 0, // [0:74] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -14646,15 +15278,15 @@ func file_proto_wallet_v1_wallet_proto_init() { if File_proto_wallet_v1_wallet_proto != nil { return } - file_proto_wallet_v1_wallet_proto_msgTypes[29].OneofWrappers = []any{} - file_proto_wallet_v1_wallet_proto_msgTypes[30].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[36].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[37].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), NumEnums: 0, - NumMessages: 147, + NumMessages: 154, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index efca79fb..07b9154f 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -104,6 +104,66 @@ message GetBalancesResponse { repeated AssetBalance balances = 1; } +message HostSalaryPolicyLevel { + int32 level_no = 1; + int64 required_diamonds = 2; + int64 host_salary_usd_minor = 3; + int64 host_coin_reward = 4; + int64 agency_salary_usd_minor = 5; + string status = 6; + int32 sort_order = 7; +} + +message HostSalaryPolicy { + uint64 policy_id = 1; + string name = 2; + int64 region_id = 3; + string status = 4; + string settlement_mode = 5; + string settlement_trigger_mode = 6; + string gift_coin_to_diamond_ratio = 7; + string residual_diamond_to_usd_rate = 8; + int64 effective_from_ms = 9; + int64 effective_to_ms = 10; + repeated HostSalaryPolicyLevel levels = 11; +} + +message GetActiveHostSalaryPolicyRequest { + string request_id = 1; + string app_code = 2; + int64 region_id = 3; + string settlement_mode = 4; + string settlement_trigger_mode = 5; + int64 now_ms = 6; +} + +message GetActiveHostSalaryPolicyResponse { + bool found = 1; + HostSalaryPolicy policy = 2; +} + +message HostSalaryProgress { + int64 host_user_id = 1; + string cycle_key = 2; + int64 region_id = 3; + int64 agency_owner_user_id = 4; + int64 total_diamonds = 5; + int64 gift_diamond_total = 6; + int64 updated_at_ms = 7; +} + +message GetHostSalaryProgressRequest { + string request_id = 1; + string app_code = 2; + int64 host_user_id = 3; + string cycle_key = 4; + int64 now_ms = 5; +} + +message GetHostSalaryProgressResponse { + HostSalaryProgress progress = 1; +} + // AdminCreditAssetRequest 是后台手动入账/调账的最小审计命令。 message AdminCreditAssetRequest { string command_id = 1; @@ -1437,6 +1497,8 @@ service WalletService { rpc DebitGift(DebitGiftRequest) returns (DebitGiftResponse); rpc BatchDebitGift(BatchDebitGiftRequest) returns (BatchDebitGiftResponse); rpc GetBalances(GetBalancesRequest) returns (GetBalancesResponse); + rpc GetActiveHostSalaryPolicy(GetActiveHostSalaryPolicyRequest) returns (GetActiveHostSalaryPolicyResponse); + rpc GetHostSalaryProgress(GetHostSalaryProgressRequest) returns (GetHostSalaryProgressResponse); rpc AdminCreditAsset(AdminCreditAssetRequest) returns (AdminCreditAssetResponse); rpc AdminCreditCoinSellerStock(AdminCreditCoinSellerStockRequest) returns (AdminCreditCoinSellerStockResponse); rpc TransferCoinFromSeller(TransferCoinFromSellerRequest) returns (TransferCoinFromSellerResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 8f18f4bc..7cacab6e 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -204,6 +204,8 @@ const ( WalletService_DebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/DebitGift" WalletService_BatchDebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchDebitGift" WalletService_GetBalances_FullMethodName = "/hyapp.wallet.v1.WalletService/GetBalances" + WalletService_GetActiveHostSalaryPolicy_FullMethodName = "/hyapp.wallet.v1.WalletService/GetActiveHostSalaryPolicy" + WalletService_GetHostSalaryProgress_FullMethodName = "/hyapp.wallet.v1.WalletService/GetHostSalaryProgress" WalletService_AdminCreditAsset_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditAsset" WalletService_AdminCreditCoinSellerStock_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditCoinSellerStock" WalletService_TransferCoinFromSeller_FullMethodName = "/hyapp.wallet.v1.WalletService/TransferCoinFromSeller" @@ -274,6 +276,8 @@ type WalletServiceClient interface { DebitGift(ctx context.Context, in *DebitGiftRequest, opts ...grpc.CallOption) (*DebitGiftResponse, error) BatchDebitGift(ctx context.Context, in *BatchDebitGiftRequest, opts ...grpc.CallOption) (*BatchDebitGiftResponse, error) GetBalances(ctx context.Context, in *GetBalancesRequest, opts ...grpc.CallOption) (*GetBalancesResponse, error) + GetActiveHostSalaryPolicy(ctx context.Context, in *GetActiveHostSalaryPolicyRequest, opts ...grpc.CallOption) (*GetActiveHostSalaryPolicyResponse, error) + GetHostSalaryProgress(ctx context.Context, in *GetHostSalaryProgressRequest, opts ...grpc.CallOption) (*GetHostSalaryProgressResponse, error) AdminCreditAsset(ctx context.Context, in *AdminCreditAssetRequest, opts ...grpc.CallOption) (*AdminCreditAssetResponse, error) AdminCreditCoinSellerStock(ctx context.Context, in *AdminCreditCoinSellerStockRequest, opts ...grpc.CallOption) (*AdminCreditCoinSellerStockResponse, error) TransferCoinFromSeller(ctx context.Context, in *TransferCoinFromSellerRequest, opts ...grpc.CallOption) (*TransferCoinFromSellerResponse, error) @@ -373,6 +377,26 @@ func (c *walletServiceClient) GetBalances(ctx context.Context, in *GetBalancesRe return out, nil } +func (c *walletServiceClient) GetActiveHostSalaryPolicy(ctx context.Context, in *GetActiveHostSalaryPolicyRequest, opts ...grpc.CallOption) (*GetActiveHostSalaryPolicyResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetActiveHostSalaryPolicyResponse) + err := c.cc.Invoke(ctx, WalletService_GetActiveHostSalaryPolicy_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) GetHostSalaryProgress(ctx context.Context, in *GetHostSalaryProgressRequest, opts ...grpc.CallOption) (*GetHostSalaryProgressResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetHostSalaryProgressResponse) + err := c.cc.Invoke(ctx, WalletService_GetHostSalaryProgress_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) AdminCreditAsset(ctx context.Context, in *AdminCreditAssetRequest, opts ...grpc.CallOption) (*AdminCreditAssetResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AdminCreditAssetResponse) @@ -972,6 +996,8 @@ type WalletServiceServer interface { DebitGift(context.Context, *DebitGiftRequest) (*DebitGiftResponse, error) BatchDebitGift(context.Context, *BatchDebitGiftRequest) (*BatchDebitGiftResponse, error) GetBalances(context.Context, *GetBalancesRequest) (*GetBalancesResponse, error) + GetActiveHostSalaryPolicy(context.Context, *GetActiveHostSalaryPolicyRequest) (*GetActiveHostSalaryPolicyResponse, error) + GetHostSalaryProgress(context.Context, *GetHostSalaryProgressRequest) (*GetHostSalaryProgressResponse, error) AdminCreditAsset(context.Context, *AdminCreditAssetRequest) (*AdminCreditAssetResponse, error) AdminCreditCoinSellerStock(context.Context, *AdminCreditCoinSellerStockRequest) (*AdminCreditCoinSellerStockResponse, error) TransferCoinFromSeller(context.Context, *TransferCoinFromSellerRequest) (*TransferCoinFromSellerResponse, error) @@ -1050,6 +1076,12 @@ func (UnimplementedWalletServiceServer) BatchDebitGift(context.Context, *BatchDe func (UnimplementedWalletServiceServer) GetBalances(context.Context, *GetBalancesRequest) (*GetBalancesResponse, error) { return nil, status.Error(codes.Unimplemented, "method GetBalances not implemented") } +func (UnimplementedWalletServiceServer) GetActiveHostSalaryPolicy(context.Context, *GetActiveHostSalaryPolicyRequest) (*GetActiveHostSalaryPolicyResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetActiveHostSalaryPolicy not implemented") +} +func (UnimplementedWalletServiceServer) GetHostSalaryProgress(context.Context, *GetHostSalaryProgressRequest) (*GetHostSalaryProgressResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetHostSalaryProgress not implemented") +} func (UnimplementedWalletServiceServer) AdminCreditAsset(context.Context, *AdminCreditAssetRequest) (*AdminCreditAssetResponse, error) { return nil, status.Error(codes.Unimplemented, "method AdminCreditAsset not implemented") } @@ -1302,6 +1334,42 @@ func _WalletService_GetBalances_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _WalletService_GetActiveHostSalaryPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetActiveHostSalaryPolicyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).GetActiveHostSalaryPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_GetActiveHostSalaryPolicy_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).GetActiveHostSalaryPolicy(ctx, req.(*GetActiveHostSalaryPolicyRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_GetHostSalaryProgress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetHostSalaryProgressRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).GetHostSalaryProgress(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_GetHostSalaryProgress_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).GetHostSalaryProgress(ctx, req.(*GetHostSalaryProgressRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_AdminCreditAsset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(AdminCreditAssetRequest) if err := dec(in); err != nil { @@ -2383,6 +2451,14 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetBalances", Handler: _WalletService_GetBalances_Handler, }, + { + MethodName: "GetActiveHostSalaryPolicy", + Handler: _WalletService_GetActiveHostSalaryPolicy_Handler, + }, + { + MethodName: "GetHostSalaryProgress", + Handler: _WalletService_GetHostSalaryProgress_Handler, + }, { MethodName: "AdminCreditAsset", Handler: _WalletService_AdminCreditAsset_Handler, diff --git a/docs/Flutter麦上心跳接口.md b/docs/Flutter麦上心跳接口.md new file mode 100644 index 00000000..cd3d34db --- /dev/null +++ b/docs/Flutter麦上心跳接口.md @@ -0,0 +1,88 @@ +# Flutter 麦上心跳接口 + +## 地址 + +```http +POST /api/v1/rooms/mic/heartbeat +Authorization: Bearer +Content-Type: application/json +``` + +## 参数 + +| 字段 | 类型 | 必填 | 说明 | +| --- | --- | --- | --- | +| `room_id` | string | 是 | 房间 ID。 | +| `command_id` | string | 是 | 本次心跳命令 ID。同一次请求重试复用同一个值,下一次心跳换新的值。 | +| `target_user_id` | int64 | 否 | 传 `0` 或不传表示当前登录用户自己。 | +| `mic_session_id` | string | 是 | 当前麦位会话 ID,必须使用上麦返回的 `mic_session_id`。 | + +请求示例: + +```json +{ + "room_id": "lalu_xxx", + "command_id": "cmd_mic_heartbeat_lalu_xxx_123_001", + "target_user_id": 0, + "mic_session_id": "mic_xxx" +} +``` + +## 返回值 + +```json +{ + "code": "OK", + "message": "OK", + "request_id": "req_xxx", + "data": { + "result": { + "applied": true, + "room_version": 18, + "server_time_ms": 1778000005000 + }, + "seat_no": 1, + "mic_heartbeat_at_ms": 1778000005000, + "room": { + "room_id": "lalu_xxx", + "version": 18, + "mic_seats": [ + { + "seat_no": 1, + "user_id": 123, + "publish_state": "publishing", + "mic_session_id": "mic_xxx", + "mic_heartbeat_at_ms": 1778000005000, + "seat_status": "publishing" + } + ] + } + } +} +``` + +| 字段 | 说明 | +| --- | --- | +| `data.seat_no` | 当前用户所在麦位。 | +| `data.mic_heartbeat_at_ms` | 服务端接受本次麦上心跳的时间,UTC epoch milliseconds。 | +| `data.room` | 刷新后的房间快照。 | +| `data.room.mic_seats[].mic_heartbeat_at_ms` | 麦位最近一次服务端接受心跳的时间。 | +| `data.room.mic_seats[].publish_state` | `publishing` 表示当前会话已确认发流,可以继续心跳。 | +| `data.room.mic_seats[].seat_status` | 展示状态,常见值为 `publishing`、`muted`、`occupied`、`empty`、`locked`。 | + +## 相关 IM + +| IM | 是否新增 | 说明 | +| --- | --- | --- | +| 无 | 否 | 麦上心跳不广播独立 IM。 | +| `room_mic_publish_confirmed` | 已有 | 发流确认成功后进入 `publishing`,Flutter 收到后可以开始麦上心跳。 | +| `room_mic_down` | 已有 | 用户下麦、离房、被踢、发流超时或 RTC 停止后释放麦位,Flutter 收到后停止麦上心跳。 | + +## Flutter 调用规则 + +1. `POST /api/v1/rooms/mic/up` 成功后保存 `mic_session_id`。 +2. RTC 发流成功后调用 `POST /api/v1/rooms/mic/publishing/confirm`。 +3. 确认成功且当前麦位 `publish_state=publishing` 后,周期调用 `POST /api/v1/rooms/mic/heartbeat`。 +4. `pending_publish` 状态不能调用麦上心跳开始计时。 +5. 返回 `mic session mismatch` 时,本地保存的是旧 `mic_session_id`,需要刷新房间详情。 +6. 收到 `room_mic_down` 或接口返回用户不在麦上时,停止本地麦上心跳。 diff --git a/docs/flutter对接/房间锁房接口Flutter对接.md b/docs/flutter对接/房间锁房接口Flutter对接.md index 9b6f7d6a..df9b1064 100644 --- a/docs/flutter对接/房间锁房接口Flutter对接.md +++ b/docs/flutter对接/房间锁房接口Flutter对接.md @@ -1,60 +1,45 @@ -# 房间锁房接口 Flutter 对接 +# 房间锁房 Flutter 对接 -本文描述 Flutter App 对接房间锁房能力的 HTTP 接口。房间密码由 `room-service` 只保存 bcrypt 哈希;客户端只提交明文用于本次设置或进房校验,任何列表、搜索、详情、房间消息和响应体都不会返回明文或哈希。 +## 地址 -## 接口地址 - -`POST /api/v1/rooms/password` - -`POST /api/v1/rooms/join` - -`GET /api/v1/rooms` - -`GET /api/v1/rooms/feeds` - -本地开发地址: +本地: ```text http://127.0.0.1:13000 ``` -## 请求方法 +接口: -| 方法 | 接口 | 说明 | +| 方法 | 地址 | 说明 | | --- | --- | --- | -| `POST` | `/api/v1/rooms/password` | 房主设置或清空房间入房密码。 | -| `POST` | `/api/v1/rooms/join` | 进入房间;带锁房间需要传 `password`。 | -| `GET` | `/api/v1/rooms` | 公共房间列表和搜索;房间卡片返回 `locked`。 | -| `GET` | `/api/v1/rooms/feeds` | Mine 页房间流;房间卡片返回 `locked`。 | +| `POST` | `/api/v1/rooms/password` | 房主设置或清空房间密码 | +| `POST` | `/api/v1/rooms/join` | 进入房间;锁房时必须传密码 | +| `GET` | `/api/v1/rooms` | 房间列表和搜索,返回 `locked` | +| `GET` | `/api/v1/rooms/feeds` | Mine 页房间流,返回 `locked` | -## 请求头 +请求头: -| Header | 必填 | 模拟值 | 说明 | +| Header | 必填 | 说明 | +| --- | --- | --- | +| `Authorization` | 是 | `Bearer ` | +| `X-App-Code` | 否 | App 编码,例如 `lalu` | + +## 设置房间密码 + +`POST /api/v1/rooms/password` + +参数: + +| 字段 | 必填 | 类型 | 说明 | | --- | --- | --- | --- | -| `Authorization` | 是 | `Bearer ` | 登录 access token;服务端从 token 读取当前用户 ID。 | -| `X-App-Code` | 否 | `lalu` | App 编码;登录态接口最终以 token 内的 `app_code` 为准。 | +| `room_id` | 是 | string | 房间 ID | +| `command_id` | 是 | string | 本次设置动作的幂等键,同一次重试复用 | +| `locked` | 是 | bool | `true` 设置密码,`false` 清空密码 | +| `password` | `locked=true` 必填 | string | 房间密码,服务端 trim 后最长 64 字符;`locked=false` 时忽略 | -## 设置或清空房间密码 - -只有房主可以调用。房管、主持人和普通观众调用会返回 `PERMISSION_DENIED`。 - -请求体: - -| 字段 | 必填 | 类型 | 模拟值 | 说明 | -| --- | --- | --- | --- | --- | -| `room_id` | 是 | string | `room_10001` | 房间 ID。 | -| `command_id` | 是 | string | `cmd_room_password_room_10001_1710000000` | 房间命令幂等键;同一次点击重试必须复用。 | -| `locked` | 是 | bool | `true` | `true` 表示设置密码,`false` 表示清空密码。 | -| `password` | `locked=true` 时必填 | string | `1234` | 入房密码;服务端 trim 后最长 64 个字符。`locked=false` 时忽略。 | - -设置密码请求示例: - -```http -POST /api/v1/rooms/password -Authorization: Bearer -X-App-Code: lalu -Content-Type: application/json +请求: +```json { "room_id": "room_10001", "command_id": "cmd_room_password_room_10001_1710000000", @@ -63,22 +48,7 @@ Content-Type: application/json } ``` -清空密码请求示例: - -```http -POST /api/v1/rooms/password -Authorization: Bearer -X-App-Code: lalu -Content-Type: application/json - -{ - "room_id": "room_10001", - "command_id": "cmd_room_password_room_10001_1710000100", - "locked": false -} -``` - -成功响应: +返回: ```json { @@ -114,42 +84,56 @@ Content-Type: application/json } ``` -字段说明: +返回字段: -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `data.result.applied` | bool | 本次命令是否产生状态变更;重复提交相同命令可能为 `false`。 | -| `data.result.room_version` | int64 | 命令完成后房间版本。 | -| `data.room.locked` | bool | 最新锁房状态;`true` 表示后续新用户进房需要密码。 | -| `data.room.version` | int64 | 最新房间快照版本;客户端本地房间状态以更大版本覆盖旧状态。 | -| `data.seats` | array | 当前座位列表;锁房接口成功后可直接复用该房间快照刷新页面。 | - -## 带密码进入房间 - -客户端进入房间前先看房间卡片或详情里的 `locked`: - -| `locked` | 客户端行为 | +| 字段 | 说明 | | --- | --- | -| `false` | 直接调用 JoinRoom,`password` 可不传或传空字符串。 | -| `true` | 先弹出密码输入,再调用 JoinRoom 并传 `password`。 | +| `data.result.applied` | 本次命令是否改变房间状态 | +| `data.result.room_version` | 房间最新版本 | +| `data.room.locked` | 最新锁房状态 | +| `data.room.version` | 房间快照版本 | +| `data.seats` | 当前麦位列表 | -请求体: +## 清空房间密码 -| 字段 | 必填 | 类型 | 模拟值 | 说明 | -| --- | --- | --- | --- | --- | -| `room_id` | 是 | string | `room_10001` | 房间 ID。 | -| `command_id` | 是 | string | `cmd_join_room_10001_20001_1710000000` | 进房命令幂等键;同一次进房重试必须复用。 | -| `role` | 否 | string | `audience` | 当前固定传 `audience`。 | -| `password` | 锁房时必填 | string | `1234` | 只用于本次进房校验,服务端不保存明文。 | +`POST /api/v1/rooms/password` -请求示例: +参数: -```http -POST /api/v1/rooms/join -Authorization: Bearer -X-App-Code: lalu -Content-Type: application/json +| 字段 | 必填 | 类型 | 说明 | +| --- | --- | --- | --- | +| `room_id` | 是 | string | 房间 ID | +| `command_id` | 是 | string | 本次清空动作的幂等键 | +| `locked` | 是 | bool | 固定传 `false` | +请求: + +```json +{ + "room_id": "room_10001", + "command_id": "cmd_room_unlock_room_10001_1710000100", + "locked": false +} +``` + +返回同设置密码接口,`data.room.locked=false`。 + +## 进入锁房房间 + +`POST /api/v1/rooms/join` + +参数: + +| 字段 | 必填 | 类型 | 说明 | +| --- | --- | --- | --- | +| `room_id` | 是 | string | 房间 ID | +| `command_id` | 是 | string | 本次进房动作的幂等键,同一次重试复用 | +| `role` | 否 | string | 当前传 `audience` | +| `password` | 锁房时必填 | string | 本次入房密码 | + +请求: + +```json { "room_id": "room_10001", "command_id": "cmd_join_room_10001_20001_1710000000", @@ -158,7 +142,7 @@ Content-Type: application/json } ``` -成功响应只展示锁房相关字段: +返回: ```json { @@ -196,35 +180,33 @@ Content-Type: application/json } ``` +返回字段: + +| 字段 | 说明 | +| --- | --- | +| `data.room.locked` | 当前房间是否锁房 | +| `data.viewer.user_id` | 当前用户 ID | +| `data.im.group_id` | JoinRoom 成功后需要加入的腾讯 IM 房间群 | +| `data.im.need_join_group` | `true` 时 Flutter 调腾讯 IM `joinGroup` | +| `data.rtc.available` | 是否拿到 RTC token | + 进房规则: | 场景 | 结果 | | --- | --- | -| 房间未锁 | 不校验 `password`。 | -| 房间已锁且密码正确 | JoinRoom 成功,客户端再调用腾讯 IM `joinGroup` 和 RTC `enterRoom`。 | -| 房间已锁且密码错误或缺失 | 返回 `403 PERMISSION_DENIED`,不会创建 presence,不会返回 RTC token。 | -| 房主进入自己的房间 | 不需要密码。 | -| 用户已经在房间内 | 再次 JoinRoom 按幂等恢复当前房间态,不会因为后续锁房被踢出。 | +| 未锁房 | `password` 可不传 | +| 已锁房且密码正确 | JoinRoom 成功,再加入 IM 房间群 | +| 已锁房且密码错误或缺失 | 返回 `403 PERMISSION_DENIED`,不要加入 IM 房间群 | +| 房主进自己房间 | 不需要密码 | +| 已在房间内重复 JoinRoom | 非房主仍要按当前最新密码校验;密码错误返回 `403 PERMISSION_DENIED` | -## 房间列表和搜索 locked 字段 +## 房间列表 locked 字段 -公共列表和搜索使用同一个接口: +`GET /api/v1/rooms?tab=hot&query=100001` -```http -GET /api/v1/rooms?tab=hot&query=100001 -Authorization: Bearer -X-App-Code: lalu -``` +`GET /api/v1/rooms/feeds?tab=followed` -Mine 页房间流: - -```http -GET /api/v1/rooms/feeds?tab=followed -Authorization: Bearer -X-App-Code: lalu -``` - -列表响应示例: +返回: ```json { @@ -236,18 +218,10 @@ X-App-Code: lalu { "room_id": "room_10001", "im_group_id": "room_10001", - "owner_user_id": "10001", "title": "Live Room", - "cover_url": "https://cdn.example/room.png", - "mode": "voice", - "status": "active", "locked": true, - "heat": 1000, "online_count": 12, - "seat_count": 15, - "occupied_seat_count": 2, "visible_region_id": 1, - "app_code": "lalu", "room_short_id": "100001" } ], @@ -256,17 +230,87 @@ X-App-Code: lalu } ``` -字段说明: +字段: -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `rooms[].locked` | bool | 房间是否需要入房密码;搜索结果和普通列表一致。 | -| `rooms[].im_group_id` | string | 腾讯 IM 群 ID;只用于 JoinRoom 成功后的 `joinGroup`,不能绕过 JoinRoom。 | -| `next_cursor` | string | 下一页游标;为空表示没有下一页。 | +| 字段 | 说明 | +| --- | --- | +| `rooms[].locked` | 是否锁房;`true` 时进房前弹密码输入 | +| `rooms[].im_group_id` | 房间 IM 群 ID,只能在 JoinRoom 成功后使用 | +| `rooms[].visible_region_id` | 房间区域 | -## 错误处理 +## 相关 IM -失败返回仍使用统一 envelope: +### JoinRoom 成功后加入房间群 + +接口 `POST /api/v1/rooms/join` 成功后,Flutter 使用: + +```text +data.im.group_id +``` + +调用腾讯 IM SDK 加入房间群。 + +规则: + +| 场景 | Flutter 行为 | +| --- | --- | +| JoinRoom 成功 | 调腾讯 IM `joinGroup(data.im.group_id)` | +| JoinRoom 返回 `PERMISSION_DENIED` | 不调用 `joinGroup` | +| JoinRoom 返回 `ROOM_CLOSED` 或 `NOT_FOUND` | 不调用 `joinGroup`,刷新列表 | + +### 房间密码变更区域通知 + +房主设置或清空密码后,服务端会发区域播报 IM,不再发房间群 IM。 + +Flutter 需要监听用户所在区域播报群的自定义消息: + +```json +{ + "event_id": "room_password_changed:evt_room_xxx", + "broadcast_type": "room_password_changed", + "scope": "region", + "app_code": "lalu", + "region_id": 1, + "room_id": "room_10001", + "actor_user_id": 10001, + "locked": true, + "sent_at_ms": 1710000000456, + "room_version": 12, + "source_event_id": "evt_room_xxx", + "action": { + "type": "refresh_room", + "room_id": "room_10001" + } +} +``` + +字段: + +| 字段 | 说明 | +| --- | --- | +| `broadcast_type` | 固定 `room_password_changed` | +| `scope` | 固定 `region` | +| `region_id` | 区域 ID | +| `room_id` | 发生变化的房间 | +| `locked` | 最新锁房状态 | +| `room_version` | 房间版本;本地只用更大的版本覆盖旧状态 | +| `action.type` | 固定 `refresh_room` | + +处理: + +| 当前页面 | 行为 | +| --- | --- | +| 房间列表页 | 更新对应房间卡片 `locked` | +| 房间详情页 | 如果 `room_id` 相同,刷新房间快照或更新本地 `locked` | +| 密码弹窗打开中 | 收到同房间更新后,按最新 `locked` 状态决定是否关闭弹窗 | + +### 房间群系统消息 + +`room_password_changed` 不走房间群 IM。房间内用户刷新锁房状态依赖区域播报或接口返回的 `room.locked`。 + +## 错误返回 + +失败统一返回: ```json { @@ -276,108 +320,13 @@ X-App-Code: lalu } ``` -| HTTP 状态码 | `code` | 典型场景 | 处理方式 | -| --- | --- | --- | --- | -| `400` | `INVALID_ARGUMENT` | `room_id`、`command_id` 缺失;设置锁房时 `password` 为空或超过 64 字符。 | 客户端修正参数,不自动重试。 | -| `401` | `UNAUTHORIZED` | token 缺失、无效、过期或会话失效。 | 重新登录。 | -| `403` | `PROFILE_REQUIRED` | 用户资料未完成。 | 跳转资料补全流程。 | -| `403` | `PERMISSION_DENIED` | 非房主设置密码;进锁房密码错误;用户被 ban。 | 设置密码时隐藏入口或提示无权限;进房时提示密码错误。 | -| `404` | `NOT_FOUND` | 房间不存在。 | 刷新列表或退出房间页。 | -| `409` | `ROOM_CLOSED` | 房间已关闭。 | 刷新列表或退出房间页。 | -| `409` | `CONFLICT` | 同一个 `command_id` 被不同请求体复用。 | 为新的用户动作生成新的 `command_id`。 | -| `502` | `UPSTREAM_ERROR` | 内部服务暂不可用。 | 可提示稍后重试。 | +常见错误: -幂等规则: - -| 场景 | 返回 | -| --- | --- | -| 同一个 `command_id` 重试同一次设置密码 | 返回同一命令结果,不重复变更房间。 | -| 同一个 `command_id` 换另一个密码 | `409 CONFLICT`。 | -| 重复清空已解锁房间 | `200 OK`,`data.room.locked=false`。 | -| 同一个用户重复 JoinRoom | 返回当前房间首屏数据,不重复创建 presence。 | - -## Flutter 解析示例 - -```dart -class RoomCommandResult { - RoomCommandResult({ - required this.applied, - required this.roomVersion, - required this.serverTimeMs, - }); - - final bool applied; - final int roomVersion; - final int serverTimeMs; - - factory RoomCommandResult.fromJson(Map json) { - return RoomCommandResult( - applied: json['applied'] as bool? ?? false, - roomVersion: (json['room_version'] as num?)?.toInt() ?? 0, - serverTimeMs: (json['server_time_ms'] as num?)?.toInt() ?? 0, - ); - } -} - -class RoomCard { - RoomCard({ - required this.roomId, - required this.imGroupId, - required this.title, - required this.locked, - required this.onlineCount, - }); - - final String roomId; - final String imGroupId; - final String title; - final bool locked; - final int onlineCount; - - factory RoomCard.fromJson(Map json) { - return RoomCard( - roomId: json['room_id'] as String? ?? '', - imGroupId: json['im_group_id'] as String? ?? '', - title: json['title'] as String? ?? '', - locked: json['locked'] as bool? ?? false, - onlineCount: (json['online_count'] as num?)?.toInt() ?? 0, - ); - } -} - -class RoomLockResult { - RoomLockResult({ - required this.result, - required this.room, - required this.serverTimeMs, - }); - - final RoomCommandResult result; - final RoomCard room; - final int serverTimeMs; - - factory RoomLockResult.fromJson(Map json) { - return RoomLockResult( - result: RoomCommandResult.fromJson( - json['result'] as Map? ?? const {}, - ), - room: RoomCard.fromJson( - json['room'] as Map? ?? const {}, - ), - serverTimeMs: (json['server_time_ms'] as num?)?.toInt() ?? 0, - ); - } -} -``` - -调用时先解析外层 envelope:只有 `code == "OK"` 时读取 `data`;其他 `code` 按登录态、参数错误、权限错误或服务错误处理,并把 `request_id` 写入客户端日志。 - -客户端生成 `command_id` 时按一次用户动作生成一次,例如: - -```dart -String newRoomCommandId(String action, String roomId, String userId) { - return 'cmd_${action}_${roomId}_${userId}_${DateTime.now().millisecondsSinceEpoch}'; -} -``` - -同一次 HTTP 重试复用原 `command_id`;用户重新输入密码或再次点击设置按钮时生成新的 `command_id`。 +| HTTP | code | 说明 | +| --- | --- | --- | +| `400` | `INVALID_ARGUMENT` | 参数缺失、设置密码时密码为空或超过 64 字符 | +| `401` | `UNAUTHORIZED` | token 无效或过期 | +| `403` | `PERMISSION_DENIED` | 非房主设置密码、进房密码错误、用户被 ban | +| `404` | `NOT_FOUND` | 房间不存在 | +| `409` | `ROOM_CLOSED` | 房间已关闭 | +| `409` | `CONFLICT` | 同一个 `command_id` 被不同请求体复用 | diff --git a/docs/语音房客户端接口流程.md b/docs/语音房客户端接口流程.md index f8c35f11..4a2562b1 100644 --- a/docs/语音房客户端接口流程.md +++ b/docs/语音房客户端接口流程.md @@ -687,6 +687,46 @@ Rules: - `room_version` 和 `event_time_ms` 用于丢弃旧事件,避免旧 audience/leave 事件清理新会话。 - 成功后麦位 `publish_state=publishing`。 +### Mic Heartbeat + +地址: + +```http +POST /api/v1/rooms/mic/heartbeat +Authorization: Bearer +Content-Type: application/json +``` + +参数: + +```json +{ + "room_id": "lalu_xxx", + "command_id": "cmd_mic_heartbeat___", + "target_user_id": 0, + "mic_session_id": "mic_xxx" +} +``` + +返回值: + +```json +{ + "result": {}, + "seat_no": 1, + "mic_heartbeat_at_ms": 1778000005000, + "room": {} +} +``` + +相关 IM: + +- 无独立 IM。该接口只刷新当前 `publishing` 麦位会话的服务端心跳时间和房间 presence。 +- `target_user_id=0` 表示当前登录用户自己。 +- `mic_session_id` 必须等于当前麦位会话。 +- `pending_publish` 不能调用该接口开始计时,必须先调用 `POST /api/v1/rooms/mic/publishing/confirm`。 +- 重试同一次心跳复用同一个 `command_id`;下一次心跳必须换新的 `command_id`。 + ### Mic Down ```http diff --git a/services/activity-service/internal/domain/broadcast/broadcast.go b/services/activity-service/internal/domain/broadcast/broadcast.go index 79f98b81..503275fe 100644 --- a/services/activity-service/internal/domain/broadcast/broadcast.go +++ b/services/activity-service/internal/domain/broadcast/broadcast.go @@ -16,6 +16,8 @@ const ( TypeRedPacket = "red_packet" // TypeRoomTreasure 是语音房宝箱满能量后的开箱倒计时播报。 TypeRoomTreasure = "room_treasure" + // TypeRoomPasswordChanged 是锁房状态变化的区域通知,客户端用它刷新房间锁状态入口。 + TypeRoomPasswordChanged = "room_password_changed" // TypeLuckyGiftBigWin 是幸运礼物中奖区域飘屏;当前默认 1 倍及以上即进入播报 outbox。 TypeLuckyGiftBigWin = "lucky_gift_big_win" diff --git a/services/activity-service/internal/service/broadcast/service.go b/services/activity-service/internal/service/broadcast/service.go index ec0adaa0..087726c6 100644 --- a/services/activity-service/internal/service/broadcast/service.go +++ b/services/activity-service/internal/service/broadcast/service.go @@ -298,7 +298,7 @@ func (s *Service) ProcessPendingBroadcasts(ctx context.Context, options WorkerOp } // HandleRoomEvent 把已提交的 room outbox 事实转换为服务端播报。 -// 只有 RoomGiftSent 且满足区域和礼物价值阈值时才生成区域播报,避免把展示策略侵入 Room Cell 主链路。 +// 礼物、宝箱和锁房只使用 room outbox 中的稳定事实,避免把展示策略侵入 Room Cell 主链路。 func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { if envelope == nil { return broadcastdomain.ConsumeRoomEventResult{}, xerr.New(xerr.InvalidArgument, "room event envelope is required") @@ -308,8 +308,11 @@ func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.Ev if envelope.GetEventType() == "RoomTreasureCountdownStarted" { return s.handleRoomTreasureCountdown(eventCtx, envelope) } + if envelope.GetEventType() == "RoomPasswordChanged" { + return s.handleRoomPasswordChanged(eventCtx, envelope) + } if envelope.GetEventType() != "RoomGiftSent" { - // 当前只消费礼物和房间宝箱事实;未来红包或运营事件应显式增加事件类型分支和测试。 + // 当前只消费礼物、房间宝箱和锁房事实;未来运营事件应显式增加事件类型分支和测试。 return result, nil } var gift roomeventsv1.RoomGiftSent @@ -343,6 +346,38 @@ func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.Ev }, nil } +func (s *Service) handleRoomPasswordChanged(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { + result := broadcastdomain.ConsumeRoomEventResult{EventID: envelope.GetEventId(), Status: broadcastdomain.StatusSkipped} + var event roomeventsv1.RoomPasswordChanged + if err := proto.Unmarshal(envelope.GetBody(), &event); err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + if event.GetVisibleRegionId() <= 0 { + // 区域通知必须有明确区域,不能把无区域房间退化成全局播报扩大影响面。 + return result, nil + } + broadcastEventID := roomPasswordChangedBroadcastEventID(envelope) + payloadJSON, err := roomPasswordChangedPayload(envelope, &event, broadcastEventID, s.now().UTC().UnixMilli()) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + published, err := s.PublishRegionBroadcast(ctx, PublishInput{ + EventID: broadcastEventID, + BroadcastType: broadcastdomain.TypeRoomPasswordChanged, + RegionID: event.GetVisibleRegionId(), + PayloadJSON: payloadJSON, + }) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + return broadcastdomain.ConsumeRoomEventResult{ + EventID: envelope.GetEventId(), + Status: published.Status, + BroadcastEventID: published.EventID, + BroadcastCreated: published.Created, + }, nil +} + func (s *Service) handleRoomTreasureCountdown(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { result := broadcastdomain.ConsumeRoomEventResult{EventID: envelope.GetEventId(), Status: broadcastdomain.StatusSkipped} var treasure roomeventsv1.RoomTreasureCountdownStarted @@ -519,6 +554,32 @@ func roomTreasureBroadcastEventID(envelope *roomeventsv1.EventEnvelope, treasure return "room_treasure_broadcast:" + envelope.GetEventId() } +func roomPasswordChangedBroadcastEventID(envelope *roomeventsv1.EventEnvelope) string { + return "room_password_changed:" + envelope.GetEventId() +} + +func roomPasswordChangedPayload(envelope *roomeventsv1.EventEnvelope, event *roomeventsv1.RoomPasswordChanged, eventID string, sentAtMS int64) (string, error) { + payload := map[string]any{ + "event_id": eventID, + "broadcast_type": broadcastdomain.TypeRoomPasswordChanged, + "scope": broadcastdomain.ScopeRegion, + "app_code": envelope.GetAppCode(), + "region_id": event.GetVisibleRegionId(), + "room_id": envelope.GetRoomId(), + "actor_user_id": event.GetActorUserId(), + "locked": event.GetLocked(), + "sent_at_ms": sentAtMS, + "room_version": envelope.GetRoomVersion(), + "source_event_id": envelope.GetEventId(), + "action": map[string]any{ + "type": "refresh_room", + "room_id": envelope.GetRoomId(), + }, + } + encoded, err := json.Marshal(payload) + return string(encoded), err +} + func roomTreasurePayload(envelope *roomeventsv1.EventEnvelope, treasure *roomeventsv1.RoomTreasureCountdownStarted, eventID string, sentAtMS int64) (string, error) { payload := map[string]any{ "event_id": eventID, diff --git a/services/activity-service/internal/service/broadcast/service_test.go b/services/activity-service/internal/service/broadcast/service_test.go index 59ec150d..251dbe29 100644 --- a/services/activity-service/internal/service/broadcast/service_test.go +++ b/services/activity-service/internal/service/broadcast/service_test.go @@ -56,6 +56,40 @@ func TestHandleRoomGiftSentCreatesRegionBroadcast(t *testing.T) { } } +func TestHandleRoomPasswordChangedCreatesRegionBroadcast(t *testing.T) { + repository := newFakeRepository() + service := New(Config{NodeID: "node-a"}, repository, nil, nil) + service.SetClock(func() time.Time { return time.UnixMilli(1_700_000_001_000) }) + envelope := mustPasswordChangedEnvelope(t, &roomeventsv1.RoomPasswordChanged{ + ActorUserId: 42, + Locked: true, + VisibleRegionId: 1001, + }) + + result, err := service.HandleRoomEvent(appcode.WithContext(context.Background(), "lalu"), envelope) + if err != nil { + t.Fatalf("HandleRoomEvent password changed failed: %v", err) + } + if result.Status != broadcastdomain.StatusPending || !result.BroadcastCreated || result.BroadcastEventID != "room_password_changed:"+envelope.GetEventId() { + t.Fatalf("unexpected password broadcast result: %+v", result) + } + record := repository.records[result.BroadcastEventID] + if record.GroupID != "hy_lalu_bc_r_1001" || record.Scope != broadcastdomain.ScopeRegion || record.BroadcastType != broadcastdomain.TypeRoomPasswordChanged { + t.Fatalf("unexpected password broadcast record: %+v", record) + } + var payload map[string]any + if err := json.Unmarshal([]byte(record.PayloadJSON), &payload); err != nil { + t.Fatalf("password payload is not json: %v", err) + } + if payload["room_id"] != "room-1001" || payload["scope"] != "region" || payload["locked"] != true || payload["actor_user_id"] != float64(42) { + t.Fatalf("password payload mismatch: %+v", payload) + } + action, ok := payload["action"].(map[string]any) + if !ok || action["type"] != "refresh_room" || action["room_id"] != "room-1001" { + t.Fatalf("password payload action mismatch: %+v", payload["action"]) + } +} + func TestHandleRoomGiftSentSkipsNonBroadcastCases(t *testing.T) { service := New(Config{SuperGiftMinValue: 1000}, newFakeRepository(), nil, nil) belowThreshold := mustGiftEnvelope(t, &roomeventsv1.RoomGiftSent{GiftValue: 999, VisibleRegionId: 1001}) @@ -301,6 +335,23 @@ func mustGiftEnvelope(t *testing.T, gift *roomeventsv1.RoomGiftSent) *roomevents } } +func mustPasswordChangedEnvelope(t *testing.T, event *roomeventsv1.RoomPasswordChanged) *roomeventsv1.EventEnvelope { + t.Helper() + body, err := proto.Marshal(event) + if err != nil { + t.Fatalf("marshal password changed failed: %v", err) + } + return &roomeventsv1.EventEnvelope{ + EventId: "evt-room-password-1", + RoomId: "room-1001", + EventType: "RoomPasswordChanged", + RoomVersion: 8, + OccurredAtMs: 1_700_000_001_000, + AppCode: "lalu", + Body: body, + } +} + func redPacketPayloadData(t *testing.T, payloadJSON string) map[string]any { t.Helper() diff --git a/services/gateway-service/internal/client/room_client.go b/services/gateway-service/internal/client/room_client.go index f66b53e2..7f514d34 100644 --- a/services/gateway-service/internal/client/room_client.go +++ b/services/gateway-service/internal/client/room_client.go @@ -20,6 +20,7 @@ type RoomClient interface { MicDown(ctx context.Context, req *roomv1.MicDownRequest) (*roomv1.MicDownResponse, error) ChangeMicSeat(ctx context.Context, req *roomv1.ChangeMicSeatRequest) (*roomv1.ChangeMicSeatResponse, error) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmMicPublishingRequest) (*roomv1.ConfirmMicPublishingResponse, error) + MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) ApplyRTCEvent(ctx context.Context, req *roomv1.ApplyRTCEventRequest) (*roomv1.ApplyRTCEventResponse, error) SetMicSeatLock(ctx context.Context, req *roomv1.SetMicSeatLockRequest) (*roomv1.SetMicSeatLockResponse, error) @@ -132,6 +133,10 @@ func (c *grpcRoomClient) ConfirmMicPublishing(ctx context.Context, req *roomv1.C return c.client.ConfirmMicPublishing(ctx, req) } +func (c *grpcRoomClient) MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) { + return c.client.MicHeartbeat(ctx, req) +} + func (c *grpcRoomClient) SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) { return c.client.SetMicMute(ctx, req) } diff --git a/services/gateway-service/internal/client/wallet_client.go b/services/gateway-service/internal/client/wallet_client.go index 930d7354..e864bc8a 100644 --- a/services/gateway-service/internal/client/wallet_client.go +++ b/services/gateway-service/internal/client/wallet_client.go @@ -11,6 +11,8 @@ import ( // WalletClient 抽象 gateway 对 wallet-service 余额查询能力的依赖。 type WalletClient interface { GetBalances(ctx context.Context, req *walletv1.GetBalancesRequest) (*walletv1.GetBalancesResponse, error) + GetActiveHostSalaryPolicy(ctx context.Context, req *walletv1.GetActiveHostSalaryPolicyRequest) (*walletv1.GetActiveHostSalaryPolicyResponse, error) + GetHostSalaryProgress(ctx context.Context, req *walletv1.GetHostSalaryProgressRequest) (*walletv1.GetHostSalaryProgressResponse, error) GetWalletOverview(ctx context.Context, req *walletv1.GetWalletOverviewRequest) (*walletv1.GetWalletOverviewResponse, error) GetWalletValueSummary(ctx context.Context, req *walletv1.GetWalletValueSummaryRequest) (*walletv1.GetWalletValueSummaryResponse, error) GetUserGiftWall(ctx context.Context, req *walletv1.GetUserGiftWallRequest) (*walletv1.GetUserGiftWallResponse, error) @@ -54,6 +56,14 @@ func (c *grpcWalletClient) GetBalances(ctx context.Context, req *walletv1.GetBal return c.client.GetBalances(ctx, req) } +func (c *grpcWalletClient) GetActiveHostSalaryPolicy(ctx context.Context, req *walletv1.GetActiveHostSalaryPolicyRequest) (*walletv1.GetActiveHostSalaryPolicyResponse, error) { + return c.client.GetActiveHostSalaryPolicy(ctx, req) +} + +func (c *grpcWalletClient) GetHostSalaryProgress(ctx context.Context, req *walletv1.GetHostSalaryProgressRequest) (*walletv1.GetHostSalaryProgressResponse, error) { + return c.client.GetHostSalaryProgress(ctx, req) +} + func (c *grpcWalletClient) GetWalletOverview(ctx context.Context, req *walletv1.GetWalletOverviewRequest) (*walletv1.GetWalletOverviewResponse, error) { return c.client.GetWalletOverview(ctx, req) } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 1eb01760..7fda6ab5 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -72,6 +72,8 @@ type UserHandlers struct { GetMyRoleSummary http.HandlerFunc SearchHostAgencies http.HandlerFunc ApplyToHostAgency http.HandlerFunc + GetHostCenterAgency http.HandlerFunc + GetHostCenterPlatformPolicy http.HandlerFunc GetAgencyCenterOverview http.HandlerFunc ListAgencyCenterHosts http.HandlerFunc ListAgencyCenterApplications http.HandlerFunc @@ -127,6 +129,7 @@ type RoomHandlers struct { MicDown http.HandlerFunc ChangeMicSeat http.HandlerFunc ConfirmMicPublishing http.HandlerFunc + MicHeartbeat http.HandlerFunc SetMicMute http.HandlerFunc SetMicSeatLock http.HandlerFunc SetChatEnabled http.HandlerFunc @@ -300,6 +303,8 @@ func (r routes) registerUserRoutes() { r.profile("/users/me/role-summary", "", h.GetMyRoleSummary) r.profile("/host/agencies/search", http.MethodGet, h.SearchHostAgencies) r.profile("/host/agency-applications", http.MethodPost, h.ApplyToHostAgency) + r.profile("/host-center/agency", http.MethodGet, h.GetHostCenterAgency) + r.profile("/host-center/platform-policy", http.MethodGet, h.GetHostCenterPlatformPolicy) r.profile("/agency-center/overview", http.MethodGet, h.GetAgencyCenterOverview) r.profile("/agency-center/hosts", http.MethodGet, h.ListAgencyCenterHosts) r.profile("/agency-center/applications", http.MethodGet, h.ListAgencyCenterApplications) @@ -357,6 +362,7 @@ func (r routes) registerRoomRoutes() { r.profile("/rooms/mic/down", http.MethodPost, h.MicDown) r.profile("/rooms/mic/change", http.MethodPost, h.ChangeMicSeat) r.profile("/rooms/mic/publishing/confirm", http.MethodPost, h.ConfirmMicPublishing) + r.profile("/rooms/mic/heartbeat", http.MethodPost, h.MicHeartbeat) r.profile("/rooms/mic/mute", http.MethodPost, h.SetMicMute) r.profile("/rooms/mic/lock", http.MethodPost, h.SetMicSeatLock) r.profile("/rooms/chat/enabled", http.MethodPost, h.SetChatEnabled) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 0700e600..a4f27e09 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -44,6 +44,7 @@ type fakeRoomClient struct { lastMicDown *roomv1.MicDownRequest lastChangeMicSeat *roomv1.ChangeMicSeatRequest lastConfirmMic *roomv1.ConfirmMicPublishingRequest + lastMicHeartbeat *roomv1.MicHeartbeatRequest lastSetMicMute *roomv1.SetMicMuteRequest lastRTCEvent *roomv1.ApplyRTCEventRequest lastMicSeatLock *roomv1.SetMicSeatLockRequest @@ -203,6 +204,11 @@ func (f *fakeRoomClient) ConfirmMicPublishing(_ context.Context, req *roomv1.Con return &roomv1.ConfirmMicPublishingResponse{Result: &roomv1.CommandResult{Applied: true, RoomVersion: 7}}, nil } +func (f *fakeRoomClient) MicHeartbeat(_ context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) { + f.lastMicHeartbeat = req + return &roomv1.MicHeartbeatResponse{Result: &roomv1.CommandResult{Applied: true, RoomVersion: 8}, SeatNo: 2, MicHeartbeatAtMs: 1_700_000_001_000}, nil +} + func (f *fakeRoomClient) SetMicMute(_ context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) { f.lastSetMicMute = req return &roomv1.SetMicMuteResponse{Result: &roomv1.CommandResult{Applied: true, RoomVersion: 7}}, nil @@ -425,63 +431,69 @@ type fakeUserHostClient struct { } type fakeWalletClient struct { - last *walletv1.GetBalancesRequest - balanceRequests []*walletv1.GetBalancesRequest - resp *walletv1.GetBalancesResponse - balancesByUserID map[int64]*walletv1.GetBalancesResponse - err error - lastOverview *walletv1.GetWalletOverviewRequest - overviewResp *walletv1.GetWalletOverviewResponse - overviewErr error - lastValueSummary *walletv1.GetWalletValueSummaryRequest - valueSummaryResp *walletv1.GetWalletValueSummaryResponse - valueSummaryErr error - lastGiftWall *walletv1.GetUserGiftWallRequest - giftWallResp *walletv1.GetUserGiftWallResponse - lastRechargeProducts *walletv1.ListRechargeProductsRequest - rechargeProductsResp *walletv1.ListRechargeProductsResponse - lastGoogleConfirm *walletv1.ConfirmGooglePaymentRequest - googleConfirmResp *walletv1.ConfirmGooglePaymentResponse - lastDiamondExchange *walletv1.GetDiamondExchangeConfigRequest - diamondExchangeResp *walletv1.GetDiamondExchangeConfigResponse - lastTransactions *walletv1.ListWalletTransactionsRequest - transactionsResp *walletv1.ListWalletTransactionsResponse - lastVipPackages *walletv1.ListVipPackagesRequest - vipPackagesResp *walletv1.ListVipPackagesResponse - lastMyVip *walletv1.GetMyVipRequest - myVipResp *walletv1.GetMyVipResponse - vipErr error - lastPurchaseVip *walletv1.PurchaseVipRequest - purchaseVipResp *walletv1.PurchaseVipResponse - lastTransfer *walletv1.TransferCoinFromSellerRequest - transferResp *walletv1.TransferCoinFromSellerResponse - transferErr error - lastListResources *walletv1.ListResourcesRequest - listResourcesResp *walletv1.ListResourcesResponse - lastGetResource *walletv1.GetResourceRequest - resourcesByID map[int64]*walletv1.Resource - lastGetResourceGroup *walletv1.GetResourceGroupRequest - resourceGroupsByID map[int64]*walletv1.ResourceGroup - lastResourceShop *walletv1.ListResourceShopItemsRequest - resourceShopResp *walletv1.ListResourceShopItemsResponse - lastPurchaseShop *walletv1.PurchaseResourceShopItemRequest - purchaseShopResp *walletv1.PurchaseResourceShopItemResponse - lastListGiftConfigs *walletv1.ListGiftConfigsRequest - listGiftConfigsResp *walletv1.ListGiftConfigsResponse - lastListGiftTypes *walletv1.ListGiftTypeConfigsRequest - listGiftTypesResp *walletv1.ListGiftTypeConfigsResponse - lastGrantResource *walletv1.GrantResourceRequest - grantResourceResp *walletv1.ResourceGrantResponse - grantResourceErr error - lastBatchEquipped *walletv1.BatchGetUserEquippedResourcesRequest - batchEquippedRequests []*walletv1.BatchGetUserEquippedResourcesRequest - batchEquippedResp *walletv1.BatchGetUserEquippedResourcesResponse - lastListRedPackets *walletv1.ListRedPacketsRequest - listRedPacketsResp *walletv1.ListRedPacketsResponse - lastGetRedPacket *walletv1.GetRedPacketRequest - getRedPacketResp *walletv1.GetRedPacketResponse - lastClaimRedPacket *walletv1.ClaimRedPacketRequest - claimRedPacketResp *walletv1.ClaimRedPacketResponse + last *walletv1.GetBalancesRequest + balanceRequests []*walletv1.GetBalancesRequest + resp *walletv1.GetBalancesResponse + balancesByUserID map[int64]*walletv1.GetBalancesResponse + err error + lastHostSalaryPolicy *walletv1.GetActiveHostSalaryPolicyRequest + hostSalaryPolicyResp *walletv1.GetActiveHostSalaryPolicyResponse + hostSalaryPolicyErr error + lastHostSalaryProgress *walletv1.GetHostSalaryProgressRequest + hostSalaryProgressResp *walletv1.GetHostSalaryProgressResponse + hostSalaryProgressErr error + lastOverview *walletv1.GetWalletOverviewRequest + overviewResp *walletv1.GetWalletOverviewResponse + overviewErr error + lastValueSummary *walletv1.GetWalletValueSummaryRequest + valueSummaryResp *walletv1.GetWalletValueSummaryResponse + valueSummaryErr error + lastGiftWall *walletv1.GetUserGiftWallRequest + giftWallResp *walletv1.GetUserGiftWallResponse + lastRechargeProducts *walletv1.ListRechargeProductsRequest + rechargeProductsResp *walletv1.ListRechargeProductsResponse + lastGoogleConfirm *walletv1.ConfirmGooglePaymentRequest + googleConfirmResp *walletv1.ConfirmGooglePaymentResponse + lastDiamondExchange *walletv1.GetDiamondExchangeConfigRequest + diamondExchangeResp *walletv1.GetDiamondExchangeConfigResponse + lastTransactions *walletv1.ListWalletTransactionsRequest + transactionsResp *walletv1.ListWalletTransactionsResponse + lastVipPackages *walletv1.ListVipPackagesRequest + vipPackagesResp *walletv1.ListVipPackagesResponse + lastMyVip *walletv1.GetMyVipRequest + myVipResp *walletv1.GetMyVipResponse + vipErr error + lastPurchaseVip *walletv1.PurchaseVipRequest + purchaseVipResp *walletv1.PurchaseVipResponse + lastTransfer *walletv1.TransferCoinFromSellerRequest + transferResp *walletv1.TransferCoinFromSellerResponse + transferErr error + lastListResources *walletv1.ListResourcesRequest + listResourcesResp *walletv1.ListResourcesResponse + lastGetResource *walletv1.GetResourceRequest + resourcesByID map[int64]*walletv1.Resource + lastGetResourceGroup *walletv1.GetResourceGroupRequest + resourceGroupsByID map[int64]*walletv1.ResourceGroup + lastResourceShop *walletv1.ListResourceShopItemsRequest + resourceShopResp *walletv1.ListResourceShopItemsResponse + lastPurchaseShop *walletv1.PurchaseResourceShopItemRequest + purchaseShopResp *walletv1.PurchaseResourceShopItemResponse + lastListGiftConfigs *walletv1.ListGiftConfigsRequest + listGiftConfigsResp *walletv1.ListGiftConfigsResponse + lastListGiftTypes *walletv1.ListGiftTypeConfigsRequest + listGiftTypesResp *walletv1.ListGiftTypeConfigsResponse + lastGrantResource *walletv1.GrantResourceRequest + grantResourceResp *walletv1.ResourceGrantResponse + grantResourceErr error + lastBatchEquipped *walletv1.BatchGetUserEquippedResourcesRequest + batchEquippedRequests []*walletv1.BatchGetUserEquippedResourcesRequest + batchEquippedResp *walletv1.BatchGetUserEquippedResourcesResponse + lastListRedPackets *walletv1.ListRedPacketsRequest + listRedPacketsResp *walletv1.ListRedPacketsResponse + lastGetRedPacket *walletv1.GetRedPacketRequest + getRedPacketResp *walletv1.GetRedPacketResponse + lastClaimRedPacket *walletv1.ClaimRedPacketRequest + claimRedPacketResp *walletv1.ClaimRedPacketResponse } type fakeMessageInboxClient struct { @@ -1212,6 +1224,28 @@ func (f *fakeWalletClient) GetBalances(_ context.Context, req *walletv1.GetBalan return &walletv1.GetBalancesResponse{}, nil } +func (f *fakeWalletClient) GetActiveHostSalaryPolicy(_ context.Context, req *walletv1.GetActiveHostSalaryPolicyRequest) (*walletv1.GetActiveHostSalaryPolicyResponse, error) { + f.lastHostSalaryPolicy = req + if f.hostSalaryPolicyErr != nil { + return nil, f.hostSalaryPolicyErr + } + if f.hostSalaryPolicyResp != nil { + return f.hostSalaryPolicyResp, nil + } + return &walletv1.GetActiveHostSalaryPolicyResponse{}, nil +} + +func (f *fakeWalletClient) GetHostSalaryProgress(_ context.Context, req *walletv1.GetHostSalaryProgressRequest) (*walletv1.GetHostSalaryProgressResponse, error) { + f.lastHostSalaryProgress = req + if f.hostSalaryProgressErr != nil { + return nil, f.hostSalaryProgressErr + } + if f.hostSalaryProgressResp != nil { + return f.hostSalaryProgressResp, nil + } + return &walletv1.GetHostSalaryProgressResponse{Progress: &walletv1.HostSalaryProgress{HostUserId: req.GetHostUserId()}}, nil +} + func (f *fakeWalletClient) GetWalletOverview(_ context.Context, req *walletv1.GetWalletOverviewRequest) (*walletv1.GetWalletOverviewResponse, error) { f.lastOverview = req if f.overviewErr != nil { @@ -1704,6 +1738,15 @@ func TestRoomCommandsPropagateClientCommandID(t *testing.T) { return client.lastConfirmMic.GetMeta() }, }, + { + name: "mic_heartbeat", + path: "/api/v1/rooms/mic/heartbeat", + body: `{"room_id":"room-1","command_id":"cmd-mic-heartbeat-1","mic_session_id":"mic-1"}`, + commandID: "cmd-mic-heartbeat-1", + extractMeta: func(client *fakeRoomClient) *roomv1.RequestMeta { + return client.lastMicHeartbeat.GetMeta() + }, + }, { name: "mic_lock", path: "/api/v1/rooms/mic/lock", @@ -3263,6 +3306,165 @@ func TestApplyToHostAgencyPropagatesClientCommandID(t *testing.T) { } } +func TestHostCenterAgencyUsesCurrentHostAgencyAndOwnerProfile(t *testing.T) { + hostClient := &fakeUserHostClient{ + hostProfile: &userv1.HostProfile{ + UserId: 42, + Status: "active", + RegionId: 30, + CurrentAgencyId: 7001, + }, + getAgencyResp: &userv1.GetAgencyResponse{Agency: &userv1.Agency{ + AgencyId: 7001, + OwnerUserId: 99, + RegionId: 30, + Name: "Yumi Star Agency", + Status: "active", + }}, + } + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 99: {UserId: 99, DisplayUserId: "163003", Username: "agency-owner", Avatar: "https://cdn.example/agency-owner.png"}, + }} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetUserHostClient(hostClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/host-center/agency?agency_id=9999", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-host-center-agency") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastHost == nil || hostClient.lastHost.GetUserId() != 42 { + t.Fatalf("host profile request mismatch: %+v", hostClient.lastHost) + } + if hostClient.lastGetAgency == nil || hostClient.lastGetAgency.GetAgencyId() != 7001 { + t.Fatalf("agency request must use current host agency: %+v", hostClient.lastGetAgency) + } + if profileClient.lastBatch == nil || len(profileClient.lastBatch.GetUserIds()) != 1 || profileClient.lastBatch.GetUserIds()[0] != 99 { + t.Fatalf("owner profile request mismatch: %+v", profileClient.lastBatch) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + agency := data["agency"].(map[string]any) + if agency["agency_id"] != "7001" || agency["short_id"] != "163003" || agency["avatar"] != "https://cdn.example/agency-owner.png" || agency["name"] != "Yumi Star Agency" { + t.Fatalf("host center agency response mismatch: %+v", agency) + } +} + +func TestHostCenterPlatformPolicyUsesCurrentHostRegion(t *testing.T) { + hostClient := &fakeUserHostClient{hostProfile: &userv1.HostProfile{ + UserId: 42, + Status: "active", + RegionId: 30, + CurrentAgencyId: 7001, + }} + walletClient := &fakeWalletClient{ + hostSalaryPolicyResp: &walletv1.GetActiveHostSalaryPolicyResponse{ + Found: true, + Policy: &walletv1.HostSalaryPolicy{ + PolicyId: 9001, + Name: "Host Growth Policy", + RegionId: 30, + Status: "active", + SettlementMode: "half_month", + SettlementTriggerMode: "automatic", + GiftCoinToDiamondRatio: "1.0000", + ResidualDiamondToUsdRate: "0.0100", + EffectiveFromMs: 1700000000000, + Levels: []*walletv1.HostSalaryPolicyLevel{ + {LevelNo: 1, RequiredDiamonds: 1000, HostSalaryUsdMinor: 1500, HostCoinReward: 200, AgencySalaryUsdMinor: 300, Status: "active", SortOrder: 1}, + {LevelNo: 2, RequiredDiamonds: 3000, HostSalaryUsdMinor: 4500, HostCoinReward: 500, AgencySalaryUsdMinor: 900, Status: "active", SortOrder: 2}, + }, + }, + }, + hostSalaryProgressResp: &walletv1.GetHostSalaryProgressResponse{Progress: &walletv1.HostSalaryProgress{ + HostUserId: 42, + CycleKey: "2026-06", + RegionId: 30, + AgencyOwnerUserId: 99, + TotalDiamonds: 1200, + GiftDiamondTotal: 1200, + }}, + } + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetUserHostClient(hostClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/host-center/platform-policy", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-host-policy") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastHost == nil || hostClient.lastHost.GetUserId() != 42 { + t.Fatalf("host profile request mismatch: %+v", hostClient.lastHost) + } + if walletClient.lastHostSalaryPolicy == nil || walletClient.lastHostSalaryPolicy.GetRegionId() != 30 || walletClient.lastHostSalaryPolicy.GetSettlementTriggerMode() != "automatic" || walletClient.lastHostSalaryPolicy.GetAppCode() == "" || walletClient.lastHostSalaryPolicy.GetRequestId() == "" { + t.Fatalf("host salary policy request mismatch: %+v", walletClient.lastHostSalaryPolicy) + } + if walletClient.lastHostSalaryProgress == nil || walletClient.lastHostSalaryProgress.GetHostUserId() != 42 || walletClient.lastHostSalaryProgress.GetAppCode() == "" || walletClient.lastHostSalaryProgress.GetRequestId() == "" { + t.Fatalf("host salary progress request mismatch: %+v", walletClient.lastHostSalaryProgress) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + policy := data["policy"].(map[string]any) + levels := policy["levels"].([]any) + firstLevel := levels[0].(map[string]any) + progress := data["progress"].(map[string]any) + levelProgress := data["level_progress"].(map[string]any) + if data["found"] != true || data["host_region_id"] != float64(30) || policy["policy_id"] != "9001" || policy["settlement_mode"] != "half_month" || firstLevel["host_salary_usd"] != 15.0 || firstLevel["agency_salary_usd"] != 3.0 { + t.Fatalf("host policy response mismatch: %+v", data) + } + if progress["cycle_key"] != "2026-06" || progress["total_diamonds"] != float64(1200) { + t.Fatalf("host salary progress response mismatch: %+v", progress) + } + if levelProgress["current_level"] != float64(1) || levelProgress["current_value"] != float64(1200) || levelProgress["next_level"] != float64(2) || levelProgress["needed_for_next_level"] != float64(1800) { + t.Fatalf("host level progress response mismatch: %+v", levelProgress) + } +} + +func TestHostCenterPlatformPolicyRejectsNonActiveHost(t *testing.T) { + hostClient := &fakeUserHostClient{hostProfile: &userv1.HostProfile{ + UserId: 42, + Status: "pending", + RegionId: 30, + }} + walletClient := &fakeWalletClient{} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetUserHostClient(hostClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/host-center/platform-policy", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusForbidden { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if walletClient.lastHostSalaryPolicy != nil { + t.Fatalf("wallet should not be called for non-active host: %+v", walletClient.lastHostSalaryPolicy) + } + if walletClient.lastHostSalaryProgress != nil { + t.Fatalf("progress should not be called for non-active host: %+v", walletClient.lastHostSalaryProgress) + } +} + func TestAgencyCenterOverviewUsesOwnerAgencySalaryAndPendingApplications(t *testing.T) { hostClient := &fakeUserHostClient{ roleSummary: &userv1.UserRoleSummary{UserId: 42, IsManager: true, AgencyId: 7001}, @@ -3463,6 +3665,27 @@ func TestConfirmMicPublishingForwardsSessionVersionAndEventTime(t *testing.T) { } } +func TestMicHeartbeatForwardsCurrentSession(t *testing.T) { + client := &fakeRoomClient{} + router := NewHandler(client).Routes(auth.NewVerifier("secret")) + body := []byte(`{"room_id":"room-1","command_id":"cmd-mic-heartbeat","target_user_id":43,"mic_session_id":"mic-session-1"}`) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/mic/heartbeat", bytes.NewReader(body)) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-mic-heartbeat") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + assertEnvelope(t, recorder, http.StatusOK, httpkit.CodeOK, "req-mic-heartbeat") + if client.lastMicHeartbeat == nil { + t.Fatal("MicHeartbeat request was not sent") + } + if client.lastMicHeartbeat.GetTargetUserId() != 43 || + client.lastMicHeartbeat.GetMicSessionId() != "mic-session-1" { + t.Fatalf("mic heartbeat fields mismatch: %+v", client.lastMicHeartbeat) + } +} + func TestThirdPartyLoginUsesPublicEnvelopeAndPropagatesRequestID(t *testing.T) { userClient := &fakeUserAuthClient{} router := NewHandler(&fakeRoomClient{}, userClient).Routes(auth.NewVerifier("secret")) @@ -5335,6 +5558,7 @@ func TestProfileGateRejectsIncompleteUsersForRoomIMRTCPaidCapabilities(t *testin {name: "profile_update", method: http.MethodPost, path: "/api/v1/rooms/profile/update", body: `{"room_id":"room-1"}`}, {name: "join_room", method: http.MethodPost, path: "/api/v1/rooms/join", body: `{"room_id":"room-1"}`}, {name: "room_heartbeat", method: http.MethodPost, path: "/api/v1/rooms/heartbeat", body: `{"room_id":"room-1"}`}, + {name: "mic_heartbeat", method: http.MethodPost, path: "/api/v1/rooms/mic/heartbeat", body: `{"room_id":"room-1","mic_session_id":"mic-1"}`}, {name: "im_usersig", method: http.MethodGet, path: "/api/v1/im/usersig"}, {name: "rtc_token", method: http.MethodPost, path: "/api/v1/rtc/token", body: `{"room_id":"room-1"}`}, {name: "send_gift", method: http.MethodPost, path: "/api/v1/rooms/gift/send", body: `{"room_id":"room-1","gift_id":"rose"}`}, diff --git a/services/gateway-service/internal/transport/http/roomapi/handler.go b/services/gateway-service/internal/transport/http/roomapi/handler.go index f3193a57..6c5a534c 100644 --- a/services/gateway-service/internal/transport/http/roomapi/handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/handler.go @@ -77,6 +77,7 @@ func (h *Handler) RoomHandlers() httproutes.RoomHandlers { MicDown: h.micDown, ChangeMicSeat: h.changeMicSeat, ConfirmMicPublishing: h.confirmMicPublishing, + MicHeartbeat: h.micHeartbeat, SetMicMute: h.setMicMute, SetMicSeatLock: h.setMicSeatLock, SetChatEnabled: h.setChatEnabled, diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_handler.go index f725a21a..daa925d0 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler.go @@ -1073,6 +1073,27 @@ func (h *Handler) confirmMicPublishing(writer http.ResponseWriter, request *http httpkit.Write(writer, request, resp, err) } +// micHeartbeat 把客户端麦上心跳转换为 room-service 当前 mic_session 刷新命令。 +func (h *Handler) micHeartbeat(writer http.ResponseWriter, request *http.Request) { + var body struct { + RoomID string `json:"room_id"` + CommandID string `json:"command_id"` + TargetUserID int64 `json:"target_user_id"` + MicSessionID string `json:"mic_session_id"` + } + + if !httpkit.Decode(writer, request, &body) { + return + } + + resp, err := h.roomClient.MicHeartbeat(request.Context(), &roomv1.MicHeartbeatRequest{ + Meta: httpkit.RoomMeta(request, body.RoomID, body.CommandID), + TargetUserId: body.TargetUserID, + MicSessionId: body.MicSessionID, + }) + httpkit.Write(writer, request, resp, err) +} + // setMicMute 把麦克风静音 HTTP 请求转换为 room-service SetMicMute 命令。 func (h *Handler) setMicMute(writer http.ResponseWriter, request *http.Request) { var body struct { diff --git a/services/gateway-service/internal/transport/http/roomapi/room_view.go b/services/gateway-service/internal/transport/http/roomapi/room_view.go index ffab7e39..34e8cbce 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_view.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_view.go @@ -332,6 +332,7 @@ type roomSeatData struct { PublishDeadlineMS int64 `json:"publish_deadline_ms,omitempty"` MicMuted bool `json:"mic_muted"` SeatStatus string `json:"seat_status,omitempty"` + MicHeartbeatAtMS int64 `json:"mic_heartbeat_at_ms,omitempty"` } type roomRankItemData struct { @@ -653,6 +654,7 @@ func roomSeatDataFromSnapshot(snapshot *roomv1.RoomSnapshot) []roomSeatData { PublishDeadlineMS: seat.GetPublishDeadlineMs(), MicMuted: seat.GetMicMuted(), SeatStatus: seat.GetSeatStatus(), + MicHeartbeatAtMS: seat.GetMicHeartbeatAtMs(), }) } return items diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index 435fcf31..1411a46b 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -56,6 +56,8 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { GetMyRoleSummary: h.getMyRoleSummary, SearchHostAgencies: h.searchHostAgencies, ApplyToHostAgency: h.applyToHostAgency, + GetHostCenterAgency: h.getHostCenterAgency, + GetHostCenterPlatformPolicy: h.getHostCenterPlatformPolicy, GetAgencyCenterOverview: h.getAgencyCenterOverview, ListAgencyCenterHosts: h.listAgencyCenterHosts, ListAgencyCenterApplications: h.listAgencyCenterApplications, diff --git a/services/gateway-service/internal/transport/http/userapi/host_center_agency_handler.go b/services/gateway-service/internal/transport/http/userapi/host_center_agency_handler.go new file mode 100644 index 00000000..ca934f09 --- /dev/null +++ b/services/gateway-service/internal/transport/http/userapi/host_center_agency_handler.go @@ -0,0 +1,69 @@ +package userapi + +import ( + "net/http" + + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type hostCenterAgencyData struct { + AgencyID string `json:"agency_id"` + ShortID string `json:"short_id"` + Name string `json:"name"` + Avatar string `json:"avatar,omitempty"` +} + +func (h *Handler) getHostCenterAgency(writer http.ResponseWriter, request *http.Request) { + profile, ok := h.resolveCurrentActiveHostProfile(writer, request) + if !ok { + return + } + if profile.GetCurrentAgencyId() <= 0 { + httpkit.WriteOK(writer, request, map[string]any{"agency": nil}) + return + } + if h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + // 当前主播所属 agency 只能从 user-service 的 host_profile 快照读取,前端不能传任意 agency_id 查看。 + agencyResp, err := h.userHostClient.GetAgency(request.Context(), &userv1.GetAgencyRequest{ + Meta: httpkit.UserMeta(request, ""), + AgencyId: profile.GetCurrentAgencyId(), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + agency := agencyResp.GetAgency() + if agency == nil || agency.GetAgencyId() != profile.GetCurrentAgencyId() || agency.GetStatus() != agencyStatusActive { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return + } + + data := hostCenterAgencyData{ + AgencyID: int64String(agency.GetAgencyId()), + ShortID: int64String(agency.GetAgencyId()), + Name: agency.GetName(), + Avatar: agency.GetAvatar(), + } + if agency.GetOwnerUserId() > 0 { + profiles, err := h.userProfiles(request, []int64{agency.GetOwnerUserId()}) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if owner, exists := profiles[agency.GetOwnerUserId()]; exists { + if owner.DisplayUserID != "" { + data.ShortID = owner.DisplayUserID + } + if owner.Avatar != "" { + data.Avatar = owner.Avatar + } + } + } + + httpkit.WriteOK(writer, request, map[string]any{"agency": data}) +} diff --git a/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go b/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go new file mode 100644 index 00000000..3fa70adf --- /dev/null +++ b/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go @@ -0,0 +1,219 @@ +package userapi + +import ( + "net/http" + "strconv" + + userv1 "hyapp.local/api/proto/user/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +const hostProfileStatusActive = "active" + +type hostCenterPolicyData struct { + PolicyID string `json:"policy_id"` + Name string `json:"name"` + RegionID int64 `json:"region_id"` + Status string `json:"status"` + SettlementMode string `json:"settlement_mode"` + SettlementTriggerMode string `json:"settlement_trigger_mode"` + GiftCoinToDiamondRatio string `json:"gift_coin_to_diamond_ratio"` + ResidualDiamondToUSDRate string `json:"residual_diamond_to_usd_rate"` + EffectiveFromMS int64 `json:"effective_from_ms"` + EffectiveToMS int64 `json:"effective_to_ms"` + Levels []hostCenterPolicyLevelData `json:"levels"` +} + +type hostCenterPolicyLevelData struct { + LevelNo int32 `json:"level_no"` + RequiredDiamonds int64 `json:"required_diamonds"` + HostSalaryUSDMinor int64 `json:"host_salary_usd_minor"` + HostSalaryUSD float64 `json:"host_salary_usd"` + HostCoinReward int64 `json:"host_coin_reward"` + AgencySalaryUSDMinor int64 `json:"agency_salary_usd_minor"` + AgencySalaryUSD float64 `json:"agency_salary_usd"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` +} + +type hostCenterSalaryProgressData struct { + HostUserID int64 `json:"host_user_id"` + CycleKey string `json:"cycle_key"` + RegionID int64 `json:"region_id"` + AgencyOwnerUserID int64 `json:"agency_owner_user_id"` + TotalDiamonds int64 `json:"total_diamonds"` + GiftDiamondTotal int64 `json:"gift_diamond_total"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type hostCenterLevelProgressData struct { + CurrentLevel int32 `json:"current_level"` + CurrentRequiredDiamonds int64 `json:"current_required_diamonds"` + CurrentValue int64 `json:"current_value"` + NextLevel int32 `json:"next_level"` + NextRequiredDiamonds int64 `json:"next_required_diamonds"` + NeededForNextLevel int64 `json:"needed_for_next_level"` +} + +func (h *Handler) getHostCenterPlatformPolicy(writer http.ResponseWriter, request *http.Request) { + profile, ok := h.resolveCurrentActiveHostProfile(writer, request) + if !ok { + return + } + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + // H5 不传 region 或 policy id;gateway 固定使用当前主播身份里的区域快照读取实际生效政策。 + resp, err := h.walletClient.GetActiveHostSalaryPolicy(request.Context(), &walletv1.GetActiveHostSalaryPolicyRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + RegionId: profile.GetRegionId(), + SettlementTriggerMode: "automatic", + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + // 等级进度必须按工资周期钻石账户计算,不能使用用户成长等级,否则“距离下一级”会和后台工资政策不一致。 + progressResp, err := h.walletClient.GetHostSalaryProgress(request.Context(), &walletv1.GetHostSalaryProgressRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + HostUserId: profile.GetUserId(), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + progress := progressResp.GetProgress() + + httpkit.WriteOK(writer, request, map[string]any{ + "found": resp.GetFound(), + "host_region_id": profile.GetRegionId(), + "policy": hostCenterPolicyFromProto(resp.GetPolicy()), + "progress": hostCenterSalaryProgressFromProto(progress), + "level_progress": hostCenterLevelProgressFromPolicy(resp.GetPolicy(), progress.GetTotalDiamonds()), + }) +} + +func (h *Handler) resolveCurrentActiveHostProfile(writer http.ResponseWriter, request *http.Request) (*userv1.HostProfile, bool) { + if h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return nil, false + } + userID := auth.UserIDFromContext(request.Context()) + resp, err := h.userHostClient.GetHostProfile(request.Context(), &userv1.GetHostProfileRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return nil, false + } + profile := resp.GetHostProfile() + if profile == nil || profile.GetUserId() != userID || profile.GetStatus() != hostProfileStatusActive || profile.GetRegionId() <= 0 { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return nil, false + } + return profile, true +} + +func hostCenterPolicyFromProto(policy *walletv1.HostSalaryPolicy) *hostCenterPolicyData { + if policy == nil { + return nil + } + levels := make([]hostCenterPolicyLevelData, 0, len(policy.GetLevels())) + for _, level := range policy.GetLevels() { + levels = append(levels, hostCenterPolicyLevelFromProto(level)) + } + return &hostCenterPolicyData{ + PolicyID: strconv.FormatUint(policy.GetPolicyId(), 10), + Name: policy.GetName(), + RegionID: policy.GetRegionId(), + Status: policy.GetStatus(), + SettlementMode: policy.GetSettlementMode(), + SettlementTriggerMode: policy.GetSettlementTriggerMode(), + GiftCoinToDiamondRatio: policy.GetGiftCoinToDiamondRatio(), + ResidualDiamondToUSDRate: policy.GetResidualDiamondToUsdRate(), + EffectiveFromMS: policy.GetEffectiveFromMs(), + EffectiveToMS: policy.GetEffectiveToMs(), + Levels: levels, + } +} + +func hostCenterPolicyLevelFromProto(level *walletv1.HostSalaryPolicyLevel) hostCenterPolicyLevelData { + if level == nil { + return hostCenterPolicyLevelData{} + } + return hostCenterPolicyLevelData{ + LevelNo: level.GetLevelNo(), + RequiredDiamonds: level.GetRequiredDiamonds(), + HostSalaryUSDMinor: level.GetHostSalaryUsdMinor(), + HostSalaryUSD: float64(level.GetHostSalaryUsdMinor()) / 100, + HostCoinReward: level.GetHostCoinReward(), + AgencySalaryUSDMinor: level.GetAgencySalaryUsdMinor(), + AgencySalaryUSD: float64(level.GetAgencySalaryUsdMinor()) / 100, + Status: level.GetStatus(), + SortOrder: level.GetSortOrder(), + } +} + +func hostCenterSalaryProgressFromProto(progress *walletv1.HostSalaryProgress) hostCenterSalaryProgressData { + if progress == nil { + return hostCenterSalaryProgressData{} + } + return hostCenterSalaryProgressData{ + HostUserID: progress.GetHostUserId(), + CycleKey: progress.GetCycleKey(), + RegionID: progress.GetRegionId(), + AgencyOwnerUserID: progress.GetAgencyOwnerUserId(), + TotalDiamonds: progress.GetTotalDiamonds(), + GiftDiamondTotal: progress.GetGiftDiamondTotal(), + UpdatedAtMS: progress.GetUpdatedAtMs(), + } +} + +func hostCenterLevelProgressFromPolicy(policy *walletv1.HostSalaryPolicy, currentValue int64) *hostCenterLevelProgressData { + levels := policy.GetLevels() + if len(levels) == 0 { + return nil + } + var current *walletv1.HostSalaryPolicyLevel + var next *walletv1.HostSalaryPolicyLevel + for _, level := range levels { + if level == nil { + continue + } + required := level.GetRequiredDiamonds() + if required <= currentValue { + if current == nil || required > current.GetRequiredDiamonds() { + current = level + } + continue + } + if next == nil || required < next.GetRequiredDiamonds() { + next = level + } + } + result := &hostCenterLevelProgressData{ + CurrentValue: currentValue, + } + if current != nil { + result.CurrentLevel = current.GetLevelNo() + result.CurrentRequiredDiamonds = current.GetRequiredDiamonds() + } + if next != nil { + result.NextLevel = next.GetLevelNo() + result.NextRequiredDiamonds = next.GetRequiredDiamonds() + result.NeededForNextLevel = next.GetRequiredDiamonds() - currentValue + return result + } + result.NextLevel = result.CurrentLevel + result.NextRequiredDiamonds = result.CurrentRequiredDiamonds + return result +} diff --git a/services/room-service/internal/integration/tencent_im.go b/services/room-service/internal/integration/tencent_im.go index 1e2f772a..f53870c7 100644 --- a/services/room-service/internal/integration/tencent_im.go +++ b/services/room-service/internal/integration/tencent_im.go @@ -212,14 +212,12 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room base.Attributes = map[string]string{"enabled": fmt.Sprintf("%t", body.GetEnabled())} return base, true, nil case "RoomPasswordChanged": - // 锁房事件只广播布尔状态,密码明文和哈希都不会进入 IM 自定义消息。 + // 锁房事件改由 activity-service 按 visible_region_id 生成区域通知;房间群不再重复投递。 var body roomeventsv1.RoomPasswordChanged if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { return tencentim.RoomEvent{}, false, err } - base.ActorUserID = body.GetActorUserId() - base.Attributes = map[string]string{"locked": fmt.Sprintf("%t", body.GetLocked())} - return base, true, nil + return tencentim.RoomEvent{}, false, nil case "RoomAdminChanged": // 管理员变更进入系统消息,客户端收到后仍应以最新 snapshot 修正本地权限 UI。 var body roomeventsv1.RoomAdminChanged diff --git a/services/room-service/internal/integration/tencent_im_test.go b/services/room-service/internal/integration/tencent_im_test.go index f58f5e9c..3f26948d 100644 --- a/services/room-service/internal/integration/tencent_im_test.go +++ b/services/room-service/internal/integration/tencent_im_test.go @@ -87,6 +87,25 @@ func TestRoomBackgroundChangedPublishesDedicatedIMEvent(t *testing.T) { } } +func TestRoomPasswordChangedSkipsRoomGroupIM(t *testing.T) { + record, err := outbox.Build("room-lock", "RoomPasswordChanged", 8, time.Now(), &roomeventsv1.RoomPasswordChanged{ + ActorUserId: 42, + Locked: true, + VisibleRegionId: 86, + }) + if err != nil { + t.Fatalf("Build RoomPasswordChanged envelope failed: %v", err) + } + + event, publish, err := roomEventFromEnvelope(record.Envelope) + if err != nil { + t.Fatalf("RoomPasswordChanged should decode: %v", err) + } + if publish { + t.Fatalf("RoomPasswordChanged must use activity region broadcast, not room group IM: %+v", event) + } +} + func TestTencentIMPublisherRemovesGroupMemberBeforeKickMessage(t *testing.T) { paths := make([]string, 0, 2) client, err := tencentim.NewRESTClient(tencentim.RESTConfig{ diff --git a/services/room-service/internal/room/command/command.go b/services/room-service/internal/room/command/command.go index b9ddbde9..5398b09b 100644 --- a/services/room-service/internal/room/command/command.go +++ b/services/room-service/internal/room/command/command.go @@ -225,6 +225,18 @@ type ConfirmMicPublishing struct { // Type 返回命令类型。 func (ConfirmMicPublishing) Type() string { return "confirm_mic_publishing" } +// MicHeartbeat 定义当前麦位会话的服务端心跳刷新请求。 +type MicHeartbeat struct { + Base + // TargetUserID 是被刷新麦上心跳的用户;为空时服务层使用 ActorUserID。 + TargetUserID int64 `json:"target_user_id"` + // MicSessionID 必须匹配当前麦位会话,避免旧客户端心跳续住新麦位。 + MicSessionID string `json:"mic_session_id"` +} + +// Type 返回命令类型。 +func (MicHeartbeat) Type() string { return "mic_heartbeat" } + // SetMicMute 定义麦克风静音状态同步请求。 type SetMicMute struct { Base @@ -563,6 +575,8 @@ func Deserialize(commandType string, payload []byte) (Command, error) { cmd = &MicDown{} case ConfirmMicPublishing{}.Type(): cmd = &ConfirmMicPublishing{} + case MicHeartbeat{}.Type(): + cmd = &MicHeartbeat{} case SetMicMute{}.Type(): cmd = &SetMicMute{} case ApplyRTCEvent{}.Type(): diff --git a/services/room-service/internal/room/service/lock_test.go b/services/room-service/internal/room/service/lock_test.go index 4f59bf3e..1b663227 100644 --- a/services/room-service/internal/room/service/lock_test.go +++ b/services/room-service/internal/room/service/lock_test.go @@ -102,4 +102,26 @@ func TestRoomPasswordControlsJoinAndListLockedFlag(t *testing.T) { if joinResp.GetUser().GetUserId() != viewerID || !joinResp.GetRoom().GetLocked() { t.Fatalf("join response mismatch: user=%+v room=%+v", joinResp.GetUser(), joinResp.GetRoom()) } + + if _, err := svc.SetRoomPassword(ctx, &roomv1.SetRoomPasswordRequest{ + Meta: roomservice.NewRequestMeta(roomID, ownerID), + Locked: true, + Password: "5678", + }); err != nil { + t.Fatalf("change room password after viewer joined failed: %v", err) + } + if _, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{ + Meta: roomservice.NewRequestMeta(roomID, viewerID), + Role: "audience", + Password: "1234", + }); err == nil { + t.Fatalf("existing online user must not bypass changed room password") + } + if _, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{ + Meta: roomservice.NewRequestMeta(roomID, viewerID), + Role: "audience", + Password: "5678", + }); err != nil { + t.Fatalf("existing online user should reconnect with latest room password: %v", err) + } } diff --git a/services/room-service/internal/room/service/mic.go b/services/room-service/internal/room/service/mic.go index 00e754e8..19e6a2a5 100644 --- a/services/room-service/internal/room/service/mic.go +++ b/services/room-service/internal/room/service/mic.go @@ -68,6 +68,7 @@ func (s *Service) MicUp(ctx context.Context, req *roomv1.MicUpRequest) (*roomv1. // 新 session 尚未接受任何 RTC/客户端事件;不能用服务端 MicUp 时间初始化, // 否则客户端设备时间略慢时,合法的首次确认会被误判为旧事件。 current.MicSeats[index].LastPublishEventTimeMS = 0 + current.MicSeats[index].MicHeartbeatAtMS = 0 current.MicSeats[index].MicMuted = false seatStatus := current.MicSeats[index].SeatStatus() @@ -283,6 +284,7 @@ func (s *Service) ChangeMicSeat(ctx context.Context, req *roomv1.ChangeMicSeatRe current.MicSeats[fromIndex].PublishDeadlineMS = 0 current.MicSeats[fromIndex].MicSessionRoomVersion = 0 current.MicSeats[fromIndex].LastPublishEventTimeMS = 0 + current.MicSeats[fromIndex].MicHeartbeatAtMS = 0 current.MicSeats[fromIndex].MicMuted = false current.MicSeats[toIndex].UserID = cmd.TargetUserID current.MicSeats[toIndex].PublishState = movedSeat.PublishState @@ -290,6 +292,7 @@ func (s *Service) ChangeMicSeat(ctx context.Context, req *roomv1.ChangeMicSeatRe current.MicSeats[toIndex].PublishDeadlineMS = movedSeat.PublishDeadlineMS current.MicSeats[toIndex].MicSessionRoomVersion = movedSeat.MicSessionRoomVersion current.MicSeats[toIndex].LastPublishEventTimeMS = movedSeat.LastPublishEventTimeMS + current.MicSeats[toIndex].MicHeartbeatAtMS = movedSeat.MicHeartbeatAtMS current.MicSeats[toIndex].MicMuted = movedSeat.MicMuted current.Version++ seatStatus := current.MicSeats[toIndex].SeatStatus() @@ -391,6 +394,8 @@ func (s *Service) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmM index := current.SeatIndex(seat.SeatNo) current.MicSeats[index].PublishState = state.MicPublishPublishing current.MicSeats[index].LastPublishEventTimeMS = cmd.EventTimeMS + // 确认发流本身代表当前会话刚被服务端接受,先初始化心跳时间,后续 MicHeartbeat 只负责刷新这个独立字段。 + current.MicSeats[index].MicHeartbeatAtMS = now.UnixMilli() if micPublishConfirmSourceIsMuted(cmd.Source) { current.MicSeats[index].MicMuted = true } @@ -419,6 +424,7 @@ func (s *Service) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmM seatNo: seat.SeatNo, micSessionID: cmd.MicSessionID, publishDeadlineMS: seat.PublishDeadlineMS, + micHeartbeatAtMS: current.MicSeats[index].MicHeartbeatAtMS, syncEvent: &tencentim.RoomEvent{ EventID: micEvent.EventID, RoomID: current.RoomID, @@ -450,6 +456,77 @@ func (s *Service) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmM }, nil } +// MicHeartbeat 刷新当前 publishing 麦位会话的服务端心跳时间。 +func (s *Service) MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) { + ctx = contextFromMeta(ctx, req.GetMeta()) + cmd := command.MicHeartbeat{ + Base: baseFromMeta(req.GetMeta()), + TargetUserID: req.GetTargetUserId(), + MicSessionID: req.GetMicSessionId(), + } + if cmd.TargetUserID == 0 { + cmd.TargetUserID = cmd.ActorUserID() + } + + result, err := s.mutateRoom(ctx, cmd, true, func(now time.Time, current *state.RoomState, _ *rank.LocalRank) (mutationResult, []outbox.Record, error) { + if err := requireActiveRoom(current); err != nil { + return mutationResult{}, nil, err + } + if cmd.TargetUserID <= 0 || cmd.MicSessionID == "" { + return mutationResult{}, nil, xerr.New(xerr.InvalidArgument, "mic heartbeat is incomplete") + } + if err := requireActorPresent(current, cmd.ActorUserID()); err != nil { + return mutationResult{}, nil, err + } + if cmd.ActorUserID() != cmd.TargetUserID { + if err := canManageTarget(current, cmd.ActorUserID(), cmd.TargetUserID); err != nil { + return mutationResult{}, nil, err + } + } + + seat, exists := current.SeatByUser(cmd.TargetUserID) + if !exists { + return mutationResult{}, nil, xerr.New(xerr.NotFound, "target not on seat") + } + if seat.MicSessionID != cmd.MicSessionID { + // 旧客户端或旧 RTC 会话的心跳不能续住新麦位会话。 + return mutationResult{}, nil, xerr.New(xerr.Conflict, "mic session mismatch") + } + if seat.PublishState != state.MicPublishPublishing { + // pending_publish 还没有有效发流,只能先走 ConfirmMicPublishing,不能靠心跳开始计时。 + return mutationResult{}, nil, xerr.New(xerr.Conflict, "mic is not publishing") + } + + heartbeatAtMS := now.UnixMilli() + if existing, ok := current.OnlineUsers[cmd.TargetUserID]; ok { + // 麦上心跳也证明用户仍处于房间页,顺手刷新通用 presence,避免客户端同时打两个心跳。 + existing.LastSeenAtMS = heartbeatAtMS + } + index := current.SeatIndex(seat.SeatNo) + current.MicSeats[index].MicHeartbeatAtMS = heartbeatAtMS + current.Version++ + + return mutationResult{ + snapshot: current.ToProto(), + seatNo: seat.SeatNo, + micHeartbeatAtMS: heartbeatAtMS, + }, nil, nil + }) + if err != nil { + return nil, err + } + if result.micHeartbeatAtMS == 0 { + result.seatNo, result.micHeartbeatAtMS = micHeartbeatFromSnapshot(result.snapshot, cmd.TargetUserID, cmd.MicSessionID) + } + + return &roomv1.MicHeartbeatResponse{ + Result: commandResult(result.applied, result.snapshot.GetVersion(), s.clock.Now()), + SeatNo: result.seatNo, + Room: result.snapshot, + MicHeartbeatAtMs: result.micHeartbeatAtMS, + }, nil +} + // SetMicMute 修改麦位上的服务端可见静音态。 func (s *Service) SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) { ctx = contextFromMeta(ctx, req.GetMeta()) @@ -555,6 +632,15 @@ func micPublishConfirmSourceIsMuted(source string) bool { } } +func micHeartbeatFromSnapshot(snapshot *roomv1.RoomSnapshot, userID int64, micSessionID string) (int32, int64) { + for _, seat := range snapshot.GetMicSeats() { + if seat.GetUserId() == userID && seat.GetMicSessionId() == micSessionID { + return seat.GetSeatNo(), seat.GetMicHeartbeatAtMs() + } + } + return 0, 0 +} + func protoSeatByUser(snapshot *roomv1.RoomSnapshot, userID int64) *roomv1.SeatState { if snapshot == nil { return nil diff --git a/services/room-service/internal/room/service/mic_test.go b/services/room-service/internal/room/service/mic_test.go new file mode 100644 index 00000000..fc4c962e --- /dev/null +++ b/services/room-service/internal/room/service/mic_test.go @@ -0,0 +1,112 @@ +package service_test + +import ( + "context" + "testing" + "time" + + roomv1 "hyapp.local/api/proto/room/v1" + "hyapp/services/room-service/internal/testutil/mysqltest" +) + +func TestMicHeartbeatRefreshesPublishingSessionAndPresence(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} + svc := newTreasureTestService(t, repository, &treasureTestWallet{}, now) + + roomID := "room-mic-heartbeat" + ownerID := int64(8601) + speakerID := int64(8602) + createTreasureRoom(t, ctx, svc, roomID, ownerID, 9101) + joinTreasureRoom(t, ctx, svc, roomID, speakerID) + + upResp, err := svc.MicUp(ctx, &roomv1.MicUpRequest{ + Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-up"), + SeatNo: 2, + }) + if err != nil { + t.Fatalf("mic up failed: %v", err) + } + now.now = now.now.Add(500 * time.Millisecond) + confirmResp, err := svc.ConfirmMicPublishing(ctx, &roomv1.ConfirmMicPublishingRequest{ + Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-confirm"), + MicSessionId: upResp.GetMicSessionId(), + RoomVersion: upResp.GetRoom().GetVersion(), + EventTimeMs: now.Now().UnixMilli(), + Source: "client", + }) + if err != nil { + t.Fatalf("confirm mic publishing failed: %v", err) + } + confirmedSeat := seatByNo(confirmResp.GetRoom(), 2) + if confirmedSeat == nil || confirmedSeat.GetPublishState() != "publishing" || confirmedSeat.GetMicHeartbeatAtMs() == 0 { + t.Fatalf("publish confirmation must initialize heartbeat: %+v", confirmedSeat) + } + + now.now = now.now.Add(3 * time.Second) + heartbeatAtMS := now.Now().UnixMilli() + heartbeatResp, err := svc.MicHeartbeat(ctx, &roomv1.MicHeartbeatRequest{ + Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-refresh"), + MicSessionId: upResp.GetMicSessionId(), + }) + if err != nil { + t.Fatalf("mic heartbeat failed: %v", err) + } + if heartbeatResp.GetSeatNo() != 2 || heartbeatResp.GetMicHeartbeatAtMs() != heartbeatAtMS { + t.Fatalf("heartbeat response mismatch: %+v want_at=%d", heartbeatResp, heartbeatAtMS) + } + seat := seatByNo(heartbeatResp.GetRoom(), 2) + if seat == nil || seat.GetMicHeartbeatAtMs() != heartbeatAtMS { + t.Fatalf("seat heartbeat must be visible in snapshot: %+v", seat) + } + user := onlineUserByID(heartbeatResp.GetRoom(), speakerID) + if user == nil || user.GetLastSeenAtMs() != heartbeatAtMS { + t.Fatalf("mic heartbeat must refresh room presence: %+v", user) + } +} + +func TestMicHeartbeatRejectsPendingSession(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} + svc := newTreasureTestService(t, repository, &treasureTestWallet{}, now) + + roomID := "room-mic-heartbeat-pending" + ownerID := int64(8701) + speakerID := int64(8702) + createTreasureRoom(t, ctx, svc, roomID, ownerID, 9101) + joinTreasureRoom(t, ctx, svc, roomID, speakerID) + + upResp, err := svc.MicUp(ctx, &roomv1.MicUpRequest{ + Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-pending-up"), + SeatNo: 1, + }) + if err != nil { + t.Fatalf("mic up failed: %v", err) + } + if _, err := svc.MicHeartbeat(ctx, &roomv1.MicHeartbeatRequest{ + Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-pending-refresh"), + MicSessionId: upResp.GetMicSessionId(), + }); err == nil { + t.Fatalf("pending_publish session must not accept mic heartbeat before publish confirmation") + } +} + +func seatByNo(snapshot *roomv1.RoomSnapshot, seatNo int32) *roomv1.SeatState { + for _, seat := range snapshot.GetMicSeats() { + if seat.GetSeatNo() == seatNo { + return seat + } + } + return nil +} + +func onlineUserByID(snapshot *roomv1.RoomSnapshot, userID int64) *roomv1.RoomUser { + for _, user := range snapshot.GetOnlineUsers() { + if user.GetUserId() == userID { + return user + } + } + return nil +} diff --git a/services/room-service/internal/room/service/presence.go b/services/room-service/internal/room/service/presence.go index 637741df..dead1003 100644 --- a/services/room-service/internal/room/service/presence.go +++ b/services/room-service/internal/room/service/presence.go @@ -49,6 +49,11 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r delete(current.BanUsers, cmd.ActorUserID()) } + if current.RoomPasswordHash != "" && current.OwnerUserID != cmd.ActorUserID() && !roomPasswordMatches(current.RoomPasswordHash, password) { + // 锁房校验必须覆盖新进房和已有 presence 的重连;否则房主改密后,悬浮保活或 stale 未清理用户会绕过最新密码。 + return mutationResult{}, nil, xerr.New(xerr.PermissionDenied, "room password is invalid") + } + if existing, exists := current.OnlineUsers[cmd.ActorUserID()]; exists { // 重复 JoinRoom 表示重连或刷新业务 presence,只更新 last_seen,不重复发进房系统消息。 existing.LastSeenAtMS = now.UnixMilli() @@ -60,11 +65,6 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r user: findProtoUser(snapshot, cmd.ActorUserID()), }, nil, nil } - if current.RoomPasswordHash != "" && current.OwnerUserID != cmd.ActorUserID() && !roomPasswordMatches(current.RoomPasswordHash, password) { - // 锁房只拦截新进入的非房主用户;已在房内的用户和 owner 不因为锁房状态重设被挤出。 - return mutationResult{}, nil, xerr.New(xerr.PermissionDenied, "room password is invalid") - } - current.OnlineUsers[cmd.ActorUserID()] = &state.RoomUserState{ UserID: cmd.ActorUserID(), Role: cmd.Role, diff --git a/services/room-service/internal/room/service/recovery.go b/services/room-service/internal/room/service/recovery.go index 67fb4e84..accf688d 100644 --- a/services/room-service/internal/room/service/recovery.go +++ b/services/room-service/internal/room/service/recovery.go @@ -228,6 +228,22 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64) index := current.SeatIndex(seat.SeatNo) current.MicSeats[index].PublishState = state.MicPublishPublishing current.MicSeats[index].LastPublishEventTimeMS = typed.EventTimeMS + current.MicSeats[index].MicHeartbeatAtMS = typed.SentAtMS + current.Version++ + case *command.MicHeartbeat: + seat, exists := current.SeatByUser(typed.TargetUserID) + if !exists { + return fmt.Errorf("mic_heartbeat replay target is not on seat: %d", typed.TargetUserID) + } + if seat.MicSessionID != typed.MicSessionID || seat.PublishState != state.MicPublishPublishing { + return fmt.Errorf("mic_heartbeat replay target session is not publishing: %d", typed.TargetUserID) + } + if existing, ok := current.OnlineUsers[typed.TargetUserID]; ok { + // 麦上心跳回放要恢复同步刷新的 presence 时间,避免 snapshot 落后时重启后又被 stale worker 清理。 + existing.LastSeenAtMS = typed.SentAtMS + } + index := current.SeatIndex(seat.SeatNo) + current.MicSeats[index].MicHeartbeatAtMS = typed.SentAtMS current.Version++ case *command.ApplyRTCEvent: switch typed.EventType { diff --git a/services/room-service/internal/room/service/room_lock.go b/services/room-service/internal/room/service/room_lock.go index 30c3501e..1bf8b6a3 100644 --- a/services/room-service/internal/room/service/room_lock.go +++ b/services/room-service/internal/room/service/room_lock.go @@ -9,7 +9,6 @@ import ( "golang.org/x/crypto/bcrypt" roomeventsv1 "hyapp.local/api/proto/events/room/v1" roomv1 "hyapp.local/api/proto/room/v1" - "hyapp/pkg/tencentim" "hyapp/pkg/xerr" "hyapp/services/room-service/internal/room/command" "hyapp/services/room-service/internal/room/outbox" @@ -61,8 +60,9 @@ func (s *Service) SetRoomPassword(ctx context.Context, req *roomv1.SetRoomPasswo current.Version++ currentHash := current.RoomPasswordHash passwordEvent, err := outbox.Build(current.RoomID, "RoomPasswordChanged", current.Version, now, &roomeventsv1.RoomPasswordChanged{ - ActorUserId: cmd.ActorUserID(), - Locked: cmd.Locked, + ActorUserId: cmd.ActorUserID(), + Locked: cmd.Locked, + VisibleRegionId: current.VisibleRegionID, }) if err != nil { return mutationResult{}, nil, err @@ -71,16 +71,6 @@ func (s *Service) SetRoomPassword(ctx context.Context, req *roomv1.SetRoomPasswo return mutationResult{ snapshot: current.ToProto(), roomPasswordHash: ¤tHash, - syncEvent: &tencentim.RoomEvent{ - EventID: passwordEvent.EventID, - RoomID: current.RoomID, - EventType: "room_password_changed", - ActorUserID: cmd.ActorUserID(), - RoomVersion: current.Version, - Attributes: map[string]string{ - "locked": boolString(cmd.Locked), - }, - }, }, []outbox.Record{passwordEvent}, nil }) if err != nil { diff --git a/services/room-service/internal/room/service/rtc_event.go b/services/room-service/internal/room/service/rtc_event.go index 34753b2d..00da11b8 100644 --- a/services/room-service/internal/room/service/rtc_event.go +++ b/services/room-service/internal/room/service/rtc_event.go @@ -107,6 +107,7 @@ func (s *Service) applyRTCAudioStarted(now time.Time, current *state.RoomState, index := current.SeatIndex(seat.SeatNo) current.MicSeats[index].PublishState = state.MicPublishPublishing current.MicSeats[index].LastPublishEventTimeMS = cmd.EventTimeMS + current.MicSeats[index].MicHeartbeatAtMS = now.UnixMilli() current.Version++ seatStatus := current.MicSeats[index].SeatStatus() diff --git a/services/room-service/internal/room/service/service.go b/services/room-service/internal/room/service/service.go index 0a89e6ce..30ddab97 100644 --- a/services/room-service/internal/room/service/service.go +++ b/services/room-service/internal/room/service/service.go @@ -105,6 +105,8 @@ type mutationResult struct { micSessionID string // publishDeadlineMS 是 pending_publish 自动释放的截止时间。 publishDeadlineMS int64 + // micHeartbeatAtMS 是服务端接受当前麦上心跳的时间,只属于麦位活跃探测,不改变时长口径。 + micHeartbeatAtMS int64 // billingReceiptID 是 SendGift 从 wallet-service 得到的账务回执。 billingReceiptID string // roomHeat 是 SendGift 后的房间热度。 diff --git a/services/room-service/internal/room/state/state.go b/services/room-service/internal/room/state/state.go index e17cb9a2..2ef606f9 100644 --- a/services/room-service/internal/room/state/state.go +++ b/services/room-service/internal/room/state/state.go @@ -62,6 +62,8 @@ type MicSeat struct { MicSessionRoomVersion int64 // LastPublishEventTimeMS 是已接受的最新 RTC/客户端发布事件时间。 LastPublishEventTimeMS int64 + // MicHeartbeatAtMS 是当前 mic_session 最近一次服务端接受麦上心跳的时间;它不参与 RTC 事件新旧判断。 + MicHeartbeatAtMS int64 // MicMuted 是服务端可见的麦克风静音状态,用于同步其他用户 UI。 MicMuted bool } @@ -379,6 +381,7 @@ func (s *RoomState) ToProto() *roomv1.RoomSnapshot { LastPublishEventTimeMs: seat.LastPublishEventTimeMS, MicMuted: seat.MicMuted, SeatStatus: seat.SeatStatus(), + MicHeartbeatAtMs: seat.MicHeartbeatAtMS, }) } @@ -455,6 +458,7 @@ func FromProto(snapshot *roomv1.RoomSnapshot) *RoomState { PublishDeadlineMS: seat.GetPublishDeadlineMs(), MicSessionRoomVersion: seat.GetMicSessionRoomVersion(), LastPublishEventTimeMS: seat.GetLastPublishEventTimeMs(), + MicHeartbeatAtMS: seat.GetMicHeartbeatAtMs(), MicMuted: seat.GetMicMuted(), }) } diff --git a/services/room-service/internal/transport/grpc/server.go b/services/room-service/internal/transport/grpc/server.go index 8b26634a..8d5b85d1 100644 --- a/services/room-service/internal/transport/grpc/server.go +++ b/services/room-service/internal/transport/grpc/server.go @@ -235,6 +235,18 @@ func (s *Server) ConfirmMicPublishing(ctx context.Context, req *roomv1.ConfirmMi return mapServiceResult(s.svc.ConfirmMicPublishing(ctx, req)) } +// MicHeartbeat 代理到领域服务。 +func (s *Server) MicHeartbeat(ctx context.Context, req *roomv1.MicHeartbeatRequest) (*roomv1.MicHeartbeatResponse, error) { + // 心跳仍由 Room Cell 串行提交,保证 presence、麦位快照和 command log 同版本。 + ctx = contextWithMetaApp(ctx, req.GetMeta()) + if resp, forwarded, err := forwardCommand(s, ctx, req.GetMeta(), func(callCtx context.Context, client roomv1.RoomCommandServiceClient) (*roomv1.MicHeartbeatResponse, error) { + return client.MicHeartbeat(callCtx, req) + }); forwarded { + return resp, err + } + return mapServiceResult(s.svc.MicHeartbeat(ctx, req)) +} + // SetMicMute 代理到领域服务。 func (s *Server) SetMicMute(ctx context.Context, req *roomv1.SetMicMuteRequest) (*roomv1.SetMicMuteResponse, error) { // 服务端可见静音态必须经 Room Cell 提交,确保其他用户 UI 和系统消息一致。 diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index 1666e720..f97737bc 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -227,6 +227,17 @@ type HostSalaryPolicyLevel struct { SortOrder int } +// HostSalaryProgress 是主播当前工资周期的钻石累计投影,用于 H5 按工资政策计算距离下一等级的差值。 +type HostSalaryProgress struct { + HostUserID int64 + CycleKey string + RegionID int64 + AgencyOwnerUserID int64 + TotalDiamonds int64 + GiftDiamondTotal int64 + UpdatedAtMS int64 +} + // CoinSellerTransferCommand 是币商给玩家转普通金币的账务命令。 type CoinSellerTransferCommand struct { AppCode string diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index fe0b10f7..ee5ba83d 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -21,6 +21,8 @@ type Repository interface { DebitGift(ctx context.Context, command ledger.DebitGiftCommand) (ledger.Receipt, error) BatchDebitGift(ctx context.Context, command ledger.BatchDebitGiftCommand) (ledger.BatchGiftReceipt, error) GetBalances(ctx context.Context, userID int64, assetTypes []string) ([]ledger.AssetBalance, error) + GetActiveHostSalaryPolicy(ctx context.Context, regionID int64, settlementMode string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) + GetHostSalaryProgress(ctx context.Context, userID int64, cycleKey string) (ledger.HostSalaryProgress, error) AdminCreditAsset(ctx context.Context, command ledger.AdminCreditAssetCommand) (ledger.AssetBalance, string, error) AdminCreditCoinSellerStock(ctx context.Context, command ledger.CoinSellerStockCreditCommand) (ledger.CoinSellerStockCreditReceipt, error) TransferCoinFromSeller(ctx context.Context, command ledger.CoinSellerTransferCommand) (ledger.CoinSellerTransferReceipt, error) @@ -238,6 +240,54 @@ func (s *Service) GetBalances(ctx context.Context, userID int64, assetTypes []st return s.repository.GetBalances(ctx, userID, normalized) } +// GetActiveHostSalaryPolicy 读取主播所在区域当前生效的工资政策,返回的 policy 与工资结算使用同一张 runtime 表。 +func (s *Service) GetActiveHostSalaryPolicy(ctx context.Context, appCode string, regionID int64, settlementMode string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) { + if regionID <= 0 { + return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "region_id is required") + } + if s.repository == nil { + return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + settlementMode = strings.TrimSpace(settlementMode) + if settlementMode != "" && settlementMode != ledger.HostSalarySettlementModeDaily && settlementMode != ledger.HostSalarySettlementModeHalfMonth { + return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_mode is invalid") + } + triggerMode = strings.TrimSpace(triggerMode) + if triggerMode == "" { + triggerMode = ledger.HostSalarySettlementTriggerAutomatic + } + if triggerMode != ledger.HostSalarySettlementTriggerAutomatic && triggerMode != ledger.HostSalarySettlementTriggerManual { + return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_trigger_mode is invalid") + } + if nowMs <= 0 { + nowMs = s.now().UTC().UnixMilli() + } + appCode = appcode.Normalize(appCode) + ctx = appcode.WithContext(ctx, appCode) + // 不传 settlement_mode 时按同区域最新 active policy 返回,用于 H5 展示平台当前规则。 + return s.repository.GetActiveHostSalaryPolicy(ctx, regionID, settlementMode, triggerMode, nowMs) +} + +// GetHostSalaryProgress 返回主播当前工资周期的钻石累计;没有收礼账户时返回 0,避免 H5 用其他等级系统兜底导致进度口径错误。 +func (s *Service) GetHostSalaryProgress(ctx context.Context, appCode string, userID int64, cycleKey string, nowMs int64) (ledger.HostSalaryProgress, error) { + if userID <= 0 { + return ledger.HostSalaryProgress{}, xerr.New(xerr.InvalidArgument, "host_user_id is required") + } + if s.repository == nil { + return ledger.HostSalaryProgress{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + if nowMs <= 0 { + nowMs = s.now().UTC().UnixMilli() + } + cycleKey = strings.TrimSpace(cycleKey) + if cycleKey == "" { + cycleKey = hostSalaryCycleKey(nowMs) + } + appCode = appcode.Normalize(appCode) + ctx = appcode.WithContext(ctx, appCode) + return s.repository.GetHostSalaryProgress(ctx, userID, cycleKey) +} + // AdminCreditAsset 执行后台手动调账;amount 为正数入账、负数扣账,审计字段必须随交易一起落库。 func (s *Service) AdminCreditAsset(ctx context.Context, command ledger.AdminCreditAssetCommand) (ledger.AssetBalance, string, error) { if command.CommandID == "" || command.TargetUserID <= 0 || command.OperatorUserID <= 0 || command.Amount == 0 { diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 1088748e..f0003116 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -287,6 +287,84 @@ func TestDebitGiftRejectsHostPeriodWithoutRegion(t *testing.T) { } } +// TestGetActiveHostSalaryPolicyReadsRuntimePolicy 验证 H5 展示读取的是工资结算 runtime 表里的生效政策和档位。 +func TestGetActiveHostSalaryPolicyReadsRuntimePolicy(t *testing.T) { + repository := mysqltest.NewRepository(t) + nowMs := time.Now().UnixMilli() + repository.SetHostSalaryPolicy(ledger.HostSalaryPolicy{ + PolicyID: 901, + Name: "current host policy", + RegionID: 8801, + Status: "active", + SettlementMode: ledger.HostSalarySettlementModeHalfMonth, + SettlementTriggerMode: ledger.HostSalarySettlementTriggerAutomatic, + GiftCoinToDiamondRatio: "1.0000", + ResidualDiamondToUSDRate: "0.0100", + EffectiveFromMs: nowMs - 1000, + EffectiveToMs: 0, + Levels: []ledger.HostSalaryPolicyLevel{ + {LevelNo: 1, RequiredDiamonds: 1000, HostSalaryUSDMinor: 1500, HostCoinReward: 200, AgencySalaryUSDMinor: 300, SortOrder: 1}, + {LevelNo: 2, RequiredDiamonds: 3000, HostSalaryUSDMinor: 4500, HostCoinReward: 500, AgencySalaryUSDMinor: 900, SortOrder: 2}, + }, + }) + svc := walletservice.New(repository) + + policy, found, err := svc.GetActiveHostSalaryPolicy(context.Background(), "lalu", 8801, "", ledger.HostSalarySettlementTriggerAutomatic, nowMs) + if err != nil { + t.Fatalf("GetActiveHostSalaryPolicy failed: %v", err) + } + if !found { + t.Fatal("expected active host salary policy") + } + if policy.PolicyID != 901 || policy.Name != "current host policy" || policy.SettlementMode != ledger.HostSalarySettlementModeHalfMonth || policy.RegionID != 8801 { + t.Fatalf("policy mismatch: %+v", policy) + } + if len(policy.Levels) != 2 || policy.Levels[1].LevelNo != 2 || policy.Levels[1].HostSalaryUSDMinor != 4500 || policy.Levels[1].AgencySalaryUSDMinor != 900 { + t.Fatalf("policy levels mismatch: %+v", policy.Levels) + } +} + +// TestGetHostSalaryProgressReadsCurrentCycleDiamonds 验证 H5 等级进度读取工资周期钻石账户,查询不到时保持 0 累计。 +func TestGetHostSalaryProgressReadsCurrentCycleDiamonds(t *testing.T) { + repository := mysqltest.NewRepository(t) + repository.SetBalance(10001, 100) + repository.SetGiftPrice("rose", "salary-progress", 200, 10, 10) + svc := walletservice.New(repository) + + receipt, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ + CommandID: "cmd-salary-progress", + RoomID: "room-1", + SenderUserID: 10001, + TargetUserID: 13002, + GiftID: "rose", + GiftCount: 1, + PriceVersion: "salary-progress", + SenderRegionID: 8801, + TargetIsHost: true, + TargetHostRegionID: 8801, + TargetAgencyOwnerUserID: 30001, + }) + if err != nil { + t.Fatalf("salary gift failed: %v", err) + } + + progress, err := svc.GetHostSalaryProgress(context.Background(), "lalu", 13002, receipt.HostPeriodCycleKey, 0) + if err != nil { + t.Fatalf("GetHostSalaryProgress failed: %v", err) + } + if progress.HostUserID != 13002 || progress.CycleKey != receipt.HostPeriodCycleKey || progress.RegionID != 8801 || progress.AgencyOwnerUserID != 30001 || progress.TotalDiamonds != 14 || progress.GiftDiamondTotal != 14 { + t.Fatalf("host salary progress mismatch: %+v", progress) + } + + missing, err := svc.GetHostSalaryProgress(context.Background(), "lalu", 99999, "2026-06", 0) + if err != nil { + t.Fatalf("GetHostSalaryProgress missing account failed: %v", err) + } + if missing.HostUserID != 99999 || missing.CycleKey != "2026-06" || missing.TotalDiamonds != 0 { + t.Fatalf("missing progress must return zero account: %+v", missing) + } +} + // TestHostSalarySettlementCreditsIncrementalRewards 走真实送礼入钻石账户后,验证日结只发放等级累计差额。 func TestHostSalarySettlementCreditsIncrementalRewards(t *testing.T) { repository := mysqltest.NewRepository(t) diff --git a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go index ff3603ff..626ee295 100644 --- a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go +++ b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go @@ -68,6 +68,11 @@ type hostSalarySettlementMetadata struct { ProcessedAtMS int64 `json:"processed_at_ms"` } +type hostSalaryPolicyQuerier interface { + QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row + QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error) +} + // ProcessHostSalarySettlementBatch 按周期账户扫描并结算主播美元、主播金币奖励和代理美元工资。 // 每个主播单独开事务,避免某个主播配置异常拖垮整个批次,也让 cron-service 可按 has_more 继续拉下一页。 func (r *Repository) ProcessHostSalarySettlementBatch(ctx context.Context, command ledger.HostSalarySettlementBatchCommand) (ledger.HostSalarySettlementBatchResult, error) { @@ -345,13 +350,53 @@ func (r *Repository) lockHostSalaryProgress(ctx context.Context, tx *sql.Tx, use return progress, nil } +// GetActiveHostSalaryPolicy 返回当前 app、区域和触发模式下正在生效的主播工资政策;这是 H5 展示平台政策的只读入口。 +func (r *Repository) GetActiveHostSalaryPolicy(ctx context.Context, regionID int64, settlementMode string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) { + if r == nil || r.db == nil { + return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + return r.queryActiveHostSalaryPolicy(ctx, r.db, regionID, settlementMode, triggerMode, nowMs) +} + +// GetHostSalaryProgress 读取主播工资周期钻石账户;没有任何收礼时返回空累计,前端据此展示距离首档还差多少钻石。 +func (r *Repository) GetHostSalaryProgress(ctx context.Context, userID int64, cycleKey string) (ledger.HostSalaryProgress, error) { + if r == nil || r.db == nil { + return ledger.HostSalaryProgress{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + progress := ledger.HostSalaryProgress{ + HostUserID: userID, + CycleKey: cycleKey, + } + row := r.db.QueryRowContext(ctx, ` + SELECT user_id, cycle_key, region_id, agency_owner_user_id, total_diamonds, + gift_diamond_total, updated_at_ms + FROM host_period_diamond_accounts + WHERE app_code = ? AND user_id = ? AND cycle_key = ?`, + appcode.FromContext(ctx), userID, cycleKey) + if err := row.Scan(&progress.HostUserID, &progress.CycleKey, &progress.RegionID, &progress.AgencyOwnerUserID, &progress.TotalDiamonds, &progress.GiftDiamondTotal, &progress.UpdatedAtMS); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return progress, nil + } + return ledger.HostSalaryProgress{}, err + } + return progress, nil +} + func (r *Repository) resolveHostSalaryPolicy(ctx context.Context, tx *sql.Tx, regionID int64, settlementType string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) { + settlementMode := "" + if settlementType != ledger.HostSalarySettlementTypeMonthEnd { + settlementMode = settlementType + } + return r.queryActiveHostSalaryPolicy(ctx, tx, regionID, settlementMode, triggerMode, nowMs) +} + +func (r *Repository) queryActiveHostSalaryPolicy(ctx context.Context, q hostSalaryPolicyQuerier, regionID int64, settlementMode string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) { modeClause := "" args := []any{appcode.FromContext(ctx), regionID, nowMs, nowMs, triggerMode} - if settlementType != ledger.HostSalarySettlementTypeMonthEnd { - // 人工/自动触发模式也参与政策匹配,避免自动任务误结算只允许手动处理的政策。 + if strings.TrimSpace(settlementMode) != "" { + // 结算任务必须精确匹配结算模式;H5 展示不传模式时只按区域和触发模式取最新生效政策。 modeClause = "AND settlement_mode = ?" - args = append(args, settlementType) + args = append(args, settlementMode) } query := fmt.Sprintf(` SELECT policy_id, name, region_id, status, settlement_mode, settlement_trigger_mode, @@ -369,14 +414,14 @@ func (r *Repository) resolveHostSalaryPolicy(ctx context.Context, tx *sql.Tx, re ORDER BY effective_from_ms DESC, policy_id DESC LIMIT 1`, modeClause) var policy ledger.HostSalaryPolicy - err := tx.QueryRowContext(ctx, query, args...).Scan(&policy.PolicyID, &policy.Name, &policy.RegionID, &policy.Status, &policy.SettlementMode, &policy.SettlementTriggerMode, &policy.GiftCoinToDiamondRatio, &policy.ResidualDiamondToUSDRate, &policy.EffectiveFromMs, &policy.EffectiveToMs) + err := q.QueryRowContext(ctx, query, args...).Scan(&policy.PolicyID, &policy.Name, &policy.RegionID, &policy.Status, &policy.SettlementMode, &policy.SettlementTriggerMode, &policy.GiftCoinToDiamondRatio, &policy.ResidualDiamondToUSDRate, &policy.EffectiveFromMs, &policy.EffectiveToMs) if err != nil { if errors.Is(err, sql.ErrNoRows) { return ledger.HostSalaryPolicy{}, false, nil } return ledger.HostSalaryPolicy{}, false, err } - levels, err := r.listHostSalaryPolicyLevels(ctx, tx, policy.PolicyID) + levels, err := r.listHostSalaryPolicyLevels(ctx, q, policy.PolicyID) if err != nil { return ledger.HostSalaryPolicy{}, false, err } @@ -384,9 +429,9 @@ func (r *Repository) resolveHostSalaryPolicy(ctx context.Context, tx *sql.Tx, re return policy, true, nil } -func (r *Repository) listHostSalaryPolicyLevels(ctx context.Context, tx *sql.Tx, policyID uint64) ([]ledger.HostSalaryPolicyLevel, error) { +func (r *Repository) listHostSalaryPolicyLevels(ctx context.Context, q hostSalaryPolicyQuerier, policyID uint64) ([]ledger.HostSalaryPolicyLevel, error) { // 等级必须按 required_diamonds 升序返回,highestHostSalaryLevel 依赖这个顺序找到最高已达档位。 - rows, err := tx.QueryContext(ctx, ` + rows, err := q.QueryContext(ctx, ` SELECT level_no, required_diamonds, host_salary_usd_minor, host_coin_reward, agency_salary_usd_minor, status, sort_order FROM host_agency_salary_policy_levels diff --git a/services/wallet-service/internal/transport/grpc/server.go b/services/wallet-service/internal/transport/grpc/server.go index 11e775ba..ba597bec 100644 --- a/services/wallet-service/internal/transport/grpc/server.go +++ b/services/wallet-service/internal/transport/grpc/server.go @@ -130,6 +130,74 @@ func (s *Server) GetBalances(ctx context.Context, req *walletv1.GetBalancesReque return response, nil } +// GetActiveHostSalaryPolicy 读取当前生效的主播工资政策,供 gateway 按当前主播区域展示平台规则。 +func (s *Server) GetActiveHostSalaryPolicy(ctx context.Context, req *walletv1.GetActiveHostSalaryPolicyRequest) (*walletv1.GetActiveHostSalaryPolicyResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + policy, found, err := s.svc.GetActiveHostSalaryPolicy(ctx, req.GetAppCode(), req.GetRegionId(), req.GetSettlementMode(), req.GetSettlementTriggerMode(), req.GetNowMs()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + response := &walletv1.GetActiveHostSalaryPolicyResponse{Found: found} + if found { + response.Policy = hostSalaryPolicyToProto(policy) + } + return response, nil +} + +// GetHostSalaryProgress 读取主播当前工资周期钻石累计,gateway 用它计算工资政策等级进度。 +func (s *Server) GetHostSalaryProgress(ctx context.Context, req *walletv1.GetHostSalaryProgressRequest) (*walletv1.GetHostSalaryProgressResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + progress, err := s.svc.GetHostSalaryProgress(ctx, req.GetAppCode(), req.GetHostUserId(), req.GetCycleKey(), req.GetNowMs()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.GetHostSalaryProgressResponse{Progress: hostSalaryProgressToProto(progress)}, nil +} + +func hostSalaryProgressToProto(progress ledger.HostSalaryProgress) *walletv1.HostSalaryProgress { + return &walletv1.HostSalaryProgress{ + HostUserId: progress.HostUserID, + CycleKey: progress.CycleKey, + RegionId: progress.RegionID, + AgencyOwnerUserId: progress.AgencyOwnerUserID, + TotalDiamonds: progress.TotalDiamonds, + GiftDiamondTotal: progress.GiftDiamondTotal, + UpdatedAtMs: progress.UpdatedAtMS, + } +} + +func hostSalaryPolicyToProto(policy ledger.HostSalaryPolicy) *walletv1.HostSalaryPolicy { + levels := make([]*walletv1.HostSalaryPolicyLevel, 0, len(policy.Levels)) + for _, level := range policy.Levels { + levels = append(levels, hostSalaryPolicyLevelToProto(level)) + } + return &walletv1.HostSalaryPolicy{ + PolicyId: policy.PolicyID, + Name: policy.Name, + RegionId: policy.RegionID, + Status: policy.Status, + SettlementMode: policy.SettlementMode, + SettlementTriggerMode: policy.SettlementTriggerMode, + GiftCoinToDiamondRatio: policy.GiftCoinToDiamondRatio, + ResidualDiamondToUsdRate: policy.ResidualDiamondToUSDRate, + EffectiveFromMs: policy.EffectiveFromMs, + EffectiveToMs: policy.EffectiveToMs, + Levels: levels, + } +} + +func hostSalaryPolicyLevelToProto(level ledger.HostSalaryPolicyLevel) *walletv1.HostSalaryPolicyLevel { + return &walletv1.HostSalaryPolicyLevel{ + LevelNo: int32(level.LevelNo), + RequiredDiamonds: level.RequiredDiamonds, + HostSalaryUsdMinor: level.HostSalaryUSDMinor, + HostCoinReward: level.HostCoinReward, + AgencySalaryUsdMinor: level.AgencySalaryUSDMinor, + Status: level.Status, + SortOrder: int32(level.SortOrder), + } +} + // GetWalletOverview 返回钱包首页摘要,供我的页和钱包二级页复用。 func (s *Server) GetWalletOverview(ctx context.Context, req *walletv1.GetWalletOverviewRequest) (*walletv1.GetWalletOverviewResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) From 0fdaec9ef984825fc4868db41b69eaab9493de68 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 19:28:56 +0800 Subject: [PATCH 08/28] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mysql/initdb/001_statistics_service.sql | 12 ++ .../statistics-service/internal/app/app.go | 1 + .../internal/app/local_flow_test.go | 7 ++ .../internal/storage/mysql/query.go | 107 +++++++++++++----- .../internal/storage/mysql/repository.go | 44 ++++++- 5 files changed, 140 insertions(+), 31 deletions(-) diff --git a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql index 34e69490..c825d46d 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -81,6 +81,18 @@ CREATE TABLE IF NOT EXISTS stat_lucky_gift_day_payers ( KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物日付费去重表'; +CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country ( + app_code VARCHAR(32) NOT NULL COMMENT '应用编码', + stat_day DATE NOT NULL COMMENT 'UTC 统计日', + country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家或区域维度 ID,0 表示未知或全局', + pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', + turnover_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物流水金币', + payout_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物返奖金币', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, stat_day, country_id, pool_id), + KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物奖池国家日统计聚合表'; + CREATE TABLE IF NOT EXISTS stat_game_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 97cdb79a..8c6f5f21 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -257,6 +257,7 @@ func luckyGiftRewardEvent(body []byte) (mysqlstorage.LuckyGiftRewardEvent, bool, EventType: message.EventType, UserID: firstNonZeroInt64(mysqlstorage.Int64(payload, "user_id"), message.UserID), CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "visible_region_id"), mysqlstorage.Int64(payload, "region_id"), mysqlstorage.Int64(payload, "target_region_id")), + PoolID: mysqlstorage.String(payload, "pool_id"), Amount: mysqlstorage.Int64(payload, "amount"), OccurredAtMS: message.OccurredAtMS, }, true, nil diff --git a/services/statistics-service/internal/app/local_flow_test.go b/services/statistics-service/internal/app/local_flow_test.go index ef679489..b0d61c42 100644 --- a/services/statistics-service/internal/app/local_flow_test.go +++ b/services/statistics-service/internal/app/local_flow_test.go @@ -135,6 +135,13 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { if overview.LuckyGiftTurnover != 1_000 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 700 || overview.LuckyGiftPayers != 1 { t.Fatalf("lucky gift metrics mismatch: %+v", overview) } + if len(overview.LuckyGiftPools) != 1 { + t.Fatalf("lucky gift pool breakdown missing: %+v", overview.LuckyGiftPools) + } + pool := overview.LuckyGiftPools[0] + if pool.PoolID != "lucky_100" || pool.TurnoverCoin != 1_000 || pool.PayoutCoin != 300 || pool.ProfitCoin != 700 { + t.Fatalf("lucky gift pool metrics mismatch: %+v", pool) + } if overview.GameTurnover != 700 || overview.GamePayout != 200 || overview.GameProfit != 500 || overview.GamePlayers != 1 { t.Fatalf("game metrics mismatch: %+v", overview) } diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index 59f81a44..e208a631 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -16,36 +16,37 @@ type OverviewQuery struct { } type Overview struct { - AppCode string `json:"app_code"` - StartMS int64 `json:"start_ms"` - EndMS int64 `json:"end_ms"` - CountryID int64 `json:"country_id"` - NewUsers int64 `json:"new_users"` - ActiveUsers int64 `json:"active_users"` - PaidUsers int64 `json:"paid_users"` - RechargeUSDMinor int64 `json:"recharge_usd_minor"` - NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` - CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` - MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` - GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` - GiftCoinSpent int64 `json:"gift_coin_spent"` - LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` - LuckyGiftPayout int64 `json:"lucky_gift_payout"` - LuckyGiftPayers int64 `json:"lucky_gift_payers"` - LuckyGiftProfit int64 `json:"lucky_gift_profit"` - LuckyGiftPayoutRate float64 `json:"lucky_gift_payout_rate"` - LuckyGiftProfitRate float64 `json:"lucky_gift_profit_rate"` - GameTurnover int64 `json:"game_turnover"` - GamePayout int64 `json:"game_payout"` - GameRefund int64 `json:"game_refund"` - GamePlayers int64 `json:"game_players"` - GameProfit int64 `json:"game_profit"` - GameProfitRate float64 `json:"game_profit_rate"` - ARPUUSDMinor int64 `json:"arpu_usd_minor"` - ARPPUUSDMinor int64 `json:"arppu_usd_minor"` - UPValueUSDMinor int64 `json:"up_value_usd_minor"` - Retention Retention `json:"retention"` - GameRanking []GameRank `json:"game_ranking"` + AppCode string `json:"app_code"` + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` + CountryID int64 `json:"country_id"` + NewUsers int64 `json:"new_users"` + ActiveUsers int64 `json:"active_users"` + PaidUsers int64 `json:"paid_users"` + RechargeUSDMinor int64 `json:"recharge_usd_minor"` + NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` + CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` + MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` + GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` + GiftCoinSpent int64 `json:"gift_coin_spent"` + LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` + LuckyGiftPayout int64 `json:"lucky_gift_payout"` + LuckyGiftPayers int64 `json:"lucky_gift_payers"` + LuckyGiftProfit int64 `json:"lucky_gift_profit"` + LuckyGiftPayoutRate float64 `json:"lucky_gift_payout_rate"` + LuckyGiftProfitRate float64 `json:"lucky_gift_profit_rate"` + GameTurnover int64 `json:"game_turnover"` + GamePayout int64 `json:"game_payout"` + GameRefund int64 `json:"game_refund"` + GamePlayers int64 `json:"game_players"` + GameProfit int64 `json:"game_profit"` + GameProfitRate float64 `json:"game_profit_rate"` + ARPUUSDMinor int64 `json:"arpu_usd_minor"` + ARPPUUSDMinor int64 `json:"arppu_usd_minor"` + UPValueUSDMinor int64 `json:"up_value_usd_minor"` + Retention Retention `json:"retention"` + GameRanking []GameRank `json:"game_ranking"` + LuckyGiftPools []LuckyGiftPoolStat `json:"lucky_gift_pools"` } type Retention struct { @@ -69,6 +70,15 @@ type GameRank struct { ProfitRate float64 `json:"profit_rate"` } +type LuckyGiftPoolStat struct { + PoolID string `json:"pool_id"` + TurnoverCoin int64 `json:"turnover_coin"` + PayoutCoin int64 `json:"payout_coin"` + ProfitCoin int64 `json:"profit_coin"` + PayoutRate float64 `json:"payout_rate"` + ProfitRate float64 `json:"profit_rate"` +} + func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Overview, error) { app := appcode.Normalize(query.AppCode) if app == "" { @@ -115,6 +125,12 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov return Overview{}, err } overview.GameRanking = ranking + // Pool 明细和顶部汇总来自同一个统计窗口;Databi 用它来下钻展示每个 pool_id 的流水、返奖和利润。 + pools, err := r.queryLuckyGiftPools(ctx, app, startDay, endDay, query.CountryID) + if err != nil { + return Overview{}, err + } + overview.LuckyGiftPools = pools return overview, nil } @@ -174,6 +190,37 @@ func (r *Repository) queryGameRanking(ctx context.Context, app, startDay, endDay return out, rows.Err() } +func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, endDay string, countryID int64) ([]LuckyGiftPoolStat, error) { + args := []any{app, startDay, endDay} + filter := "" + if countryID > 0 { + filter = " AND country_id = ?" + args = append(args, countryID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT pool_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0) + FROM stat_lucky_gift_pool_day_country + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+filter+` + GROUP BY pool_id + ORDER BY COALESCE(SUM(turnover_coin),0) DESC, pool_id ASC`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + out := []LuckyGiftPoolStat{} + for rows.Next() { + var item LuckyGiftPoolStat + if err := rows.Scan(&item.PoolID, &item.TurnoverCoin, &item.PayoutCoin); err != nil { + return nil, err + } + item.ProfitCoin = item.TurnoverCoin - item.PayoutCoin + item.PayoutRate = ratio(item.PayoutCoin, item.TurnoverCoin) + item.ProfitRate = ratio(item.ProfitCoin, item.TurnoverCoin) + out = append(out, item) + } + return out, rows.Err() +} + func normalizeRange(startMS, endMS int64) (int64, int64) { if startMS <= 0 { now := time.Now().UTC() diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index f7025333..6bb4231a 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -102,6 +102,13 @@ func (r *Repository) Migrate(ctx context.Context) error { PRIMARY KEY (app_code, stat_day, user_id), KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + `CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country ( + app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + pool_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, payout_coin BIGINT NOT NULL DEFAULT 0, + updated_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, stat_day, country_id, pool_id), + KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_game_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, @@ -171,6 +178,7 @@ type LuckyGiftRewardEvent struct { EventType string UserID int64 CountryID int64 + PoolID string Amount int64 OccurredAtMS int64 } @@ -268,7 +276,8 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e return err } luckyTurnover, luckyPayers := int64(0), int64(0) - if strings.TrimSpace(event.PoolID) != "" { + poolID := strings.TrimSpace(event.PoolID) + if poolID != "" { luckyTurnover = event.GiftValue affected, err := insertUnique(ctx, tx, ` INSERT IGNORE INTO stat_lucky_gift_day_payers (app_code, stat_day, country_id, user_id, first_paid_at_ms) @@ -278,6 +287,17 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e return err } luckyPayers = affected + // Pool 明细是 Databi 点击下钻的真实口径:每笔带 pool_id 的幸运礼物送礼先按 UTC 日、国家和奖池累加流水,返奖事件稍后用相同维度补齐 payout。 + if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, poolID, nowMS); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE stat_lucky_gift_pool_day_country + SET turnover_coin = turnover_coin + ?, updated_at_ms = ? + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND pool_id = ? + `, luckyTurnover, nowMS, appcode.Normalize(event.AppCode), day, countryID, poolID); err != nil { + return err + } } _, err := tx.ExecContext(ctx, ` UPDATE stat_app_day_country @@ -296,6 +316,20 @@ func (r *Repository) ConsumeLuckyGiftReward(ctx context.Context, event LuckyGift if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { return err } + poolID := strings.TrimSpace(event.PoolID) + if poolID != "" { + // 钱包返奖事件带回 pool_id 后,按同一 UTC 日和国家写入奖池返奖;利润不落表,查询时用 turnover-payout 实时计算,避免双写漂移。 + if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, poolID, nowMS); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE stat_lucky_gift_pool_day_country + SET payout_coin = payout_coin + ?, updated_at_ms = ? + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND pool_id = ? + `, event.Amount, nowMS, appcode.Normalize(event.AppCode), day, countryID, poolID); err != nil { + return err + } + } _, err := tx.ExecContext(ctx, ` UPDATE stat_app_day_country SET lucky_gift_payout = lucky_gift_payout + ?, updated_at_ms = ? @@ -470,6 +504,14 @@ func ensureGameDay(ctx context.Context, tx *sql.Tx, app string, day string, coun return err } +func ensureLuckyGiftPoolDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, poolID string, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO stat_lucky_gift_pool_day_country (app_code, stat_day, country_id, pool_id, updated_at_ms) + VALUES (?, ?, ?, ?, ?) + `, appcode.Normalize(app), day, countryID, strings.TrimSpace(poolID), nowMS) + return err +} + func insertUnique(ctx context.Context, tx *sql.Tx, query string, args ...any) (int64, error) { result, err := tx.ExecContext(ctx, query, args...) if err != nil { From 6d4648bf8d8c8b2c976e3b1276d24cbf340f3cde Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 20:01:55 +0800 Subject: [PATCH 09/28] =?UTF-8?q?=E5=A2=9E=E5=8A=A0bd=20leader?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/proto/user/v1/host.pb.go | 753 ++++++++++++------ api/proto/user/v1/host.proto | 24 + api/proto/user/v1/host_grpc.pb.go | 76 ++ .../internal/client/user_client.go | 20 + .../transport/http/httproutes/router.go | 10 + .../internal/transport/http/response_test.go | 56 ++ .../http/userapi/bd_leader_center_handler.go | 363 +++++++++ .../transport/http/userapi/handler.go | 5 + .../internal/service/host/commands.go | 18 + .../internal/service/host/service.go | 54 +- .../internal/service/host/service_test.go | 72 +- .../storage/mysql/host/invitations.go | 55 +- .../internal/storage/mysql/host/queries.go | 80 ++ .../internal/transport/grpc/host.go | 48 +- 14 files changed, 1335 insertions(+), 299 deletions(-) create mode 100644 services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index 2f366d19..c54d3b88 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -1916,6 +1916,230 @@ func (x *InviteBDResponse) GetInvitation() *RoleInvitation { return nil } +type ListBDLeaderBDsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + LeaderUserId int64 `protobuf:"varint,2,opt,name=leader_user_id,json=leaderUserId,proto3" json:"leader_user_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDLeaderBDsRequest) Reset() { + *x = ListBDLeaderBDsRequest{} + mi := &file_proto_user_v1_host_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDLeaderBDsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDLeaderBDsRequest) ProtoMessage() {} + +func (x *ListBDLeaderBDsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[21] + 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 ListBDLeaderBDsRequest.ProtoReflect.Descriptor instead. +func (*ListBDLeaderBDsRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{21} +} + +func (x *ListBDLeaderBDsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListBDLeaderBDsRequest) GetLeaderUserId() int64 { + if x != nil { + return x.LeaderUserId + } + return 0 +} + +func (x *ListBDLeaderBDsRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListBDLeaderBDsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListBDLeaderBDsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + BdProfiles []*BDProfile `protobuf:"bytes,1,rep,name=bd_profiles,json=bdProfiles,proto3" json:"bd_profiles,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDLeaderBDsResponse) Reset() { + *x = ListBDLeaderBDsResponse{} + mi := &file_proto_user_v1_host_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDLeaderBDsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDLeaderBDsResponse) ProtoMessage() {} + +func (x *ListBDLeaderBDsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[22] + 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 ListBDLeaderBDsResponse.ProtoReflect.Descriptor instead. +func (*ListBDLeaderBDsResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{22} +} + +func (x *ListBDLeaderBDsResponse) GetBdProfiles() []*BDProfile { + if x != nil { + return x.BdProfiles + } + return nil +} + +type ListBDLeaderAgenciesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + LeaderUserId int64 `protobuf:"varint,2,opt,name=leader_user_id,json=leaderUserId,proto3" json:"leader_user_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDLeaderAgenciesRequest) Reset() { + *x = ListBDLeaderAgenciesRequest{} + mi := &file_proto_user_v1_host_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDLeaderAgenciesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDLeaderAgenciesRequest) ProtoMessage() {} + +func (x *ListBDLeaderAgenciesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[23] + 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 ListBDLeaderAgenciesRequest.ProtoReflect.Descriptor instead. +func (*ListBDLeaderAgenciesRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{23} +} + +func (x *ListBDLeaderAgenciesRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListBDLeaderAgenciesRequest) GetLeaderUserId() int64 { + if x != nil { + return x.LeaderUserId + } + return 0 +} + +func (x *ListBDLeaderAgenciesRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListBDLeaderAgenciesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListBDLeaderAgenciesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Agencies []*Agency `protobuf:"bytes,1,rep,name=agencies,proto3" json:"agencies,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDLeaderAgenciesResponse) Reset() { + *x = ListBDLeaderAgenciesResponse{} + mi := &file_proto_user_v1_host_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDLeaderAgenciesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDLeaderAgenciesResponse) ProtoMessage() {} + +func (x *ListBDLeaderAgenciesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[24] + 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 ListBDLeaderAgenciesResponse.ProtoReflect.Descriptor instead. +func (*ListBDLeaderAgenciesResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{24} +} + +func (x *ListBDLeaderAgenciesResponse) GetAgencies() []*Agency { + if x != nil { + return x.Agencies + } + return nil +} + type ProcessRoleInvitationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` @@ -1930,7 +2154,7 @@ type ProcessRoleInvitationRequest struct { func (x *ProcessRoleInvitationRequest) Reset() { *x = ProcessRoleInvitationRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[21] + mi := &file_proto_user_v1_host_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1942,7 +2166,7 @@ func (x *ProcessRoleInvitationRequest) String() string { func (*ProcessRoleInvitationRequest) ProtoMessage() {} func (x *ProcessRoleInvitationRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[21] + mi := &file_proto_user_v1_host_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1955,7 +2179,7 @@ func (x *ProcessRoleInvitationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProcessRoleInvitationRequest.ProtoReflect.Descriptor instead. func (*ProcessRoleInvitationRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{21} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{25} } func (x *ProcessRoleInvitationRequest) GetMeta() *RequestMeta { @@ -2013,7 +2237,7 @@ type ProcessRoleInvitationResponse struct { func (x *ProcessRoleInvitationResponse) Reset() { *x = ProcessRoleInvitationResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[22] + mi := &file_proto_user_v1_host_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2025,7 +2249,7 @@ func (x *ProcessRoleInvitationResponse) String() string { func (*ProcessRoleInvitationResponse) ProtoMessage() {} func (x *ProcessRoleInvitationResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[22] + mi := &file_proto_user_v1_host_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2038,7 +2262,7 @@ func (x *ProcessRoleInvitationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ProcessRoleInvitationResponse.ProtoReflect.Descriptor instead. func (*ProcessRoleInvitationResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{22} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{26} } func (x *ProcessRoleInvitationResponse) GetInvitation() *RoleInvitation { @@ -2086,7 +2310,7 @@ type GetHostProfileRequest struct { func (x *GetHostProfileRequest) Reset() { *x = GetHostProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[23] + mi := &file_proto_user_v1_host_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2098,7 +2322,7 @@ func (x *GetHostProfileRequest) String() string { func (*GetHostProfileRequest) ProtoMessage() {} func (x *GetHostProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[23] + mi := &file_proto_user_v1_host_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2111,7 +2335,7 @@ func (x *GetHostProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHostProfileRequest.ProtoReflect.Descriptor instead. func (*GetHostProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{23} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{27} } func (x *GetHostProfileRequest) GetMeta() *RequestMeta { @@ -2137,7 +2361,7 @@ type GetHostProfileResponse struct { func (x *GetHostProfileResponse) Reset() { *x = GetHostProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[24] + mi := &file_proto_user_v1_host_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2149,7 +2373,7 @@ func (x *GetHostProfileResponse) String() string { func (*GetHostProfileResponse) ProtoMessage() {} func (x *GetHostProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[24] + mi := &file_proto_user_v1_host_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2162,7 +2386,7 @@ func (x *GetHostProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHostProfileResponse.ProtoReflect.Descriptor instead. func (*GetHostProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{24} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{28} } func (x *GetHostProfileResponse) GetHostProfile() *HostProfile { @@ -2182,7 +2406,7 @@ type GetBDProfileRequest struct { func (x *GetBDProfileRequest) Reset() { *x = GetBDProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[25] + mi := &file_proto_user_v1_host_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2194,7 +2418,7 @@ func (x *GetBDProfileRequest) String() string { func (*GetBDProfileRequest) ProtoMessage() {} func (x *GetBDProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[25] + mi := &file_proto_user_v1_host_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2207,7 +2431,7 @@ func (x *GetBDProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBDProfileRequest.ProtoReflect.Descriptor instead. func (*GetBDProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{25} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{29} } func (x *GetBDProfileRequest) GetMeta() *RequestMeta { @@ -2233,7 +2457,7 @@ type GetBDProfileResponse struct { func (x *GetBDProfileResponse) Reset() { *x = GetBDProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[26] + mi := &file_proto_user_v1_host_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2245,7 +2469,7 @@ func (x *GetBDProfileResponse) String() string { func (*GetBDProfileResponse) ProtoMessage() {} func (x *GetBDProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[26] + mi := &file_proto_user_v1_host_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2258,7 +2482,7 @@ func (x *GetBDProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBDProfileResponse.ProtoReflect.Descriptor instead. func (*GetBDProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{26} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{30} } func (x *GetBDProfileResponse) GetBdProfile() *BDProfile { @@ -2278,7 +2502,7 @@ type GetCoinSellerProfileRequest struct { func (x *GetCoinSellerProfileRequest) Reset() { *x = GetCoinSellerProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[27] + mi := &file_proto_user_v1_host_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2290,7 +2514,7 @@ func (x *GetCoinSellerProfileRequest) String() string { func (*GetCoinSellerProfileRequest) ProtoMessage() {} func (x *GetCoinSellerProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[27] + mi := &file_proto_user_v1_host_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2303,7 +2527,7 @@ func (x *GetCoinSellerProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCoinSellerProfileRequest.ProtoReflect.Descriptor instead. func (*GetCoinSellerProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{27} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{31} } func (x *GetCoinSellerProfileRequest) GetMeta() *RequestMeta { @@ -2329,7 +2553,7 @@ type GetCoinSellerProfileResponse struct { func (x *GetCoinSellerProfileResponse) Reset() { *x = GetCoinSellerProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[28] + mi := &file_proto_user_v1_host_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2341,7 +2565,7 @@ func (x *GetCoinSellerProfileResponse) String() string { func (*GetCoinSellerProfileResponse) ProtoMessage() {} func (x *GetCoinSellerProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[28] + mi := &file_proto_user_v1_host_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2354,7 +2578,7 @@ func (x *GetCoinSellerProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCoinSellerProfileResponse.ProtoReflect.Descriptor instead. func (*GetCoinSellerProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{28} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{32} } func (x *GetCoinSellerProfileResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -2374,7 +2598,7 @@ type ListActiveCoinSellersInMyRegionRequest struct { func (x *ListActiveCoinSellersInMyRegionRequest) Reset() { *x = ListActiveCoinSellersInMyRegionRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[29] + mi := &file_proto_user_v1_host_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2386,7 +2610,7 @@ func (x *ListActiveCoinSellersInMyRegionRequest) String() string { func (*ListActiveCoinSellersInMyRegionRequest) ProtoMessage() {} func (x *ListActiveCoinSellersInMyRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[29] + mi := &file_proto_user_v1_host_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2399,7 +2623,7 @@ func (x *ListActiveCoinSellersInMyRegionRequest) ProtoReflect() protoreflect.Mes // Deprecated: Use ListActiveCoinSellersInMyRegionRequest.ProtoReflect.Descriptor instead. func (*ListActiveCoinSellersInMyRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{29} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{33} } func (x *ListActiveCoinSellersInMyRegionRequest) GetMeta() *RequestMeta { @@ -2425,7 +2649,7 @@ type ListActiveCoinSellersInMyRegionResponse struct { func (x *ListActiveCoinSellersInMyRegionResponse) Reset() { *x = ListActiveCoinSellersInMyRegionResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[30] + mi := &file_proto_user_v1_host_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2437,7 +2661,7 @@ func (x *ListActiveCoinSellersInMyRegionResponse) String() string { func (*ListActiveCoinSellersInMyRegionResponse) ProtoMessage() {} func (x *ListActiveCoinSellersInMyRegionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[30] + mi := &file_proto_user_v1_host_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2450,7 +2674,7 @@ func (x *ListActiveCoinSellersInMyRegionResponse) ProtoReflect() protoreflect.Me // Deprecated: Use ListActiveCoinSellersInMyRegionResponse.ProtoReflect.Descriptor instead. func (*ListActiveCoinSellersInMyRegionResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{30} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{34} } func (x *ListActiveCoinSellersInMyRegionResponse) GetCoinSellers() []*CoinSellerListItem { @@ -2470,7 +2694,7 @@ type GetUserRoleSummaryRequest struct { func (x *GetUserRoleSummaryRequest) Reset() { *x = GetUserRoleSummaryRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[31] + mi := &file_proto_user_v1_host_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2482,7 +2706,7 @@ func (x *GetUserRoleSummaryRequest) String() string { func (*GetUserRoleSummaryRequest) ProtoMessage() {} func (x *GetUserRoleSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[31] + mi := &file_proto_user_v1_host_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2495,7 +2719,7 @@ func (x *GetUserRoleSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserRoleSummaryRequest.ProtoReflect.Descriptor instead. func (*GetUserRoleSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{31} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{35} } func (x *GetUserRoleSummaryRequest) GetMeta() *RequestMeta { @@ -2521,7 +2745,7 @@ type GetUserRoleSummaryResponse struct { func (x *GetUserRoleSummaryResponse) Reset() { *x = GetUserRoleSummaryResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[32] + mi := &file_proto_user_v1_host_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2533,7 +2757,7 @@ func (x *GetUserRoleSummaryResponse) String() string { func (*GetUserRoleSummaryResponse) ProtoMessage() {} func (x *GetUserRoleSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[32] + mi := &file_proto_user_v1_host_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2546,7 +2770,7 @@ func (x *GetUserRoleSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserRoleSummaryResponse.ProtoReflect.Descriptor instead. func (*GetUserRoleSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{32} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{36} } func (x *GetUserRoleSummaryResponse) GetSummary() *UserRoleSummary { @@ -2566,7 +2790,7 @@ type GetAgencyRequest struct { func (x *GetAgencyRequest) Reset() { *x = GetAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[33] + mi := &file_proto_user_v1_host_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2578,7 +2802,7 @@ func (x *GetAgencyRequest) String() string { func (*GetAgencyRequest) ProtoMessage() {} func (x *GetAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[33] + mi := &file_proto_user_v1_host_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2591,7 +2815,7 @@ func (x *GetAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyRequest.ProtoReflect.Descriptor instead. func (*GetAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{33} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{37} } func (x *GetAgencyRequest) GetMeta() *RequestMeta { @@ -2617,7 +2841,7 @@ type GetAgencyResponse struct { func (x *GetAgencyResponse) Reset() { *x = GetAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[34] + mi := &file_proto_user_v1_host_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2629,7 +2853,7 @@ func (x *GetAgencyResponse) String() string { func (*GetAgencyResponse) ProtoMessage() {} func (x *GetAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[34] + mi := &file_proto_user_v1_host_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2642,7 +2866,7 @@ func (x *GetAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyResponse.ProtoReflect.Descriptor instead. func (*GetAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{34} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{38} } func (x *GetAgencyResponse) GetAgency() *Agency { @@ -2663,7 +2887,7 @@ type CheckBusinessCapabilityRequest struct { func (x *CheckBusinessCapabilityRequest) Reset() { *x = CheckBusinessCapabilityRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[35] + mi := &file_proto_user_v1_host_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2675,7 +2899,7 @@ func (x *CheckBusinessCapabilityRequest) String() string { func (*CheckBusinessCapabilityRequest) ProtoMessage() {} func (x *CheckBusinessCapabilityRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[35] + mi := &file_proto_user_v1_host_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2688,7 +2912,7 @@ func (x *CheckBusinessCapabilityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckBusinessCapabilityRequest.ProtoReflect.Descriptor instead. func (*CheckBusinessCapabilityRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{35} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{39} } func (x *CheckBusinessCapabilityRequest) GetMeta() *RequestMeta { @@ -2722,7 +2946,7 @@ type CheckBusinessCapabilityResponse struct { func (x *CheckBusinessCapabilityResponse) Reset() { *x = CheckBusinessCapabilityResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[36] + mi := &file_proto_user_v1_host_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2734,7 +2958,7 @@ func (x *CheckBusinessCapabilityResponse) String() string { func (*CheckBusinessCapabilityResponse) ProtoMessage() {} func (x *CheckBusinessCapabilityResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[36] + mi := &file_proto_user_v1_host_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2747,7 +2971,7 @@ func (x *CheckBusinessCapabilityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckBusinessCapabilityResponse.ProtoReflect.Descriptor instead. func (*CheckBusinessCapabilityResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{36} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{40} } func (x *CheckBusinessCapabilityResponse) GetAllowed() bool { @@ -2775,7 +2999,7 @@ type GetAgencyMembersRequest struct { func (x *GetAgencyMembersRequest) Reset() { *x = GetAgencyMembersRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[37] + mi := &file_proto_user_v1_host_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2787,7 +3011,7 @@ func (x *GetAgencyMembersRequest) String() string { func (*GetAgencyMembersRequest) ProtoMessage() {} func (x *GetAgencyMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[37] + mi := &file_proto_user_v1_host_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2800,7 +3024,7 @@ func (x *GetAgencyMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyMembersRequest.ProtoReflect.Descriptor instead. func (*GetAgencyMembersRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{37} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{41} } func (x *GetAgencyMembersRequest) GetMeta() *RequestMeta { @@ -2833,7 +3057,7 @@ type GetAgencyMembersResponse struct { func (x *GetAgencyMembersResponse) Reset() { *x = GetAgencyMembersResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[38] + mi := &file_proto_user_v1_host_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2845,7 +3069,7 @@ func (x *GetAgencyMembersResponse) String() string { func (*GetAgencyMembersResponse) ProtoMessage() {} func (x *GetAgencyMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[38] + mi := &file_proto_user_v1_host_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2858,7 +3082,7 @@ func (x *GetAgencyMembersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyMembersResponse.ProtoReflect.Descriptor instead. func (*GetAgencyMembersResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{38} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{42} } func (x *GetAgencyMembersResponse) GetMemberships() []*AgencyMembership { @@ -2879,7 +3103,7 @@ type GetAgencyApplicationsRequest struct { func (x *GetAgencyApplicationsRequest) Reset() { *x = GetAgencyApplicationsRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[39] + mi := &file_proto_user_v1_host_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2891,7 +3115,7 @@ func (x *GetAgencyApplicationsRequest) String() string { func (*GetAgencyApplicationsRequest) ProtoMessage() {} func (x *GetAgencyApplicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[39] + mi := &file_proto_user_v1_host_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2904,7 +3128,7 @@ func (x *GetAgencyApplicationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyApplicationsRequest.ProtoReflect.Descriptor instead. func (*GetAgencyApplicationsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{39} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{43} } func (x *GetAgencyApplicationsRequest) GetMeta() *RequestMeta { @@ -2937,7 +3161,7 @@ type GetAgencyApplicationsResponse struct { func (x *GetAgencyApplicationsResponse) Reset() { *x = GetAgencyApplicationsResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[40] + mi := &file_proto_user_v1_host_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2949,7 +3173,7 @@ func (x *GetAgencyApplicationsResponse) String() string { func (*GetAgencyApplicationsResponse) ProtoMessage() {} func (x *GetAgencyApplicationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[40] + mi := &file_proto_user_v1_host_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2962,7 +3186,7 @@ func (x *GetAgencyApplicationsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyApplicationsResponse.ProtoReflect.Descriptor instead. func (*GetAgencyApplicationsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{40} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{44} } func (x *GetAgencyApplicationsResponse) GetApplications() []*AgencyApplication { @@ -2986,7 +3210,7 @@ type CreateBDLeaderRequest struct { func (x *CreateBDLeaderRequest) Reset() { *x = CreateBDLeaderRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[41] + mi := &file_proto_user_v1_host_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2998,7 +3222,7 @@ func (x *CreateBDLeaderRequest) String() string { func (*CreateBDLeaderRequest) ProtoMessage() {} func (x *CreateBDLeaderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[41] + mi := &file_proto_user_v1_host_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3011,7 +3235,7 @@ func (x *CreateBDLeaderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDLeaderRequest.ProtoReflect.Descriptor instead. func (*CreateBDLeaderRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{41} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{45} } func (x *CreateBDLeaderRequest) GetMeta() *RequestMeta { @@ -3065,7 +3289,7 @@ type CreateBDLeaderResponse struct { func (x *CreateBDLeaderResponse) Reset() { *x = CreateBDLeaderResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[42] + mi := &file_proto_user_v1_host_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3077,7 +3301,7 @@ func (x *CreateBDLeaderResponse) String() string { func (*CreateBDLeaderResponse) ProtoMessage() {} func (x *CreateBDLeaderResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[42] + mi := &file_proto_user_v1_host_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3090,7 +3314,7 @@ func (x *CreateBDLeaderResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDLeaderResponse.ProtoReflect.Descriptor instead. func (*CreateBDLeaderResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{42} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{46} } func (x *CreateBDLeaderResponse) GetBdProfile() *BDProfile { @@ -3114,7 +3338,7 @@ type CreateBDRequest struct { func (x *CreateBDRequest) Reset() { *x = CreateBDRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[43] + mi := &file_proto_user_v1_host_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3126,7 +3350,7 @@ func (x *CreateBDRequest) String() string { func (*CreateBDRequest) ProtoMessage() {} func (x *CreateBDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[43] + mi := &file_proto_user_v1_host_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3139,7 +3363,7 @@ func (x *CreateBDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDRequest.ProtoReflect.Descriptor instead. func (*CreateBDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{43} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{47} } func (x *CreateBDRequest) GetMeta() *RequestMeta { @@ -3193,7 +3417,7 @@ type CreateBDResponse struct { func (x *CreateBDResponse) Reset() { *x = CreateBDResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[44] + mi := &file_proto_user_v1_host_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3205,7 +3429,7 @@ func (x *CreateBDResponse) String() string { func (*CreateBDResponse) ProtoMessage() {} func (x *CreateBDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[44] + mi := &file_proto_user_v1_host_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3218,7 +3442,7 @@ func (x *CreateBDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDResponse.ProtoReflect.Descriptor instead. func (*CreateBDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{44} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{48} } func (x *CreateBDResponse) GetBdProfile() *BDProfile { @@ -3242,7 +3466,7 @@ type SetBDStatusRequest struct { func (x *SetBDStatusRequest) Reset() { *x = SetBDStatusRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[45] + mi := &file_proto_user_v1_host_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3254,7 +3478,7 @@ func (x *SetBDStatusRequest) String() string { func (*SetBDStatusRequest) ProtoMessage() {} func (x *SetBDStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[45] + mi := &file_proto_user_v1_host_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3267,7 +3491,7 @@ func (x *SetBDStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBDStatusRequest.ProtoReflect.Descriptor instead. func (*SetBDStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{45} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{49} } func (x *SetBDStatusRequest) GetMeta() *RequestMeta { @@ -3321,7 +3545,7 @@ type SetBDStatusResponse struct { func (x *SetBDStatusResponse) Reset() { *x = SetBDStatusResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[46] + mi := &file_proto_user_v1_host_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3333,7 +3557,7 @@ func (x *SetBDStatusResponse) String() string { func (*SetBDStatusResponse) ProtoMessage() {} func (x *SetBDStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[46] + mi := &file_proto_user_v1_host_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3346,7 +3570,7 @@ func (x *SetBDStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBDStatusResponse.ProtoReflect.Descriptor instead. func (*SetBDStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{46} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{50} } func (x *SetBDStatusResponse) GetBdProfile() *BDProfile { @@ -3369,7 +3593,7 @@ type CreateCoinSellerRequest struct { func (x *CreateCoinSellerRequest) Reset() { *x = CreateCoinSellerRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[47] + mi := &file_proto_user_v1_host_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3381,7 +3605,7 @@ func (x *CreateCoinSellerRequest) String() string { func (*CreateCoinSellerRequest) ProtoMessage() {} func (x *CreateCoinSellerRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[47] + mi := &file_proto_user_v1_host_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3394,7 +3618,7 @@ func (x *CreateCoinSellerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateCoinSellerRequest.ProtoReflect.Descriptor instead. func (*CreateCoinSellerRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{47} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{51} } func (x *CreateCoinSellerRequest) GetMeta() *RequestMeta { @@ -3441,7 +3665,7 @@ type CreateCoinSellerResponse struct { func (x *CreateCoinSellerResponse) Reset() { *x = CreateCoinSellerResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[48] + mi := &file_proto_user_v1_host_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3453,7 +3677,7 @@ func (x *CreateCoinSellerResponse) String() string { func (*CreateCoinSellerResponse) ProtoMessage() {} func (x *CreateCoinSellerResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[48] + mi := &file_proto_user_v1_host_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3466,7 +3690,7 @@ func (x *CreateCoinSellerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateCoinSellerResponse.ProtoReflect.Descriptor instead. func (*CreateCoinSellerResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{48} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{52} } func (x *CreateCoinSellerResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -3490,7 +3714,7 @@ type SetCoinSellerStatusRequest struct { func (x *SetCoinSellerStatusRequest) Reset() { *x = SetCoinSellerStatusRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[49] + mi := &file_proto_user_v1_host_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3502,7 +3726,7 @@ func (x *SetCoinSellerStatusRequest) String() string { func (*SetCoinSellerStatusRequest) ProtoMessage() {} func (x *SetCoinSellerStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[49] + mi := &file_proto_user_v1_host_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3515,7 +3739,7 @@ func (x *SetCoinSellerStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetCoinSellerStatusRequest.ProtoReflect.Descriptor instead. func (*SetCoinSellerStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{49} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{53} } func (x *SetCoinSellerStatusRequest) GetMeta() *RequestMeta { @@ -3569,7 +3793,7 @@ type SetCoinSellerStatusResponse struct { func (x *SetCoinSellerStatusResponse) Reset() { *x = SetCoinSellerStatusResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[50] + mi := &file_proto_user_v1_host_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3581,7 +3805,7 @@ func (x *SetCoinSellerStatusResponse) String() string { func (*SetCoinSellerStatusResponse) ProtoMessage() {} func (x *SetCoinSellerStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[50] + mi := &file_proto_user_v1_host_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3594,7 +3818,7 @@ func (x *SetCoinSellerStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetCoinSellerStatusResponse.ProtoReflect.Descriptor instead. func (*SetCoinSellerStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{50} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{54} } func (x *SetCoinSellerStatusResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -3621,7 +3845,7 @@ type CreateAgencyRequest struct { func (x *CreateAgencyRequest) Reset() { *x = CreateAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[51] + mi := &file_proto_user_v1_host_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3633,7 +3857,7 @@ func (x *CreateAgencyRequest) String() string { func (*CreateAgencyRequest) ProtoMessage() {} func (x *CreateAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[51] + mi := &file_proto_user_v1_host_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3646,7 +3870,7 @@ func (x *CreateAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAgencyRequest.ProtoReflect.Descriptor instead. func (*CreateAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{51} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{55} } func (x *CreateAgencyRequest) GetMeta() *RequestMeta { @@ -3723,7 +3947,7 @@ type CreateAgencyResponse struct { func (x *CreateAgencyResponse) Reset() { *x = CreateAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[52] + mi := &file_proto_user_v1_host_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3735,7 +3959,7 @@ func (x *CreateAgencyResponse) String() string { func (*CreateAgencyResponse) ProtoMessage() {} func (x *CreateAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[52] + mi := &file_proto_user_v1_host_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3748,7 +3972,7 @@ func (x *CreateAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAgencyResponse.ProtoReflect.Descriptor instead. func (*CreateAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{52} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{56} } func (x *CreateAgencyResponse) GetAgency() *Agency { @@ -3785,7 +4009,7 @@ type CloseAgencyRequest struct { func (x *CloseAgencyRequest) Reset() { *x = CloseAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[53] + mi := &file_proto_user_v1_host_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3797,7 +4021,7 @@ func (x *CloseAgencyRequest) String() string { func (*CloseAgencyRequest) ProtoMessage() {} func (x *CloseAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[53] + mi := &file_proto_user_v1_host_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3810,7 +4034,7 @@ func (x *CloseAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseAgencyRequest.ProtoReflect.Descriptor instead. func (*CloseAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{53} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{57} } func (x *CloseAgencyRequest) GetMeta() *RequestMeta { @@ -3857,7 +4081,7 @@ type CloseAgencyResponse struct { func (x *CloseAgencyResponse) Reset() { *x = CloseAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[54] + mi := &file_proto_user_v1_host_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3869,7 +4093,7 @@ func (x *CloseAgencyResponse) String() string { func (*CloseAgencyResponse) ProtoMessage() {} func (x *CloseAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[54] + mi := &file_proto_user_v1_host_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3882,7 +4106,7 @@ func (x *CloseAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseAgencyResponse.ProtoReflect.Descriptor instead. func (*CloseAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{54} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{58} } func (x *CloseAgencyResponse) GetAgency() *Agency { @@ -3906,7 +4130,7 @@ type SetAgencyJoinEnabledRequest struct { func (x *SetAgencyJoinEnabledRequest) Reset() { *x = SetAgencyJoinEnabledRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[55] + mi := &file_proto_user_v1_host_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3918,7 +4142,7 @@ func (x *SetAgencyJoinEnabledRequest) String() string { func (*SetAgencyJoinEnabledRequest) ProtoMessage() {} func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[55] + mi := &file_proto_user_v1_host_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3931,7 +4155,7 @@ func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledRequest.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{55} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{59} } func (x *SetAgencyJoinEnabledRequest) GetMeta() *RequestMeta { @@ -3985,7 +4209,7 @@ type SetAgencyJoinEnabledResponse struct { func (x *SetAgencyJoinEnabledResponse) Reset() { *x = SetAgencyJoinEnabledResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[56] + mi := &file_proto_user_v1_host_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3997,7 +4221,7 @@ func (x *SetAgencyJoinEnabledResponse) String() string { func (*SetAgencyJoinEnabledResponse) ProtoMessage() {} func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[56] + mi := &file_proto_user_v1_host_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4010,7 +4234,7 @@ func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledResponse.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{56} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{60} } func (x *SetAgencyJoinEnabledResponse) GetAgency() *Agency { @@ -4220,7 +4444,22 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\x10InviteBDResponse\x12=\n" + "\n" + "invitation\x18\x01 \x01(\v2\x1d.hyapp.user.v1.RoleInvitationR\n" + - "invitation\"\xe6\x01\n" + + "invitation\"\xa3\x01\n" + + "\x16ListBDLeaderBDsRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12$\n" + + "\x0eleader_user_id\x18\x02 \x01(\x03R\fleaderUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"T\n" + + "\x17ListBDLeaderBDsResponse\x129\n" + + "\vbd_profiles\x18\x01 \x03(\v2\x18.hyapp.user.v1.BDProfileR\n" + + "bdProfiles\"\xa8\x01\n" + + "\x1bListBDLeaderAgenciesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12$\n" + + "\x0eleader_user_id\x18\x02 \x01(\x03R\fleaderUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"Q\n" + + "\x1cListBDLeaderAgenciesResponse\x121\n" + + "\bagencies\x18\x01 \x03(\v2\x15.hyapp.user.v1.AgencyR\bagencies\"\xe6\x01\n" + "\x1cProcessRoleInvitationRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + "\n" + @@ -4379,14 +4618,16 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\fjoin_enabled\x18\x05 \x01(\bR\vjoinEnabled\x12\x16\n" + "\x06reason\x18\x06 \x01(\tR\x06reason\"M\n" + "\x1cSetAgencyJoinEnabledResponse\x12-\n" + - "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency2\x89\r\n" + + "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency2\xdc\x0e\n" + "\x0fUserHostService\x12]\n" + "\x0eSearchAgencies\x12$.hyapp.user.v1.SearchAgenciesRequest\x1a%.hyapp.user.v1.SearchAgenciesResponse\x12Z\n" + "\rApplyToAgency\x12#.hyapp.user.v1.ApplyToAgencyRequest\x1a$.hyapp.user.v1.ApplyToAgencyResponse\x12x\n" + "\x17ReviewAgencyApplication\x12-.hyapp.user.v1.ReviewAgencyApplicationRequest\x1a..hyapp.user.v1.ReviewAgencyApplicationResponse\x12]\n" + "\x0eKickAgencyHost\x12$.hyapp.user.v1.KickAgencyHostRequest\x1a%.hyapp.user.v1.KickAgencyHostResponse\x12W\n" + "\fInviteAgency\x12\".hyapp.user.v1.InviteAgencyRequest\x1a#.hyapp.user.v1.InviteAgencyResponse\x12K\n" + - "\bInviteBD\x12\x1e.hyapp.user.v1.InviteBDRequest\x1a\x1f.hyapp.user.v1.InviteBDResponse\x12r\n" + + "\bInviteBD\x12\x1e.hyapp.user.v1.InviteBDRequest\x1a\x1f.hyapp.user.v1.InviteBDResponse\x12`\n" + + "\x0fListBDLeaderBDs\x12%.hyapp.user.v1.ListBDLeaderBDsRequest\x1a&.hyapp.user.v1.ListBDLeaderBDsResponse\x12o\n" + + "\x14ListBDLeaderAgencies\x12*.hyapp.user.v1.ListBDLeaderAgenciesRequest\x1a+.hyapp.user.v1.ListBDLeaderAgenciesResponse\x12r\n" + "\x15ProcessRoleInvitation\x12+.hyapp.user.v1.ProcessRoleInvitationRequest\x1a,.hyapp.user.v1.ProcessRoleInvitationResponse\x12]\n" + "\x0eGetHostProfile\x12$.hyapp.user.v1.GetHostProfileRequest\x1a%.hyapp.user.v1.GetHostProfileResponse\x12W\n" + "\fGetBDProfile\x12\".hyapp.user.v1.GetBDProfileRequest\x1a#.hyapp.user.v1.GetBDProfileResponse\x12o\n" + @@ -4419,7 +4660,7 @@ func file_proto_user_v1_host_proto_rawDescGZIP() []byte { return file_proto_user_v1_host_proto_rawDescData } -var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 57) +var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 61) var file_proto_user_v1_host_proto_goTypes = []any{ (*HostProfile)(nil), // 0: hyapp.user.v1.HostProfile (*Agency)(nil), // 1: hyapp.user.v1.Agency @@ -4442,154 +4683,166 @@ var file_proto_user_v1_host_proto_goTypes = []any{ (*InviteAgencyResponse)(nil), // 18: hyapp.user.v1.InviteAgencyResponse (*InviteBDRequest)(nil), // 19: hyapp.user.v1.InviteBDRequest (*InviteBDResponse)(nil), // 20: hyapp.user.v1.InviteBDResponse - (*ProcessRoleInvitationRequest)(nil), // 21: hyapp.user.v1.ProcessRoleInvitationRequest - (*ProcessRoleInvitationResponse)(nil), // 22: hyapp.user.v1.ProcessRoleInvitationResponse - (*GetHostProfileRequest)(nil), // 23: hyapp.user.v1.GetHostProfileRequest - (*GetHostProfileResponse)(nil), // 24: hyapp.user.v1.GetHostProfileResponse - (*GetBDProfileRequest)(nil), // 25: hyapp.user.v1.GetBDProfileRequest - (*GetBDProfileResponse)(nil), // 26: hyapp.user.v1.GetBDProfileResponse - (*GetCoinSellerProfileRequest)(nil), // 27: hyapp.user.v1.GetCoinSellerProfileRequest - (*GetCoinSellerProfileResponse)(nil), // 28: hyapp.user.v1.GetCoinSellerProfileResponse - (*ListActiveCoinSellersInMyRegionRequest)(nil), // 29: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - (*ListActiveCoinSellersInMyRegionResponse)(nil), // 30: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - (*GetUserRoleSummaryRequest)(nil), // 31: hyapp.user.v1.GetUserRoleSummaryRequest - (*GetUserRoleSummaryResponse)(nil), // 32: hyapp.user.v1.GetUserRoleSummaryResponse - (*GetAgencyRequest)(nil), // 33: hyapp.user.v1.GetAgencyRequest - (*GetAgencyResponse)(nil), // 34: hyapp.user.v1.GetAgencyResponse - (*CheckBusinessCapabilityRequest)(nil), // 35: hyapp.user.v1.CheckBusinessCapabilityRequest - (*CheckBusinessCapabilityResponse)(nil), // 36: hyapp.user.v1.CheckBusinessCapabilityResponse - (*GetAgencyMembersRequest)(nil), // 37: hyapp.user.v1.GetAgencyMembersRequest - (*GetAgencyMembersResponse)(nil), // 38: hyapp.user.v1.GetAgencyMembersResponse - (*GetAgencyApplicationsRequest)(nil), // 39: hyapp.user.v1.GetAgencyApplicationsRequest - (*GetAgencyApplicationsResponse)(nil), // 40: hyapp.user.v1.GetAgencyApplicationsResponse - (*CreateBDLeaderRequest)(nil), // 41: hyapp.user.v1.CreateBDLeaderRequest - (*CreateBDLeaderResponse)(nil), // 42: hyapp.user.v1.CreateBDLeaderResponse - (*CreateBDRequest)(nil), // 43: hyapp.user.v1.CreateBDRequest - (*CreateBDResponse)(nil), // 44: hyapp.user.v1.CreateBDResponse - (*SetBDStatusRequest)(nil), // 45: hyapp.user.v1.SetBDStatusRequest - (*SetBDStatusResponse)(nil), // 46: hyapp.user.v1.SetBDStatusResponse - (*CreateCoinSellerRequest)(nil), // 47: hyapp.user.v1.CreateCoinSellerRequest - (*CreateCoinSellerResponse)(nil), // 48: hyapp.user.v1.CreateCoinSellerResponse - (*SetCoinSellerStatusRequest)(nil), // 49: hyapp.user.v1.SetCoinSellerStatusRequest - (*SetCoinSellerStatusResponse)(nil), // 50: hyapp.user.v1.SetCoinSellerStatusResponse - (*CreateAgencyRequest)(nil), // 51: hyapp.user.v1.CreateAgencyRequest - (*CreateAgencyResponse)(nil), // 52: hyapp.user.v1.CreateAgencyResponse - (*CloseAgencyRequest)(nil), // 53: hyapp.user.v1.CloseAgencyRequest - (*CloseAgencyResponse)(nil), // 54: hyapp.user.v1.CloseAgencyResponse - (*SetAgencyJoinEnabledRequest)(nil), // 55: hyapp.user.v1.SetAgencyJoinEnabledRequest - (*SetAgencyJoinEnabledResponse)(nil), // 56: hyapp.user.v1.SetAgencyJoinEnabledResponse - (*RequestMeta)(nil), // 57: hyapp.user.v1.RequestMeta + (*ListBDLeaderBDsRequest)(nil), // 21: hyapp.user.v1.ListBDLeaderBDsRequest + (*ListBDLeaderBDsResponse)(nil), // 22: hyapp.user.v1.ListBDLeaderBDsResponse + (*ListBDLeaderAgenciesRequest)(nil), // 23: hyapp.user.v1.ListBDLeaderAgenciesRequest + (*ListBDLeaderAgenciesResponse)(nil), // 24: hyapp.user.v1.ListBDLeaderAgenciesResponse + (*ProcessRoleInvitationRequest)(nil), // 25: hyapp.user.v1.ProcessRoleInvitationRequest + (*ProcessRoleInvitationResponse)(nil), // 26: hyapp.user.v1.ProcessRoleInvitationResponse + (*GetHostProfileRequest)(nil), // 27: hyapp.user.v1.GetHostProfileRequest + (*GetHostProfileResponse)(nil), // 28: hyapp.user.v1.GetHostProfileResponse + (*GetBDProfileRequest)(nil), // 29: hyapp.user.v1.GetBDProfileRequest + (*GetBDProfileResponse)(nil), // 30: hyapp.user.v1.GetBDProfileResponse + (*GetCoinSellerProfileRequest)(nil), // 31: hyapp.user.v1.GetCoinSellerProfileRequest + (*GetCoinSellerProfileResponse)(nil), // 32: hyapp.user.v1.GetCoinSellerProfileResponse + (*ListActiveCoinSellersInMyRegionRequest)(nil), // 33: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + (*ListActiveCoinSellersInMyRegionResponse)(nil), // 34: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + (*GetUserRoleSummaryRequest)(nil), // 35: hyapp.user.v1.GetUserRoleSummaryRequest + (*GetUserRoleSummaryResponse)(nil), // 36: hyapp.user.v1.GetUserRoleSummaryResponse + (*GetAgencyRequest)(nil), // 37: hyapp.user.v1.GetAgencyRequest + (*GetAgencyResponse)(nil), // 38: hyapp.user.v1.GetAgencyResponse + (*CheckBusinessCapabilityRequest)(nil), // 39: hyapp.user.v1.CheckBusinessCapabilityRequest + (*CheckBusinessCapabilityResponse)(nil), // 40: hyapp.user.v1.CheckBusinessCapabilityResponse + (*GetAgencyMembersRequest)(nil), // 41: hyapp.user.v1.GetAgencyMembersRequest + (*GetAgencyMembersResponse)(nil), // 42: hyapp.user.v1.GetAgencyMembersResponse + (*GetAgencyApplicationsRequest)(nil), // 43: hyapp.user.v1.GetAgencyApplicationsRequest + (*GetAgencyApplicationsResponse)(nil), // 44: hyapp.user.v1.GetAgencyApplicationsResponse + (*CreateBDLeaderRequest)(nil), // 45: hyapp.user.v1.CreateBDLeaderRequest + (*CreateBDLeaderResponse)(nil), // 46: hyapp.user.v1.CreateBDLeaderResponse + (*CreateBDRequest)(nil), // 47: hyapp.user.v1.CreateBDRequest + (*CreateBDResponse)(nil), // 48: hyapp.user.v1.CreateBDResponse + (*SetBDStatusRequest)(nil), // 49: hyapp.user.v1.SetBDStatusRequest + (*SetBDStatusResponse)(nil), // 50: hyapp.user.v1.SetBDStatusResponse + (*CreateCoinSellerRequest)(nil), // 51: hyapp.user.v1.CreateCoinSellerRequest + (*CreateCoinSellerResponse)(nil), // 52: hyapp.user.v1.CreateCoinSellerResponse + (*SetCoinSellerStatusRequest)(nil), // 53: hyapp.user.v1.SetCoinSellerStatusRequest + (*SetCoinSellerStatusResponse)(nil), // 54: hyapp.user.v1.SetCoinSellerStatusResponse + (*CreateAgencyRequest)(nil), // 55: hyapp.user.v1.CreateAgencyRequest + (*CreateAgencyResponse)(nil), // 56: hyapp.user.v1.CreateAgencyResponse + (*CloseAgencyRequest)(nil), // 57: hyapp.user.v1.CloseAgencyRequest + (*CloseAgencyResponse)(nil), // 58: hyapp.user.v1.CloseAgencyResponse + (*SetAgencyJoinEnabledRequest)(nil), // 59: hyapp.user.v1.SetAgencyJoinEnabledRequest + (*SetAgencyJoinEnabledResponse)(nil), // 60: hyapp.user.v1.SetAgencyJoinEnabledResponse + (*RequestMeta)(nil), // 61: hyapp.user.v1.RequestMeta } var file_proto_user_v1_host_proto_depIdxs = []int32{ - 57, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 1: hyapp.user.v1.SearchAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 57, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 3: hyapp.user.v1.ApplyToAgencyResponse.application:type_name -> hyapp.user.v1.AgencyApplication - 57, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 5: hyapp.user.v1.ReviewAgencyApplicationResponse.application:type_name -> hyapp.user.v1.AgencyApplication 0, // 6: hyapp.user.v1.ReviewAgencyApplicationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 7: hyapp.user.v1.ReviewAgencyApplicationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 57, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 9: hyapp.user.v1.KickAgencyHostResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 0, // 10: hyapp.user.v1.KickAgencyHostResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 57, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 12: hyapp.user.v1.InviteAgencyResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 57, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 14: hyapp.user.v1.InviteBDResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 57, // 15: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 8, // 16: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 0, // 17: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 1, // 18: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency - 6, // 19: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 2, // 20: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 57, // 21: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 0, // 22: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 57, // 23: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 24: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 57, // 25: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 26: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 57, // 27: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 4, // 28: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem - 57, // 29: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 30: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary - 57, // 31: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 32: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 57, // 33: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 57, // 34: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 6, // 35: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership - 57, // 36: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 7, // 37: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication - 57, // 38: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 39: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 57, // 40: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 41: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 57, // 42: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 43: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 57, // 44: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 45: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 57, // 46: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 47: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 57, // 48: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 49: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 0, // 50: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 6, // 51: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 57, // 52: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 53: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 57, // 54: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 55: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency - 9, // 56: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest - 11, // 57: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest - 13, // 58: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest - 15, // 59: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest - 17, // 60: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest - 19, // 61: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest - 21, // 62: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest - 23, // 63: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest - 25, // 64: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest - 27, // 65: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest - 29, // 66: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - 31, // 67: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest - 33, // 68: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest - 35, // 69: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest - 37, // 70: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest - 39, // 71: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest - 41, // 72: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest - 43, // 73: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest - 45, // 74: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest - 47, // 75: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest - 49, // 76: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest - 51, // 77: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest - 53, // 78: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest - 55, // 79: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest - 10, // 80: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse - 12, // 81: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse - 14, // 82: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse - 16, // 83: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse - 18, // 84: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse - 20, // 85: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse - 22, // 86: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse - 24, // 87: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse - 26, // 88: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse - 28, // 89: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse - 30, // 90: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - 32, // 91: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse - 34, // 92: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse - 36, // 93: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse - 38, // 94: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse - 40, // 95: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse - 42, // 96: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse - 44, // 97: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse - 46, // 98: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse - 48, // 99: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse - 50, // 100: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse - 52, // 101: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse - 54, // 102: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse - 56, // 103: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse - 80, // [80:104] is the sub-list for method output_type - 56, // [56:80] is the sub-list for method input_type - 56, // [56:56] is the sub-list for extension type_name - 56, // [56:56] is the sub-list for extension extendee - 0, // [0:56] is the sub-list for field type_name + 61, // 15: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 16: hyapp.user.v1.ListBDLeaderBDsResponse.bd_profiles:type_name -> hyapp.user.v1.BDProfile + 61, // 17: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 18: hyapp.user.v1.ListBDLeaderAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency + 61, // 19: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 8, // 20: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation + 0, // 21: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 1, // 22: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency + 6, // 23: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership + 2, // 24: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 61, // 25: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 0, // 26: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 61, // 27: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 28: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 61, // 29: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 30: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 61, // 31: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 4, // 32: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem + 61, // 33: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 34: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary + 61, // 35: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 36: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 61, // 37: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 61, // 38: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 6, // 39: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership + 61, // 40: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 7, // 41: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication + 61, // 42: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 43: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 61, // 44: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 45: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 61, // 46: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 47: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 61, // 48: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 49: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 61, // 50: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 51: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 61, // 52: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 53: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 0, // 54: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 6, // 55: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership + 61, // 56: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 57: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 61, // 58: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 59: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency + 9, // 60: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest + 11, // 61: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest + 13, // 62: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest + 15, // 63: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest + 17, // 64: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest + 19, // 65: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest + 21, // 66: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest + 23, // 67: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest + 25, // 68: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest + 27, // 69: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest + 29, // 70: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest + 31, // 71: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest + 33, // 72: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + 35, // 73: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest + 37, // 74: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest + 39, // 75: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest + 41, // 76: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest + 43, // 77: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest + 45, // 78: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest + 47, // 79: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest + 49, // 80: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest + 51, // 81: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest + 53, // 82: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest + 55, // 83: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest + 57, // 84: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest + 59, // 85: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest + 10, // 86: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse + 12, // 87: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse + 14, // 88: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse + 16, // 89: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse + 18, // 90: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse + 20, // 91: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse + 22, // 92: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse + 24, // 93: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse + 26, // 94: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse + 28, // 95: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse + 30, // 96: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse + 32, // 97: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse + 34, // 98: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + 36, // 99: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse + 38, // 100: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse + 40, // 101: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse + 42, // 102: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse + 44, // 103: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse + 46, // 104: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse + 48, // 105: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse + 50, // 106: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse + 52, // 107: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse + 54, // 108: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse + 56, // 109: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse + 58, // 110: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse + 60, // 111: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse + 86, // [86:112] is the sub-list for method output_type + 60, // [60:86] is the sub-list for method input_type + 60, // [60:60] is the sub-list for extension type_name + 60, // [60:60] is the sub-list for extension extendee + 0, // [0:60] is the sub-list for field type_name } func init() { file_proto_user_v1_host_proto_init() } @@ -4604,7 +4857,7 @@ func file_proto_user_v1_host_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_host_proto_rawDesc), len(file_proto_user_v1_host_proto_rawDesc)), NumEnums: 0, - NumMessages: 57, + NumMessages: 61, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/user/v1/host.proto b/api/proto/user/v1/host.proto index d69d85bb..b18edc2d 100644 --- a/api/proto/user/v1/host.proto +++ b/api/proto/user/v1/host.proto @@ -221,6 +221,28 @@ message InviteBDResponse { RoleInvitation invitation = 1; } +message ListBDLeaderBDsRequest { + RequestMeta meta = 1; + int64 leader_user_id = 2; + string status = 3; + int32 page_size = 4; +} + +message ListBDLeaderBDsResponse { + repeated BDProfile bd_profiles = 1; +} + +message ListBDLeaderAgenciesRequest { + RequestMeta meta = 1; + int64 leader_user_id = 2; + string status = 3; + int32 page_size = 4; +} + +message ListBDLeaderAgenciesResponse { + repeated Agency agencies = 1; +} + message ProcessRoleInvitationRequest { RequestMeta meta = 1; string command_id = 2; @@ -438,6 +460,8 @@ service UserHostService { rpc KickAgencyHost(KickAgencyHostRequest) returns (KickAgencyHostResponse); rpc InviteAgency(InviteAgencyRequest) returns (InviteAgencyResponse); rpc InviteBD(InviteBDRequest) returns (InviteBDResponse); + rpc ListBDLeaderBDs(ListBDLeaderBDsRequest) returns (ListBDLeaderBDsResponse); + rpc ListBDLeaderAgencies(ListBDLeaderAgenciesRequest) returns (ListBDLeaderAgenciesResponse); rpc ProcessRoleInvitation(ProcessRoleInvitationRequest) returns (ProcessRoleInvitationResponse); rpc GetHostProfile(GetHostProfileRequest) returns (GetHostProfileResponse); rpc GetBDProfile(GetBDProfileRequest) returns (GetBDProfileResponse); diff --git a/api/proto/user/v1/host_grpc.pb.go b/api/proto/user/v1/host_grpc.pb.go index 623dadb9..7765209f 100644 --- a/api/proto/user/v1/host_grpc.pb.go +++ b/api/proto/user/v1/host_grpc.pb.go @@ -25,6 +25,8 @@ const ( UserHostService_KickAgencyHost_FullMethodName = "/hyapp.user.v1.UserHostService/KickAgencyHost" UserHostService_InviteAgency_FullMethodName = "/hyapp.user.v1.UserHostService/InviteAgency" UserHostService_InviteBD_FullMethodName = "/hyapp.user.v1.UserHostService/InviteBD" + UserHostService_ListBDLeaderBDs_FullMethodName = "/hyapp.user.v1.UserHostService/ListBDLeaderBDs" + UserHostService_ListBDLeaderAgencies_FullMethodName = "/hyapp.user.v1.UserHostService/ListBDLeaderAgencies" UserHostService_ProcessRoleInvitation_FullMethodName = "/hyapp.user.v1.UserHostService/ProcessRoleInvitation" UserHostService_GetHostProfile_FullMethodName = "/hyapp.user.v1.UserHostService/GetHostProfile" UserHostService_GetBDProfile_FullMethodName = "/hyapp.user.v1.UserHostService/GetBDProfile" @@ -49,6 +51,8 @@ type UserHostServiceClient interface { KickAgencyHost(ctx context.Context, in *KickAgencyHostRequest, opts ...grpc.CallOption) (*KickAgencyHostResponse, error) InviteAgency(ctx context.Context, in *InviteAgencyRequest, opts ...grpc.CallOption) (*InviteAgencyResponse, error) InviteBD(ctx context.Context, in *InviteBDRequest, opts ...grpc.CallOption) (*InviteBDResponse, error) + ListBDLeaderBDs(ctx context.Context, in *ListBDLeaderBDsRequest, opts ...grpc.CallOption) (*ListBDLeaderBDsResponse, error) + ListBDLeaderAgencies(ctx context.Context, in *ListBDLeaderAgenciesRequest, opts ...grpc.CallOption) (*ListBDLeaderAgenciesResponse, error) ProcessRoleInvitation(ctx context.Context, in *ProcessRoleInvitationRequest, opts ...grpc.CallOption) (*ProcessRoleInvitationResponse, error) GetHostProfile(ctx context.Context, in *GetHostProfileRequest, opts ...grpc.CallOption) (*GetHostProfileResponse, error) GetBDProfile(ctx context.Context, in *GetBDProfileRequest, opts ...grpc.CallOption) (*GetBDProfileResponse, error) @@ -129,6 +133,26 @@ func (c *userHostServiceClient) InviteBD(ctx context.Context, in *InviteBDReques return out, nil } +func (c *userHostServiceClient) ListBDLeaderBDs(ctx context.Context, in *ListBDLeaderBDsRequest, opts ...grpc.CallOption) (*ListBDLeaderBDsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBDLeaderBDsResponse) + err := c.cc.Invoke(ctx, UserHostService_ListBDLeaderBDs_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userHostServiceClient) ListBDLeaderAgencies(ctx context.Context, in *ListBDLeaderAgenciesRequest, opts ...grpc.CallOption) (*ListBDLeaderAgenciesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBDLeaderAgenciesResponse) + err := c.cc.Invoke(ctx, UserHostService_ListBDLeaderAgencies_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userHostServiceClient) ProcessRoleInvitation(ctx context.Context, in *ProcessRoleInvitationRequest, opts ...grpc.CallOption) (*ProcessRoleInvitationResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ProcessRoleInvitationResponse) @@ -241,6 +265,8 @@ type UserHostServiceServer interface { KickAgencyHost(context.Context, *KickAgencyHostRequest) (*KickAgencyHostResponse, error) InviteAgency(context.Context, *InviteAgencyRequest) (*InviteAgencyResponse, error) InviteBD(context.Context, *InviteBDRequest) (*InviteBDResponse, error) + ListBDLeaderBDs(context.Context, *ListBDLeaderBDsRequest) (*ListBDLeaderBDsResponse, error) + ListBDLeaderAgencies(context.Context, *ListBDLeaderAgenciesRequest) (*ListBDLeaderAgenciesResponse, error) ProcessRoleInvitation(context.Context, *ProcessRoleInvitationRequest) (*ProcessRoleInvitationResponse, error) GetHostProfile(context.Context, *GetHostProfileRequest) (*GetHostProfileResponse, error) GetBDProfile(context.Context, *GetBDProfileRequest) (*GetBDProfileResponse, error) @@ -279,6 +305,12 @@ func (UnimplementedUserHostServiceServer) InviteAgency(context.Context, *InviteA func (UnimplementedUserHostServiceServer) InviteBD(context.Context, *InviteBDRequest) (*InviteBDResponse, error) { return nil, status.Error(codes.Unimplemented, "method InviteBD not implemented") } +func (UnimplementedUserHostServiceServer) ListBDLeaderBDs(context.Context, *ListBDLeaderBDsRequest) (*ListBDLeaderBDsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBDLeaderBDs not implemented") +} +func (UnimplementedUserHostServiceServer) ListBDLeaderAgencies(context.Context, *ListBDLeaderAgenciesRequest) (*ListBDLeaderAgenciesResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBDLeaderAgencies not implemented") +} func (UnimplementedUserHostServiceServer) ProcessRoleInvitation(context.Context, *ProcessRoleInvitationRequest) (*ProcessRoleInvitationResponse, error) { return nil, status.Error(codes.Unimplemented, "method ProcessRoleInvitation not implemented") } @@ -438,6 +470,42 @@ func _UserHostService_InviteBD_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _UserHostService_ListBDLeaderBDs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListBDLeaderBDsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserHostServiceServer).ListBDLeaderBDs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserHostService_ListBDLeaderBDs_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserHostServiceServer).ListBDLeaderBDs(ctx, req.(*ListBDLeaderBDsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _UserHostService_ListBDLeaderAgencies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListBDLeaderAgenciesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserHostServiceServer).ListBDLeaderAgencies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserHostService_ListBDLeaderAgencies_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserHostServiceServer).ListBDLeaderAgencies(ctx, req.(*ListBDLeaderAgenciesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserHostService_ProcessRoleInvitation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ProcessRoleInvitationRequest) if err := dec(in); err != nil { @@ -649,6 +717,14 @@ var UserHostService_ServiceDesc = grpc.ServiceDesc{ MethodName: "InviteBD", Handler: _UserHostService_InviteBD_Handler, }, + { + MethodName: "ListBDLeaderBDs", + Handler: _UserHostService_ListBDLeaderBDs_Handler, + }, + { + MethodName: "ListBDLeaderAgencies", + Handler: _UserHostService_ListBDLeaderAgencies_Handler, + }, { MethodName: "ProcessRoleInvitation", Handler: _UserHostService_ProcessRoleInvitation_Handler, diff --git a/services/gateway-service/internal/client/user_client.go b/services/gateway-service/internal/client/user_client.go index b5ac0aff..c1d14479 100644 --- a/services/gateway-service/internal/client/user_client.go +++ b/services/gateway-service/internal/client/user_client.go @@ -69,6 +69,10 @@ type UserCountryQueryClient interface { type UserHostClient interface { SearchAgencies(ctx context.Context, req *userv1.SearchAgenciesRequest) (*userv1.SearchAgenciesResponse, error) ApplyToAgency(ctx context.Context, req *userv1.ApplyToAgencyRequest) (*userv1.ApplyToAgencyResponse, error) + InviteAgency(ctx context.Context, req *userv1.InviteAgencyRequest) (*userv1.InviteAgencyResponse, error) + InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) + ListBDLeaderBDs(ctx context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) + ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) GetHostProfile(ctx context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) GetBDProfile(ctx context.Context, req *userv1.GetBDProfileRequest) (*userv1.GetBDProfileResponse, error) GetCoinSellerProfile(ctx context.Context, req *userv1.GetCoinSellerProfileRequest) (*userv1.GetCoinSellerProfileResponse, error) @@ -315,6 +319,22 @@ func (c *grpcUserHostClient) ApplyToAgency(ctx context.Context, req *userv1.Appl return c.client.ApplyToAgency(ctx, req) } +func (c *grpcUserHostClient) InviteAgency(ctx context.Context, req *userv1.InviteAgencyRequest) (*userv1.InviteAgencyResponse, error) { + return c.client.InviteAgency(ctx, req) +} + +func (c *grpcUserHostClient) InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) { + return c.client.InviteBD(ctx, req) +} + +func (c *grpcUserHostClient) ListBDLeaderBDs(ctx context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) { + return c.client.ListBDLeaderBDs(ctx, req) +} + +func (c *grpcUserHostClient) ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) { + return c.client.ListBDLeaderAgencies(ctx, req) +} + func (c *grpcUserHostClient) GetHostProfile(ctx context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) { return c.client.GetHostProfile(ctx, req) } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 7fda6ab5..68447200 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -79,6 +79,11 @@ type UserHandlers struct { ListAgencyCenterApplications http.HandlerFunc ReviewAgencyCenterApplication http.HandlerFunc RemoveAgencyCenterHost http.HandlerFunc + GetBDLeaderCenterOverview http.HandlerFunc + ListBDLeaderCenterBDs http.HandlerFunc + ListBDLeaderCenterAgencies http.HandlerFunc + InviteBDLeaderBD http.HandlerFunc + InviteBDLeaderAgency http.HandlerFunc CompleteMyOnboarding http.HandlerFunc UpdateMyProfile http.HandlerFunc ChangeMyCountry http.HandlerFunc @@ -310,6 +315,11 @@ func (r routes) registerUserRoutes() { r.profile("/agency-center/applications", http.MethodGet, h.ListAgencyCenterApplications) r.profile("/agency-center/applications/{application_id}/review", http.MethodPost, h.ReviewAgencyCenterApplication) r.profile("/agency-center/hosts/{host_user_id}/remove", http.MethodPost, h.RemoveAgencyCenterHost) + r.profile("/bd-leader-center/overview", http.MethodGet, h.GetBDLeaderCenterOverview) + r.profile("/bd-leader-center/bds", http.MethodGet, h.ListBDLeaderCenterBDs) + r.profile("/bd-leader-center/agencies", http.MethodGet, h.ListBDLeaderCenterAgencies) + r.profile("/bd-leader/invitations/bd", http.MethodPost, h.InviteBDLeaderBD) + r.profile("/bd-leader/invitations/agency", http.MethodPost, h.InviteBDLeaderAgency) r.auth("/users/me/onboarding/complete", "", h.CompleteMyOnboarding) r.profile("/users/me/profile/update", "", h.UpdateMyProfile) r.profile("/users/me/country/change", "", h.ChangeMyCountry) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index a4f27e09..5744270b 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -395,6 +395,18 @@ type fakeUserHostClient struct { lastApplyAgency *userv1.ApplyToAgencyRequest applyAgencyResp *userv1.ApplyToAgencyResponse applyAgencyErr error + lastInviteAgency *userv1.InviteAgencyRequest + inviteAgencyResp *userv1.InviteAgencyResponse + inviteAgencyErr error + lastInviteBD *userv1.InviteBDRequest + inviteBDResp *userv1.InviteBDResponse + inviteBDErr error + lastLeaderBDs *userv1.ListBDLeaderBDsRequest + leaderBDsResp *userv1.ListBDLeaderBDsResponse + leaderBDsErr error + lastLeaderAgencies *userv1.ListBDLeaderAgenciesRequest + leaderAgenciesResp *userv1.ListBDLeaderAgenciesResponse + leaderAgenciesErr error last *userv1.GetCoinSellerProfileRequest profile *userv1.CoinSellerProfile err error @@ -1082,6 +1094,50 @@ func (f *fakeUserHostClient) ApplyToAgency(_ context.Context, req *userv1.ApplyT return &userv1.ApplyToAgencyResponse{}, nil } +func (f *fakeUserHostClient) InviteAgency(_ context.Context, req *userv1.InviteAgencyRequest) (*userv1.InviteAgencyResponse, error) { + f.lastInviteAgency = req + if f.inviteAgencyErr != nil { + return nil, f.inviteAgencyErr + } + if f.inviteAgencyResp != nil { + return f.inviteAgencyResp, nil + } + return &userv1.InviteAgencyResponse{}, nil +} + +func (f *fakeUserHostClient) InviteBD(_ context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) { + f.lastInviteBD = req + if f.inviteBDErr != nil { + return nil, f.inviteBDErr + } + if f.inviteBDResp != nil { + return f.inviteBDResp, nil + } + return &userv1.InviteBDResponse{}, nil +} + +func (f *fakeUserHostClient) ListBDLeaderBDs(_ context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) { + f.lastLeaderBDs = req + if f.leaderBDsErr != nil { + return nil, f.leaderBDsErr + } + if f.leaderBDsResp != nil { + return f.leaderBDsResp, nil + } + return &userv1.ListBDLeaderBDsResponse{}, nil +} + +func (f *fakeUserHostClient) ListBDLeaderAgencies(_ context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) { + f.lastLeaderAgencies = req + if f.leaderAgenciesErr != nil { + return nil, f.leaderAgenciesErr + } + if f.leaderAgenciesResp != nil { + return f.leaderAgenciesResp, nil + } + return &userv1.ListBDLeaderAgenciesResponse{}, nil +} + func (f *fakeUserHostClient) GetHostProfile(_ context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) { f.lastHost = req if f.hostErr != nil { diff --git a/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go b/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go new file mode 100644 index 00000000..460dbddc --- /dev/null +++ b/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go @@ -0,0 +1,363 @@ +package userapi + +import ( + "net/http" + "strconv" + "strings" + + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +const ( + adminSalaryAssetType = "ADMIN_SALARY_USD" + bdStatusActive = "active" +) + +type bdLeaderProfileData struct { + UserID string `json:"user_id"` + Role string `json:"role"` + RegionID int64 `json:"region_id"` + ParentLeaderUserID string `json:"parent_leader_user_id,omitempty"` + Status string `json:"status"` + CreatedByUserID string `json:"created_by_user_id,omitempty"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +func (h *Handler) getBDLeaderCenterOverview(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + profile, ok := h.resolveActiveBDLeader(writer, request, userID) + if !ok { + return + } + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + users, err := h.userProfiles(request, []int64{userID}) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + salary, err := h.salaryBalance(request, userID, adminSalaryAssetType) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + bdResp, err := h.userHostClient.ListBDLeaderBDs(request.Context(), &userv1.ListBDLeaderBDsRequest{ + Meta: httpkit.UserMeta(request, ""), + LeaderUserId: userID, + Status: bdStatusActive, + PageSize: 100, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + agencyResp, err := h.userHostClient.ListBDLeaderAgencies(request.Context(), &userv1.ListBDLeaderAgenciesRequest{ + Meta: httpkit.UserMeta(request, ""), + LeaderUserId: userID, + Status: agencyStatusActive, + PageSize: 100, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + httpkit.WriteOK(writer, request, map[string]any{ + "profile": users[userID], + "bd_profile": bdLeaderProfileFromProto(profile), + "salary": salary, + "overview": map[string]any{ + "total_bd": len(bdResp.GetBdProfiles()), + "total_agency": len(agencyResp.GetAgencies()), + }, + }) +} + +func (h *Handler) listBDLeaderCenterBDs(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + if _, ok := h.resolveActiveBDLeader(writer, request, userID); !ok { + return + } + pageSize := queryPageSize(request, 20) + resp, err := h.userHostClient.ListBDLeaderBDs(request.Context(), &userv1.ListBDLeaderBDsRequest{ + Meta: httpkit.UserMeta(request, ""), + LeaderUserId: userID, + Status: bdStatusActive, + PageSize: int32(pageSize), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + agencyResp, err := h.userHostClient.ListBDLeaderAgencies(request.Context(), &userv1.ListBDLeaderAgenciesRequest{ + Meta: httpkit.UserMeta(request, ""), + LeaderUserId: userID, + Status: agencyStatusActive, + PageSize: 100, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + agencyCounts := make(map[int64]int) + for _, agency := range agencyResp.GetAgencies() { + agencyCounts[agency.GetParentBdUserId()]++ + } + + userIDs := make([]int64, 0, len(resp.GetBdProfiles())) + for _, profile := range resp.GetBdProfiles() { + userIDs = append(userIDs, profile.GetUserId()) + } + users, err := h.userProfiles(request, userIDs) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + items := make([]map[string]any, 0, len(resp.GetBdProfiles())) + for _, profile := range resp.GetBdProfiles() { + user := users[profile.GetUserId()] + items = append(items, map[string]any{ + "user_id": int64String(profile.GetUserId()), + "display_user_id": user.DisplayUserID, + "username": user.Username, + "avatar": user.Avatar, + "role": profile.GetRole(), + "status": profile.GetStatus(), + "region_id": profile.GetRegionId(), + "agency_count": agencyCounts[profile.GetUserId()], + }) + } + httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": len(items)}) +} + +func (h *Handler) listBDLeaderCenterAgencies(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + if _, ok := h.resolveActiveBDLeader(writer, request, userID); !ok { + return + } + pageSize := queryPageSize(request, 20) + resp, err := h.userHostClient.ListBDLeaderAgencies(request.Context(), &userv1.ListBDLeaderAgenciesRequest{ + Meta: httpkit.UserMeta(request, ""), + LeaderUserId: userID, + Status: agencyStatusActive, + PageSize: int32(pageSize), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + userIDs := make([]int64, 0, len(resp.GetAgencies())) + for _, agency := range resp.GetAgencies() { + userIDs = append(userIDs, agency.GetOwnerUserId(), agency.GetParentBdUserId()) + } + users, err := h.userProfiles(request, userIDs) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + items := make([]map[string]any, 0, len(resp.GetAgencies())) + for _, agency := range resp.GetAgencies() { + membersResp, err := h.userHostClient.GetAgencyMembers(request.Context(), &userv1.GetAgencyMembersRequest{ + Meta: httpkit.UserMeta(request, ""), + AgencyId: agency.GetAgencyId(), + Status: membershipStatusActive, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + owner := users[agency.GetOwnerUserId()] + parentBD := users[agency.GetParentBdUserId()] + items = append(items, map[string]any{ + "agency": hostAgencyFromProto(agency), + "owner": owner, + "parent_bd": parentBD, + "host_count": len(membersResp.GetMemberships()), + "created_at_ms": agency.GetCreatedAtMs(), + }) + } + httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": len(items)}) +} + +func (h *Handler) inviteBDLeaderBD(writer http.ResponseWriter, request *http.Request) { + h.inviteBDLeaderRole(writer, request, "bd") +} + +func (h *Handler) inviteBDLeaderAgency(writer http.ResponseWriter, request *http.Request) { + h.inviteBDLeaderRole(writer, request, "agency") +} + +func (h *Handler) inviteBDLeaderRole(writer http.ResponseWriter, request *http.Request, role string) { + userID := auth.UserIDFromContext(request.Context()) + if _, ok := h.resolveActiveBDLeader(writer, request, userID); !ok { + return + } + var body map[string]any + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := stringJSONValue(body["command_id"]) + targetUserID := int64JSONValue(body["target_user_id"]) + if commandID == "" || targetUserID <= 0 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + + if role == "bd" { + resp, err := h.userHostClient.InviteBD(request.Context(), &userv1.InviteBDRequest{ + Meta: httpkit.UserMeta(request, ""), + CommandId: commandID, + InviterUserId: userID, + TargetUserId: targetUserID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{"invitation": roleInvitationData(resp.GetInvitation())}) + return + } + + agencyName := stringJSONValue(body["agency_name"]) + if agencyName == "" { + users, err := h.userProfiles(request, []int64{targetUserID}) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + target := users[targetUserID] + agencyName = firstBDLeaderNonBlank(target.Username, target.DisplayUserID, int64String(targetUserID)) + } + resp, err := h.userHostClient.InviteAgency(request.Context(), &userv1.InviteAgencyRequest{ + Meta: httpkit.UserMeta(request, ""), + CommandId: commandID, + InviterUserId: userID, + TargetUserId: targetUserID, + AgencyName: agencyName, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{"invitation": roleInvitationData(resp.GetInvitation())}) +} + +func (h *Handler) resolveActiveBDLeader(writer http.ResponseWriter, request *http.Request, userID int64) (*userv1.BDProfile, bool) { + if h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return nil, false + } + resp, err := h.userHostClient.GetBDProfile(request.Context(), &userv1.GetBDProfileRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return nil, false + } + profile := resp.GetBdProfile() + if profile == nil || profile.GetRole() != "bd_leader" || profile.GetStatus() != bdStatusActive { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return nil, false + } + return profile, true +} + +func bdLeaderProfileFromProto(profile *userv1.BDProfile) bdLeaderProfileData { + if profile == nil { + return bdLeaderProfileData{} + } + return bdLeaderProfileData{ + UserID: int64String(profile.GetUserId()), + Role: profile.GetRole(), + RegionID: profile.GetRegionId(), + ParentLeaderUserID: int64String(profile.GetParentLeaderUserId()), + Status: profile.GetStatus(), + CreatedByUserID: int64String(profile.GetCreatedByUserId()), + CreatedAtMS: profile.GetCreatedAtMs(), + UpdatedAtMS: profile.GetUpdatedAtMs(), + } +} + +func roleInvitationData(invitation *userv1.RoleInvitation) map[string]any { + if invitation == nil { + return map[string]any{} + } + return map[string]any{ + "invitation_id": int64String(invitation.GetInvitationId()), + "command_id": invitation.GetCommandId(), + "invitation_type": invitation.GetInvitationType(), + "status": invitation.GetStatus(), + "inviter_user_id": int64String(invitation.GetInviterUserId()), + "target_user_id": int64String(invitation.GetTargetUserId()), + "region_id": invitation.GetRegionId(), + "agency_name": invitation.GetAgencyName(), + "parent_bd_user_id": int64String(invitation.GetParentBdUserId()), + "parent_leader_user_id": int64String(invitation.GetParentLeaderUserId()), + "processed_by_user_id": int64String(invitation.GetProcessedByUserId()), + "process_reason": invitation.GetProcessReason(), + "processed_at_ms": invitation.GetProcessedAtMs(), + "created_at_ms": invitation.GetCreatedAtMs(), + "updated_at_ms": invitation.GetUpdatedAtMs(), + } +} + +func queryPageSize(request *http.Request, fallback int) int { + value, _ := strconv.Atoi(strings.TrimSpace(request.URL.Query().Get("page_size"))) + if value <= 0 { + value = fallback + } + if value > 100 { + return 100 + } + return value +} + +func stringJSONValue(value any) string { + switch v := value.(type) { + case string: + return strings.TrimSpace(v) + case float64: + return strconv.FormatInt(int64(v), 10) + case int64: + return strconv.FormatInt(v, 10) + case int: + return strconv.Itoa(v) + default: + return "" + } +} + +func int64JSONValue(value any) int64 { + switch v := value.(type) { + case string: + parsed, _ := strconv.ParseInt(strings.TrimSpace(v), 10, 64) + return parsed + case float64: + return int64(v) + case int64: + return v + case int: + return int64(v) + default: + return 0 + } +} + +func firstBDLeaderNonBlank(values ...string) string { + for _, value := range values { + if trimmed := strings.TrimSpace(value); trimmed != "" { + return trimmed + } + } + return "-" +} diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index 1411a46b..a94dcdd9 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -63,6 +63,11 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { ListAgencyCenterApplications: h.listAgencyCenterApplications, ReviewAgencyCenterApplication: h.reviewAgencyCenterApplication, RemoveAgencyCenterHost: h.removeAgencyCenterHost, + GetBDLeaderCenterOverview: h.getBDLeaderCenterOverview, + ListBDLeaderCenterBDs: h.listBDLeaderCenterBDs, + ListBDLeaderCenterAgencies: h.listBDLeaderCenterAgencies, + InviteBDLeaderBD: h.inviteBDLeaderBD, + InviteBDLeaderAgency: h.inviteBDLeaderAgency, CompleteMyOnboarding: h.completeMyOnboarding, UpdateMyProfile: h.updateMyProfile, ChangeMyCountry: h.changeMyCountry, diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index 51158198..f972624a 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -79,6 +79,9 @@ type InviteAgencyCommand struct { InviterUserID int64 TargetUserID int64 AgencyName string + AgencyID int64 + MembershipID int64 + EventID int64 NowMs int64 } @@ -95,9 +98,24 @@ type InviteBDCommand struct { InvitationID int64 InviterUserID int64 TargetUserID int64 + EventID int64 NowMs int64 } +// ListBDLeaderBDsCommand 描述 BD Leader 查询直属 BD 列表的条件。 +type ListBDLeaderBDsCommand struct { + LeaderUserID int64 + Status string + PageSize int +} + +// ListBDLeaderAgenciesCommand 描述 BD Leader 查询下级 Agency 列表的条件。 +type ListBDLeaderAgenciesCommand struct { + LeaderUserID int64 + Status string + PageSize int +} + // ProcessRoleInvitationInput 是处理角色邀请的外部输入。 type ProcessRoleInvitationInput struct { CommandID string diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index 9fa9a910..8d2c2e0a 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -20,6 +20,8 @@ type Repository interface { KickAgencyHost(ctx context.Context, command KickAgencyHostCommand) (hostdomain.KickAgencyHostResult, error) InviteAgency(ctx context.Context, command InviteAgencyCommand) (hostdomain.RoleInvitation, error) InviteBD(ctx context.Context, command InviteBDCommand) (hostdomain.RoleInvitation, error) + ListBDLeaderBDs(ctx context.Context, command ListBDLeaderBDsCommand) ([]hostdomain.BDProfile, error) + ListBDLeaderAgencies(ctx context.Context, command ListBDLeaderAgenciesCommand) ([]hostdomain.Agency, error) ProcessRoleInvitation(ctx context.Context, command ProcessRoleInvitationCommand) (hostdomain.ProcessRoleInvitationResult, error) CreateBDLeader(ctx context.Context, command CreateBDLeaderCommand) (hostdomain.BDProfile, error) CreateBD(ctx context.Context, command CreateBDCommand) (hostdomain.BDProfile, error) @@ -196,12 +198,12 @@ func (s *Service) GetAgency(ctx context.Context, agencyID int64) (hostdomain.Age return s.repository.GetAgency(ctx, agencyID) } -// InviteAgency 创建邀请用户成为 Agency 拥有者的待处理邀请。 +// InviteAgency 由 BD 直接创建用户的 Agency owner 身份,不再等待目标用户确认。 func (s *Service) InviteAgency(ctx context.Context, command InviteAgencyInput) (hostdomain.RoleInvitation, error) { if err := s.requireWriteDependencies(); err != nil { return hostdomain.RoleInvitation{}, err } - // Agency 名称在邀请创建时固化,接受时用这份快照创建 Agency。 + // Agency 名称在邀请动作里固化;持久化层会在同一事务中写 accepted invitation、Agency、owner Host 和 owner membership。 agencyName := strings.TrimSpace(command.AgencyName) if strings.TrimSpace(command.CommandID) == "" || command.InviterUserID <= 0 || command.TargetUserID <= 0 || agencyName == "" { return hostdomain.RoleInvitation{}, xerr.New(xerr.InvalidArgument, "command_id, inviter_user_id, target_user_id and agency_name are required") @@ -214,16 +216,19 @@ func (s *Service) InviteAgency(ctx context.Context, command InviteAgencyInput) ( InviterUserID: command.InviterUserID, TargetUserID: command.TargetUserID, AgencyName: agencyName, + AgencyID: s.idGenerator.NewInt64(), + MembershipID: s.idGenerator.NewInt64(), + EventID: s.nextEventIDRange(3), NowMs: nowMs, }) } -// InviteBD 创建 BD 负责人邀请用户成为 BD 的待处理邀请。 +// InviteBD 由 BD Leader 直接创建用户的 BD 身份,不再等待目标用户确认。 func (s *Service) InviteBD(ctx context.Context, command InviteBDInput) (hostdomain.RoleInvitation, error) { if err := s.requireWriteDependencies(); err != nil { return hostdomain.RoleInvitation{}, err } - // 负责人身份、区域、目标是否已有 BD 都交给持久化层在同一事务中校验。 + // 负责人身份、区域、目标是否已有 BD 都交给持久化层在同一事务中校验,并和 accepted invitation 一起提交。 if strings.TrimSpace(command.CommandID) == "" || command.InviterUserID <= 0 || command.TargetUserID <= 0 { return hostdomain.RoleInvitation{}, xerr.New(xerr.InvalidArgument, "command_id, inviter_user_id and target_user_id are required") } @@ -234,10 +239,41 @@ func (s *Service) InviteBD(ctx context.Context, command InviteBDInput) (hostdoma InvitationID: s.idGenerator.NewInt64(), InviterUserID: command.InviterUserID, TargetUserID: command.TargetUserID, + EventID: s.idGenerator.NewInt64(), NowMs: nowMs, }) } +// ListBDLeaderBDs 返回当前 BD Leader 直属的有效 BD 列表。 +func (s *Service) ListBDLeaderBDs(ctx context.Context, command ListBDLeaderBDsCommand) ([]hostdomain.BDProfile, error) { + if s.repository == nil { + return nil, xerr.New(xerr.Unavailable, "host repository is not configured") + } + if command.LeaderUserID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "leader_user_id is required") + } + return s.repository.ListBDLeaderBDs(ctx, ListBDLeaderBDsCommand{ + LeaderUserID: command.LeaderUserID, + Status: normalizeStatus(command.Status), + PageSize: normalizePageSize(command.PageSize), + }) +} + +// ListBDLeaderAgencies 返回当前 BD Leader 团队下的 Agency 列表。 +func (s *Service) ListBDLeaderAgencies(ctx context.Context, command ListBDLeaderAgenciesCommand) ([]hostdomain.Agency, error) { + if s.repository == nil { + return nil, xerr.New(xerr.Unavailable, "host repository is not configured") + } + if command.LeaderUserID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "leader_user_id is required") + } + return s.repository.ListBDLeaderAgencies(ctx, ListBDLeaderAgenciesCommand{ + LeaderUserID: command.LeaderUserID, + Status: normalizeStatus(command.Status), + PageSize: normalizePageSize(command.PageSize), + }) +} + // ProcessRoleInvitation 接受、拒绝或取消角色邀请。 func (s *Service) ProcessRoleInvitation(ctx context.Context, command ProcessRoleInvitationInput) (hostdomain.ProcessRoleInvitationResult, error) { if err := s.requireWriteDependencies(); err != nil { @@ -576,3 +612,13 @@ func normalizeAction(value string) string { func normalizeStatus(value string) string { return strings.ToLower(strings.TrimSpace(value)) } + +func normalizePageSize(value int) int { + if value <= 0 { + return 20 + } + if value > 100 { + return 100 + } + return value +} diff --git a/services/user-service/internal/service/host/service_test.go b/services/user-service/internal/service/host/service_test.go index 9462e76a..8ab15cdc 100644 --- a/services/user-service/internal/service/host/service_test.go +++ b/services/user-service/internal/service/host/service_test.go @@ -195,27 +195,23 @@ func TestAcceptAgencyInvitationCreatesOwnerHostAndRejectsActiveHost(t *testing.T if err != nil { t.Fatalf("InviteAgency failed: %v", err) } - accepted, err := svc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ - CommandID: "accept-agency-601", - ActorUserID: 601, - InvitationID: invitation.InvitationID, - Action: hostdomain.InvitationActionAccept, - }) - if err != nil { - t.Fatalf("accept agency invitation failed: %v", err) + if invitation.Status != hostdomain.InvitationStatusAccepted { + t.Fatalf("agency invitation should be accepted immediately: %+v", invitation) } - if accepted.Agency.OwnerUserID != 601 || accepted.HostProfile.CurrentAgencyID != accepted.Agency.AgencyID || accepted.Membership.MembershipType != hostdomain.MembershipTypeOwner { - t.Fatalf("owner agency facts mismatch: %+v", accepted) - } - - blockedInvitation, err := svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ - CommandID: "invite-agency-602", - InviterUserID: 501, - TargetUserID: 602, - AgencyName: "Blocked Agency", - }) + summary, err := svc.GetUserRoleSummary(ctx, 601) if err != nil { - t.Fatalf("InviteAgency for later active host failed: %v", err) + t.Fatalf("GetUserRoleSummary failed: %v", err) + } + agency, err := svc.GetAgency(ctx, summary.AgencyID) + if err != nil { + t.Fatalf("GetAgency failed: %v", err) + } + hostProfile, err := svc.GetHostProfile(ctx, 601) + if err != nil { + t.Fatalf("GetHostProfile failed: %v", err) + } + if !summary.IsAgency || !summary.IsHost || agency.OwnerUserID != 601 || hostProfile.CurrentAgencyID != agency.AgencyID { + t.Fatalf("owner agency facts mismatch: summary=%+v agency=%+v host=%+v", summary, agency, hostProfile) } repository.PutHostProfile(hostdomain.HostProfile{ UserID: 602, @@ -223,14 +219,14 @@ func TestAcceptAgencyInvitationCreatesOwnerHostAndRejectsActiveHost(t *testing.T RegionID: 10, Source: "test", }) - _, err = svc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ - CommandID: "accept-agency-602", - ActorUserID: 602, - InvitationID: blockedInvitation.InvitationID, - Action: hostdomain.InvitationActionAccept, + _, err = svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ + CommandID: "invite-agency-602", + InviterUserID: 501, + TargetUserID: 602, + AgencyName: "Blocked Agency", }) if got := xerr.CodeOf(err); got != xerr.Conflict { - t.Fatalf("active host must not accept agency invitation: got %s err=%v", got, err) + t.Fatalf("active host must not become agency owner: got %s err=%v", got, err) } } @@ -255,17 +251,15 @@ func TestAcceptBDInvitationDoesNotCreateHostProfile(t *testing.T) { if err != nil { t.Fatalf("InviteBD failed: %v", err) } - accepted, err := svc.ProcessRoleInvitation(ctx, hostservice.ProcessRoleInvitationInput{ - CommandID: "accept-bd-702", - ActorUserID: 702, - InvitationID: invitation.InvitationID, - Action: hostdomain.InvitationActionAccept, - }) - if err != nil { - t.Fatalf("accept bd invitation failed: %v", err) + if invitation.Status != hostdomain.InvitationStatusAccepted { + t.Fatalf("bd invitation should be accepted immediately: %+v", invitation) } - if accepted.BDProfile.UserID != 702 || accepted.BDProfile.Role != hostdomain.BDRoleBD || accepted.BDProfile.ParentLeaderUserID != 701 { - t.Fatalf("bd profile mismatch: %+v", accepted.BDProfile) + bdProfile, err := svc.GetBDProfile(ctx, 702) + if err != nil { + t.Fatalf("GetBDProfile failed: %v", err) + } + if bdProfile.UserID != 702 || bdProfile.Role != hostdomain.BDRoleBD || bdProfile.ParentLeaderUserID != 701 { + t.Fatalf("bd profile mismatch: %+v", bdProfile) } if _, err := svc.GetHostProfile(ctx, 702); xerr.CodeOf(err) != xerr.NotFound { t.Fatalf("becoming bd must not create host profile: err=%v", err) @@ -710,11 +704,11 @@ func TestGetUserRoleSummaryAggregatesRolesAndPendingInvitations(t *testing.T) { if !summary.IsHost || !summary.IsAgency || !summary.IsManager || !summary.IsBD || !summary.IsBDLeader || !summary.IsCoinSeller || summary.AgencyID != 933 || summary.BDID != 931 { t.Fatalf("role summary mismatch: %+v", summary) } - pending, err := svc.GetUserRoleSummary(ctx, 932) + directBD, err := svc.GetUserRoleSummary(ctx, 932) if err != nil { - t.Fatalf("GetUserRoleSummary pending failed: %v", err) + t.Fatalf("GetUserRoleSummary direct bd failed: %v", err) } - if pending.PendingRoleInvitations != 1 || pending.IsHost || pending.IsBD { - t.Fatalf("pending role summary mismatch: %+v", pending) + if directBD.PendingRoleInvitations != 0 || directBD.IsHost || !directBD.IsBD || directBD.BDID != 932 { + t.Fatalf("direct bd role summary mismatch: %+v", directBD) } } diff --git a/services/user-service/internal/storage/mysql/host/invitations.go b/services/user-service/internal/storage/mysql/host/invitations.go index a78b88a0..e6b2c604 100644 --- a/services/user-service/internal/storage/mysql/host/invitations.go +++ b/services/user-service/internal/storage/mysql/host/invitations.go @@ -69,7 +69,7 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit InvitationID: command.InvitationID, CommandID: command.CommandID, InvitationType: hostdomain.InvitationTypeAgency, - Status: hostdomain.InvitationStatusPending, + Status: hostdomain.InvitationStatusAccepted, InviterUserID: command.InviterUserID, InviterBDUserID: inviter.UserID, TargetUserID: command.TargetUserID, @@ -77,13 +77,42 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit AgencyName: command.AgencyName, ParentBDUserID: inviter.UserID, ParentLeaderUserID: parentLeaderUserID, + ProcessedByUserID: command.InviterUserID, + ProcessReason: "direct_invite", + ProcessedAtMs: command.NowMs, CreatedAtMs: command.NowMs, UpdatedAtMs: command.NowMs, } - // 待处理邀请与 command_result 同事务写入,保证重复提交能按 invitation_id 回放。 + // 新邀请不再等待目标用户确认:accepted invitation、Agency、owner Host 和 owner membership 必须同事务提交。 if err := insertRoleInvitation(ctx, tx, invitation); err != nil { return hostdomain.RoleInvitation{}, mapHostDuplicateError(err) } + result := hostdomain.ProcessRoleInvitationResult{Invitation: invitation} + created, err := r.acceptAgencyInvitation(ctx, tx, hostservice.ProcessRoleInvitationCommand{ + CommandID: command.CommandID, + ActorUserID: command.InviterUserID, + InvitationID: command.InvitationID, + Action: hostdomain.InvitationActionAccept, + Reason: "direct_invite", + AgencyID: command.AgencyID, + MembershipID: command.MembershipID, + EventID: command.EventID, + NowMs: command.NowMs, + }, &invitation, &result) + if err != nil { + return hostdomain.RoleInvitation{}, err + } + if created { + if err := insertHostOutbox(ctx, tx, command.EventID, "HostCreated", "host_profile", invitation.TargetUserID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err + } + if err := insertHostOutbox(ctx, tx, command.EventID+1, "AgencyCreated", "agency", command.AgencyID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err + } + if err := insertHostOutbox(ctx, tx, command.EventID+2, "AgencyMembershipChanged", "agency_membership", command.MembershipID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err + } + } if err := insertCommandResult(ctx, tx, hostdomain.CommandResult{ CommandID: command.CommandID, CommandType: hostdomain.CommandTypeInviteAgency, @@ -145,19 +174,37 @@ func (r *Repository) InviteBD(ctx context.Context, command hostservice.InviteBDC InvitationID: command.InvitationID, CommandID: command.CommandID, InvitationType: hostdomain.InvitationTypeBD, - Status: hostdomain.InvitationStatusPending, + Status: hostdomain.InvitationStatusAccepted, InviterUserID: command.InviterUserID, InviterBDUserID: inviter.UserID, TargetUserID: command.TargetUserID, RegionID: inviter.RegionID, ParentLeaderUserID: inviter.UserID, + ProcessedByUserID: command.InviterUserID, + ProcessReason: "direct_invite", + ProcessedAtMs: command.NowMs, CreatedAtMs: command.NowMs, UpdatedAtMs: command.NowMs, } - // 这里只创建待处理邀请;真正的 BD 身份行在目标用户接受时再落库。 + // 新 BD 邀请直接创建 BD 身份;accepted invitation 只作为审计事实和幂等回放结果。 if err := insertRoleInvitation(ctx, tx, invitation); err != nil { return hostdomain.RoleInvitation{}, mapHostDuplicateError(err) } + result := hostdomain.ProcessRoleInvitationResult{Invitation: invitation} + if err := r.acceptBDInvitation(ctx, tx, hostservice.ProcessRoleInvitationCommand{ + CommandID: command.CommandID, + ActorUserID: command.InviterUserID, + InvitationID: command.InvitationID, + Action: hostdomain.InvitationActionAccept, + Reason: "direct_invite", + EventID: command.EventID, + NowMs: command.NowMs, + }, &invitation, &result); err != nil { + return hostdomain.RoleInvitation{}, err + } + if err := insertHostOutbox(ctx, tx, command.EventID, "BDCreated", "bd_profile", invitation.TargetUserID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err + } if err := insertCommandResult(ctx, tx, hostdomain.CommandResult{ CommandID: command.CommandID, CommandType: hostdomain.CommandTypeInviteBD, diff --git a/services/user-service/internal/storage/mysql/host/queries.go b/services/user-service/internal/storage/mysql/host/queries.go index d592af01..ddf1234e 100644 --- a/services/user-service/internal/storage/mysql/host/queries.go +++ b/services/user-service/internal/storage/mysql/host/queries.go @@ -281,6 +281,50 @@ func (r *Repository) HasActiveAgencyOwner(ctx context.Context, userID int64) (in return agency.AgencyID, true, nil } +// ListBDLeaderBDs 读取 BD Leader 直属 BD;调用前先校验 leader 当前仍有效,避免停用后继续读取团队数据。 +func (r *Repository) ListBDLeaderBDs(ctx context.Context, command hostservice.ListBDLeaderBDsCommand) ([]hostdomain.BDProfile, error) { + leader, err := queryBDProfile(ctx, r.db, "WHERE user_id = ?", command.LeaderUserID) + if err != nil { + return nil, err + } + if leader.Status != hostdomain.BDStatusActive || leader.Role != hostdomain.BDRoleLeader { + return nil, xerr.New(xerr.PermissionDenied, "leader is not active") + } + status := command.Status + if status == "" { + status = hostdomain.BDStatusActive + } + clause, args := appScopedClause(ctx, "WHERE role = ? AND parent_leader_user_id = ? AND status = ? ORDER BY created_at_ms DESC, user_id DESC LIMIT ?", hostdomain.BDRoleBD, command.LeaderUserID, status, command.PageSize) + return queryBDProfiles(ctx, r.db, clause, args...) +} + +// ListBDLeaderAgencies 读取 BD Leader 团队 Agency;包含直属 leader 自己创建的 Agency 和下属 BD 创建的 Agency。 +func (r *Repository) ListBDLeaderAgencies(ctx context.Context, command hostservice.ListBDLeaderAgenciesCommand) ([]hostdomain.Agency, error) { + leader, err := queryBDProfile(ctx, r.db, "WHERE user_id = ?", command.LeaderUserID) + if err != nil { + return nil, err + } + if leader.Status != hostdomain.BDStatusActive || leader.Role != hostdomain.BDRoleLeader { + return nil, xerr.New(xerr.PermissionDenied, "leader is not active") + } + status := command.Status + if status == "" { + status = hostdomain.AgencyStatusActive + } + clause, args := appScopedClause(ctx, `WHERE status = ? AND ( + parent_bd_user_id = ? + OR parent_bd_user_id IN ( + SELECT user_id + FROM bd_profiles + WHERE app_code = agencies.app_code + AND role = ? + AND parent_leader_user_id = ? + AND status = ? + ) + ) ORDER BY created_at_ms DESC, agency_id DESC LIMIT ?`, status, command.LeaderUserID, hostdomain.BDRoleBD, command.LeaderUserID, hostdomain.BDStatusActive, command.PageSize) + return queryAgencies(ctx, r.db, clause, args...) +} + // ListAgencyMembers 读取 Agency 成员关系列表。 func (r *Repository) ListAgencyMembers(ctx context.Context, agencyID int64, status string) ([]hostdomain.AgencyMembership, error) { query := fmt.Sprintf(`SELECT %s FROM agency_memberships WHERE app_code = ? AND agency_id = ?`, agencyMembershipColumns) @@ -373,6 +417,24 @@ func queryAgency(ctx context.Context, q sqlQueryer, clause string, args ...any) return agency, err } +func queryAgencies(ctx context.Context, q sqlQueryer, clause string, args ...any) ([]hostdomain.Agency, error) { + rows, err := q.QueryContext(ctx, fmt.Sprintf(`SELECT %s FROM agencies %s`, agencyColumns, clause), args...) + if err != nil { + return nil, err + } + defer rows.Close() + + agencies := make([]hostdomain.Agency, 0) + for rows.Next() { + agency, err := scanAgency(rows) + if err != nil { + return nil, err + } + agencies = append(agencies, agency) + } + return agencies, rows.Err() +} + func queryActiveAgencyByOwner(ctx context.Context, q sqlQueryer, ownerUserID int64, lock bool) (hostdomain.Agency, bool, error) { clause := "WHERE owner_user_id = ? AND status = ?" if lock { @@ -461,6 +523,24 @@ func queryBDProfile(ctx context.Context, q sqlQueryer, clause string, args ...an return profile, err } +func queryBDProfiles(ctx context.Context, q sqlQueryer, clause string, args ...any) ([]hostdomain.BDProfile, error) { + rows, err := q.QueryContext(ctx, fmt.Sprintf(`SELECT %s FROM bd_profiles %s`, bdProfileColumns, clause), args...) + if err != nil { + return nil, err + } + defer rows.Close() + + profiles := make([]hostdomain.BDProfile, 0) + for rows.Next() { + profile, err := scanBDProfile(rows) + if err != nil { + return nil, err + } + profiles = append(profiles, profile) + } + return profiles, rows.Err() +} + func queryBDProfileMaybe(ctx context.Context, q sqlQueryer, userID int64, lock bool) (hostdomain.BDProfile, bool, error) { clause := "WHERE user_id = ? AND status = ?" if lock { diff --git a/services/user-service/internal/transport/grpc/host.go b/services/user-service/internal/transport/grpc/host.go index 1e9f2a16..33ce2d29 100644 --- a/services/user-service/internal/transport/grpc/host.go +++ b/services/user-service/internal/transport/grpc/host.go @@ -98,7 +98,7 @@ func (s *Server) KickAgencyHost(ctx context.Context, req *userv1.KickAgencyHostR }, nil } -// InviteAgency 创建用户成为 Agency 拥有者的邀请。 +// InviteAgency 直接创建用户成为 Agency owner 的关系事实,不再等待目标用户确认。 func (s *Server) InviteAgency(ctx context.Context, req *userv1.InviteAgencyRequest) (*userv1.InviteAgencyResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) @@ -118,7 +118,7 @@ func (s *Server) InviteAgency(ctx context.Context, req *userv1.InviteAgencyReque return &userv1.InviteAgencyResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } -// InviteBD 创建用户成为 BD 的邀请,只有 BD 负责人可调用。 +// InviteBD 直接创建用户成为 BD 的关系事实,只有 BD 负责人可调用。 func (s *Server) InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) { if s.hostSvc == nil { return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) @@ -137,6 +137,50 @@ func (s *Server) InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*us return &userv1.InviteBDResponse{Invitation: toProtoRoleInvitation(invitation)}, nil } +// ListBDLeaderBDs 返回当前 BD Leader 直属 BD 列表。 +func (s *Server) ListBDLeaderBDs(ctx context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) { + if s.hostSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) + } + ctx = contextWithApp(ctx, req.GetMeta()) + profiles, err := s.hostSvc.ListBDLeaderBDs(ctx, hostservice.ListBDLeaderBDsCommand{ + LeaderUserID: req.GetLeaderUserId(), + Status: req.GetStatus(), + PageSize: int(req.GetPageSize()), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + + resp := &userv1.ListBDLeaderBDsResponse{BdProfiles: make([]*userv1.BDProfile, 0, len(profiles))} + for _, profile := range profiles { + resp.BdProfiles = append(resp.BdProfiles, toProtoBDProfile(profile)) + } + return resp, nil +} + +// ListBDLeaderAgencies 返回当前 BD Leader 团队下的 Agency 列表。 +func (s *Server) ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) { + if s.hostSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) + } + ctx = contextWithApp(ctx, req.GetMeta()) + agencies, err := s.hostSvc.ListBDLeaderAgencies(ctx, hostservice.ListBDLeaderAgenciesCommand{ + LeaderUserID: req.GetLeaderUserId(), + Status: req.GetStatus(), + PageSize: int(req.GetPageSize()), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + + resp := &userv1.ListBDLeaderAgenciesResponse{Agencies: make([]*userv1.Agency, 0, len(agencies))} + for _, agency := range agencies { + resp.Agencies = append(resp.Agencies, toProtoAgency(agency)) + } + return resp, nil +} + // ProcessRoleInvitation 处理 Agency 或 BD 邀请。 func (s *Server) ProcessRoleInvitation(ctx context.Context, req *userv1.ProcessRoleInvitationRequest) (*userv1.ProcessRoleInvitationResponse, error) { if s.hostSvc == nil { From 0ad227187f42574f74ef5aec4963194c372c24f6 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 21:26:47 +0800 Subject: [PATCH 10/28] Enforce room cover and device registration uniqueness --- api/proto/room/v1/room.pb.go | 4 +-- api/proto/room/v1/room.proto | 4 +-- .../创建房间与IM入群Flutter对接.md | 3 +- docs/语音房区域房间列表架构.md | 4 +-- docs/语音房基础闭环实现.md | 2 +- docs/进房与重连开发需求.md | 4 +-- pkg/xerr/catalog.go | 6 ++++ pkg/xerr/errors.go | 2 ++ .../mysql/036_user_register_device_unique.sql | 5 +++ .../internal/transport/http/response_test.go | 17 +++++----- .../transport/http/roomapi/room_handler.go | 4 +-- .../http/roomapi/room_handler_test.go | 23 +++++++++++++ .../internal/room/command/command.go | 2 +- .../internal/room/service/background_test.go | 2 ++ .../internal/room/service/create_room.go | 6 ++-- .../room/service/create_room_real_im_test.go | 1 + .../internal/room/service/create_room_test.go | 31 +++++++++++++++++ .../internal/room/service/follow_test.go | 1 + .../internal/room/service/kick_test.go | 4 +++ .../internal/room/service/lock_test.go | 1 + .../internal/room/service/pin_test.go | 1 + .../room/service/room_treasure_test.go | 1 + .../internal/transport/grpc/server_test.go | 1 + .../deploy/mysql/initdb/001_user_service.sql | 1 + .../internal/service/auth/service.go | 2 ++ .../internal/service/auth/service_test.go | 33 +++++++++++++++++++ .../internal/service/auth/third_party.go | 20 +++++++++++ .../internal/storage/mysql/auth/common.go | 2 ++ .../storage/mysql/auth/third_party.go | 19 +++++++++++ .../internal/testutil/mysqltest/mysqltest.go | 5 +++ 30 files changed, 186 insertions(+), 25 deletions(-) create mode 100644 scripts/mysql/036_user_register_device_unique.sql diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 2fca303c..6c35bdb5 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -3313,7 +3313,7 @@ func (x *SetRoomBackgroundResponse) GetBackground() *RoomBackgroundImage { } // CreateRoomRequest 创建一个新的房间执行单元。 -// 必填语义:meta.room_id、meta.command_id、meta.actor_user_id、mode 和 room_name。 +// 必填语义:meta.room_id、meta.command_id、meta.actor_user_id、mode、room_name 和 room_avatar。 // 同一个 meta.actor_user_id 只能作为 owner 创建一个房间;重复创建返回 Conflict。 type CreateRoomRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -3326,7 +3326,7 @@ type CreateRoomRequest struct { VisibleRegionId int64 `protobuf:"varint,4,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` // room_name 是客户端创建房间时填写的展示名称,room-service 会写入 RoomSnapshot.room_ext["title"]。 RoomName string `protobuf:"bytes,5,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"` - // room_avatar 是客户端可选上传的展示头像;为空时 room-service 写入默认系统头像。 + // room_avatar 是客户端上传的房间封面;创建时必填,room-service 会写入 RoomSnapshot.room_ext["cover_url"]。 RoomAvatar string `protobuf:"bytes,6,opt,name=room_avatar,json=roomAvatar,proto3" json:"room_avatar,omitempty"` // room_description 是房间简介,只作为房间扩展资料保存,不参与 Room Cell 高频状态决策。 RoomDescription string `protobuf:"bytes,7,opt,name=room_description,json=roomDescription,proto3" json:"room_description,omitempty"` diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index 216a684f..c5ee3ad0 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -387,7 +387,7 @@ message SetRoomBackgroundResponse { } // CreateRoomRequest 创建一个新的房间执行单元。 -// 必填语义:meta.room_id、meta.command_id、meta.actor_user_id、mode 和 room_name。 +// 必填语义:meta.room_id、meta.command_id、meta.actor_user_id、mode、room_name 和 room_avatar。 // 同一个 meta.actor_user_id 只能作为 owner 创建一个房间;重复创建返回 Conflict。 message CreateRoomRequest { RequestMeta meta = 1; @@ -399,7 +399,7 @@ message CreateRoomRequest { int64 visible_region_id = 4; // room_name 是客户端创建房间时填写的展示名称,room-service 会写入 RoomSnapshot.room_ext["title"]。 string room_name = 5; - // room_avatar 是客户端可选上传的展示头像;为空时 room-service 写入默认系统头像。 + // room_avatar 是客户端上传的房间封面;创建时必填,room-service 会写入 RoomSnapshot.room_ext["cover_url"]。 string room_avatar = 6; // room_description 是房间简介,只作为房间扩展资料保存,不参与 Room Cell 高频状态决策。 string room_description = 7; diff --git a/docs/flutter对接/创建房间与IM入群Flutter对接.md b/docs/flutter对接/创建房间与IM入群Flutter对接.md index 3a3546ab..f19143e7 100644 --- a/docs/flutter对接/创建房间与IM入群Flutter对接.md +++ b/docs/flutter对接/创建房间与IM入群Flutter对接.md @@ -101,7 +101,7 @@ Content-Type: application/json | `seat_count` | 否 | int | 不传或传 `0` 使用后台默认麦位数;正数必须命中后台启用座位数。 | | `mode` | 是 | string | 当前传 `voice`。 | | `room_name` | 是 | string | 房间标题,最长 128 个字符。 | -| `room_avatar` | 否 | string | 房间头像 URL;为空时服务端写默认头像。 | +| `room_avatar` | 是 | string | 房间封面 URL;不传或空字符串会返回 `INVALID_ARGUMENT`。 | | `room_description` | 否 | string | 房间简介,最长 512 个字符。 | 成功响应: @@ -401,4 +401,3 @@ String newCommandId(String action) { | `/rooms/join` 返回 `PERMISSION_DENIED` | 可能被 ban 或锁房密码错误;不调用 `joinGroup`。 | | IM `joinGroup` 群不存在 | 当前不应出现;记录 `request_id`、`room_id`、`group_id` 上报。 | | IM 登录票据过期 | 重新调用 `/api/v1/im/usersig` 并 `login`。 | - diff --git a/docs/语音房区域房间列表架构.md b/docs/语音房区域房间列表架构.md index 56e9b6f8..6ed581a7 100644 --- a/docs/语音房区域房间列表架构.md +++ b/docs/语音房区域房间列表架构.md @@ -130,7 +130,7 @@ sequenceDiagram participant U as user-service participant R as room-service - C->>G: POST /api/v1/rooms/create(room_name, room_avatar?, room_description?) + C->>G: POST /api/v1/rooms/create(room_name, room_avatar, room_description?) G->>U: GetUser(actor_user_id) U-->>G: region_id, display_user_id G->>G: generate room_id = app_code + uuid @@ -146,7 +146,7 @@ sequenceDiagram - 客户端不能提交 `room_id`;gateway 按当前 `app_code` 生成 `_` 作为房间长 ID。 - `room_short_id` 首版直接等于创建者当前 `display_user_id`,用于搜索、分享和展示。 - 同一个登录用户只能作为 owner 创建一个房间;room-service 按 `RequestMeta.actor_user_id` 判定 owner,不能通过更换 `room_id` 创建第二个房间。 -- 客户端必须提交 `room_name`;`room_avatar` 为空时由 room-service 写默认系统头像,`room_description` 只进入 `RoomExt`。 +- 客户端必须提交 `room_name` 和 `room_avatar`;`room_description` 只进入 `RoomExt`。 - `visible_region_id` 来自创建者当前 `users.region_id`。 - 创建者没有区域时写 `0`,进入 `GLOBAL` 列表桶。 - 房间创建成功后,创建者改国家不自动修改房间区域。 diff --git a/docs/语音房基础闭环实现.md b/docs/语音房基础闭环实现.md index 73b640fc..199df601 100644 --- a/docs/语音房基础闭环实现.md +++ b/docs/语音房基础闭环实现.md @@ -83,7 +83,7 @@ sequenceDiagram U-->>G: access token with user_id G-->>C: token envelope - C->>G: POST /api/v1/rooms/create(room_name, room_avatar?, room_description?) + C->>G: POST /api/v1/rooms/create(room_name, room_avatar, room_description?) G->>R: CreateRoom(actor_user_id, room profile) R->>T: create_group(room_id) T-->>R: group ready diff --git a/docs/进房与重连开发需求.md b/docs/进房与重连开发需求.md index c1f32a30..a0d07c6c 100644 --- a/docs/进房与重连开发需求.md +++ b/docs/进房与重连开发需求.md @@ -75,12 +75,12 @@ Authorization: Bearer "command_id": "cmd_create_room_550e8400", "mode": "voice", "room_name": "周末语音房", - "room_avatar": "", + "room_avatar": "https://cdn.example/room.png", "room_description": "本房间用于轻量聊天和上麦互动" } ``` -正式客户端不应该传 `room_id`、`owner_user_id` 和 `host_user_id`。`command_id` 由客户端按创建房间动作生成,同一动作重试必须复用。gateway 必须从 access token 取当前 `user_id` 写入 `RequestMeta.actor_user_id`,并生成内部 `room_id`;room-service 使用该 actor 确定 owner 和默认 host。`seat_count` 可省略,省略或传 `0` 时使用后台默认座位数 `15`;传正数时必须命中后台启用座位数。`room_name` 必填,`room_avatar` 为空时写入默认系统头像,房间展示资料统一落在 `RoomExt`。 +正式客户端不应该传 `room_id`、`owner_user_id` 和 `host_user_id`。`command_id` 由客户端按创建房间动作生成,同一动作重试必须复用。gateway 必须从 access token 取当前 `user_id` 写入 `RequestMeta.actor_user_id`,并生成内部 `room_id`;room-service 使用该 actor 确定 owner 和默认 host。`seat_count` 可省略,省略或传 `0` 时使用后台默认座位数 `15`;传正数时必须命中后台启用座位数。`room_name` 和 `room_avatar` 必填,房间展示资料统一落在 `RoomExt`。 响应必须包含: diff --git a/pkg/xerr/catalog.go b/pkg/xerr/catalog.go index 7ae038f2..b1015397 100644 --- a/pkg/xerr/catalog.go +++ b/pkg/xerr/catalog.go @@ -63,6 +63,12 @@ var catalog = map[Code]Spec{ RegionCountryConflict: spec(codes.FailedPrecondition, httpStatusConflict, RegionCountryConflict, "conflict"), RegionDisabled: spec(codes.FailedPrecondition, httpStatusConflict, RegionDisabled, "conflict"), InvalidInviteCode: spec(codes.InvalidArgument, httpStatusBadRequest, InvalidInviteCode, "invalid argument"), + DeviceAlreadyRegistered: spec( + codes.FailedPrecondition, + httpStatusConflict, + DeviceAlreadyRegistered, + "conflict", + ), InsufficientBalance: spec(codes.FailedPrecondition, httpStatusConflict, InsufficientBalance, "insufficient balance"), DuplicateBillingCommand: spec(codes.AlreadyExists, httpStatusConflict, DuplicateBillingCommand, "conflict"), diff --git a/pkg/xerr/errors.go b/pkg/xerr/errors.go index f8bd5f55..0a2c6613 100644 --- a/pkg/xerr/errors.go +++ b/pkg/xerr/errors.go @@ -71,6 +71,8 @@ const ( RegionDisabled Code = "REGION_DISABLED" // InvalidInviteCode 表示邀请码不存在、停用、跨 App、邀请人不可用或用户尝试自邀。 InvalidInviteCode Code = "INVALID_INVITE_CODE" + // DeviceAlreadyRegistered 表示同一注册设备已经创建过账号,不能再次作为三方注册入口。 + DeviceAlreadyRegistered Code = "DEVICE_ALREADY_REGISTERED" // InsufficientBalance 表示钱包余额不足。 InsufficientBalance Code = "INSUFFICIENT_BALANCE" diff --git a/scripts/mysql/036_user_register_device_unique.sql b/scripts/mysql/036_user_register_device_unique.sql new file mode 100644 index 00000000..1d09ad94 --- /dev/null +++ b/scripts/mysql/036_user_register_device_unique.sql @@ -0,0 +1,5 @@ +USE hyapp_user; + +-- 同一个 App 内,一个非空注册设备号只能创建一个用户;NULL 仍用于没有注册设备快照的历史或测试行。 +ALTER TABLE users + ADD UNIQUE KEY uk_users_register_device_id (app_code, register_device_id); diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 5744270b..ecbcf971 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -5814,7 +5814,7 @@ func TestRoutesWriteInvalidJSONEnvelope(t *testing.T) { func TestCreateRoomIgnoresClientRoomIDAndGeneratesScopedRoomID(t *testing.T) { client := &fakeRoomClient{} router := NewHandlerWithClients(client, nil, nil, &fakeUserProfileClient{regionID: 1001}).Routes(auth.NewVerifier("secret")) - request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{"room_id":"room:1","command_id":"cmd-create-scoped","seat_count":10,"mode":"voice","room_name":"Lobby"}`))) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{"room_id":"room:1","command_id":"cmd-create-scoped","seat_count":10,"mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`))) request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) request.Header.Set("X-Request-ID", "req-generated-room-id") recorder := httptest.NewRecorder() @@ -5835,7 +5835,7 @@ func TestCreateRoomIgnoresClientRoomIDAndGeneratesScopedRoomID(t *testing.T) { func TestCreateRoomAllowsMissingSeatCount(t *testing.T) { client := &fakeRoomClient{} router := NewHandlerWithClients(client, nil, nil, &fakeUserProfileClient{regionID: 1001}).Routes(auth.NewVerifier("secret")) - request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{"room_id":"room:1","command_id":"cmd-create-default-seat","mode":"voice","room_name":"Lobby"}`))) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader([]byte(`{"room_id":"room:1","command_id":"cmd-create-default-seat","mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`))) request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) request.Header.Set("X-Request-ID", "req-create-default-seat") recorder := httptest.NewRecorder() @@ -5972,10 +5972,11 @@ func TestCreateRoomRejectsMissingRequiredFieldsBeforeGRPC(t *testing.T) { name string body string }{ - {name: "command_id", body: `{"room_id":"room-1","seat_count":10,"mode":"voice","room_name":"Lobby"}`}, - {name: "mode", body: `{"room_id":"room-1","command_id":"cmd-create-missing-mode","seat_count":10,"room_name":"Lobby"}`}, - {name: "room_name", body: `{"room_id":"room-1","command_id":"cmd-create-missing-name","seat_count":10,"mode":"voice"}`}, - {name: "negative_seat_count", body: `{"room_id":"room-1","command_id":"cmd-create-negative-seat","seat_count":-1,"mode":"voice","room_name":"Lobby"}`}, + {name: "command_id", body: `{"room_id":"room-1","seat_count":10,"mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`}, + {name: "mode", body: `{"room_id":"room-1","command_id":"cmd-create-missing-mode","seat_count":10,"room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`}, + {name: "room_name", body: `{"room_id":"room-1","command_id":"cmd-create-missing-name","seat_count":10,"mode":"voice","room_avatar":"https://cdn.example.com/room.png"}`}, + {name: "room_avatar", body: `{"room_id":"room-1","command_id":"cmd-create-missing-avatar","seat_count":10,"mode":"voice","room_name":"Lobby"}`}, + {name: "negative_seat_count", body: `{"room_id":"room-1","command_id":"cmd-create-negative-seat","seat_count":-1,"mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`}, } for _, test := range tests { @@ -5999,7 +6000,7 @@ func TestCreateRoomRejectsMissingRequiredFieldsBeforeGRPC(t *testing.T) { func TestRoutesWriteUpstreamErrorEnvelope(t *testing.T) { router := NewHandlerWithClients(&fakeRoomClient{createErr: errors.New("room unavailable")}, nil, nil, &fakeUserProfileClient{regionID: 1001}).Routes(auth.NewVerifier("secret")) - body := []byte(`{"room_id":"room-1","command_id":"cmd-create-upstream","seat_count":10,"mode":"voice","room_name":"Lobby"}`) + body := []byte(`{"room_id":"room-1","command_id":"cmd-create-upstream","seat_count":10,"mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`) request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader(body)) request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) request.Header.Set("X-Request-ID", "req-upstream") @@ -6015,7 +6016,7 @@ func TestCreateRoomOwnerConflictWritesConflictEnvelope(t *testing.T) { createErr: xerr.ToGRPCError(xerr.New(xerr.Conflict, "owner already has room")), } router := NewHandlerWithClients(roomClient, nil, nil, &fakeUserProfileClient{regionID: 1001}).Routes(auth.NewVerifier("secret")) - body := []byte(`{"room_id":"room-owner-2","command_id":"cmd-create-owner-conflict","seat_count":10,"mode":"voice","room_name":"Lobby"}`) + body := []byte(`{"room_id":"room-owner-2","command_id":"cmd-create-owner-conflict","seat_count":10,"mode":"voice","room_name":"Lobby","room_avatar":"https://cdn.example.com/room.png"}`) request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewReader(body)) request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) request.Header.Set("X-Request-ID", "req-owner-conflict") diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_handler.go index daa925d0..915536c1 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler.go @@ -675,8 +675,8 @@ func (h *Handler) createRoom(writer http.ResponseWriter, request *http.Request) body.RoomName = strings.TrimSpace(body.RoomName) body.RoomAvatar = strings.TrimSpace(body.RoomAvatar) body.RoomDescription = strings.TrimSpace(body.RoomDescription) - if body.CommandID == "" || body.SeatCount < 0 || body.Mode == "" || body.RoomName == "" { - // command_id 必须来自客户端用户动作,seat_count 可省略走后台默认值;mode 和 room_name 仍是创建页最小必填信息。 + if body.CommandID == "" || body.SeatCount < 0 || body.Mode == "" || body.RoomName == "" || body.RoomAvatar == "" { + // command_id 必须来自客户端用户动作,seat_count 可省略走后台默认值;mode、room_name 和 room_avatar 是创建页最小必填信息。 httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler_test.go b/services/gateway-service/internal/transport/http/roomapi/room_handler_test.go index 61fadd94..ac3f4e86 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler_test.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler_test.go @@ -1,12 +1,35 @@ package roomapi import ( + "bytes" + "net/http" + "net/http/httptest" "testing" "time" roomv1 "hyapp.local/api/proto/room/v1" ) +func TestCreateRoomRejectsMissingRoomAvatar(t *testing.T) { + handler := New(Config{}) + request := httptest.NewRequest(http.MethodPost, "/api/v1/rooms/create", bytes.NewBufferString(`{ + "command_id": "cmd-create-room", + "seat_count": 10, + "mode": "voice", + "room_name": "No Cover Room" + }`)) + recorder := httptest.NewRecorder() + + handler.createRoom(recorder, request) + + if recorder.Code != http.StatusBadRequest { + t.Fatalf("missing room_avatar must fail before upstream calls: status=%d body=%s", recorder.Code, recorder.Body.String()) + } + if !bytes.Contains(recorder.Body.Bytes(), []byte(`"code":"INVALID_ARGUMENT"`)) { + t.Fatalf("missing room_avatar must return invalid argument envelope: %s", recorder.Body.String()) + } +} + func TestRoomGiftTabsUsesTypeCodeAsKeyAndTabKeyAsLabel(t *testing.T) { tabs := roomGiftTabs( []giftConfigData{ diff --git a/services/room-service/internal/room/command/command.go b/services/room-service/internal/room/command/command.go index 5398b09b..bc22a9a5 100644 --- a/services/room-service/internal/room/command/command.go +++ b/services/room-service/internal/room/command/command.go @@ -66,7 +66,7 @@ type CreateRoom struct { VisibleRegionID int64 `json:"visible_region_id"` // RoomName 是房间展示名称,恢复时回填 RoomExt["title"],不拆成独立状态 owner。 RoomName string `json:"room_name"` - // RoomAvatar 是房间展示头像,恢复时回填 RoomExt["cover_url"]。 + // RoomAvatar 是创建时必填的房间封面,恢复时回填 RoomExt["cover_url"]。 RoomAvatar string `json:"room_avatar"` // RoomDescription 是房间简介,恢复时回填 RoomExt["description"]。 RoomDescription string `json:"room_description"` diff --git a/services/room-service/internal/room/service/background_test.go b/services/room-service/internal/room/service/background_test.go index 86f9c744..3958460d 100644 --- a/services/room-service/internal/room/service/background_test.go +++ b/services/room-service/internal/room/service/background_test.go @@ -32,6 +32,7 @@ func TestRoomBackgroundSaveListSetFlow(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Background Flow", + RoomAvatar: testRoomCoverURL, RoomShortId: "bg-flow", }); err != nil { t.Fatalf("create room failed: %v", err) @@ -104,6 +105,7 @@ func TestRoomBackgroundOnlyOwnerCanEdit(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Background Owner", + RoomAvatar: testRoomCoverURL, RoomShortId: "bg-owner", }); err != nil { t.Fatalf("create room failed: %v", err) diff --git a/services/room-service/internal/room/service/create_room.go b/services/room-service/internal/room/service/create_room.go index b9b11cd7..10b85c07 100644 --- a/services/room-service/internal/room/service/create_room.go +++ b/services/room-service/internal/room/service/create_room.go @@ -27,7 +27,7 @@ const ( roomExtShortIDKey = "room_short_id" roomExtBackgroundKey = "background_url" - // defaultRoomAvatar 是房间头像缺省值,语义上代表系统默认资源,不绑定外部 CDN 地址。 + // defaultRoomAvatar 只服务房间资料更新/后台清空封面后的兜底;创建房间必须显式提交封面。 defaultRoomAvatar = "hyapp://room/default-avatar" // RoomExt 的展示字段最终会进入 room_list_entries 和客户端快照,服务端在入口裁剪长度边界。 @@ -304,8 +304,8 @@ func normalizeCreateRoomProfile(req *roomv1.CreateRoomRequest) (roomProfileInput avatar := strings.TrimSpace(req.GetRoomAvatar()) if avatar == "" { - // 默认头像由 room-service 决定,客户端和 gateway 不需要复制同一套兜底策略。 - avatar = defaultRoomAvatar + // 创建房间封面必须来自客户端上传结果;owner service 兜底校验可以防止内部 gRPC 绕过 gateway 创建空封面房。 + return roomProfileInput{}, xerr.New(xerr.InvalidArgument, "room_avatar is required") } if utf8.RuneCountInString(avatar) > maxRoomAvatarRunes { // cover_url 会投影到 room_list_entries.cover_url,超长值必须在写入前拒绝。 diff --git a/services/room-service/internal/room/service/create_room_real_im_test.go b/services/room-service/internal/room/service/create_room_real_im_test.go index e926fb45..05979c54 100644 --- a/services/room-service/internal/room/service/create_room_real_im_test.go +++ b/services/room-service/internal/room/service/create_room_real_im_test.go @@ -53,6 +53,7 @@ func TestRealCreateRoomEnsuresTencentIMGroup(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Real Tencent IM Room", + RoomAvatar: testRoomCoverURL, RoomShortId: strconv.FormatInt(ownerID, 10), }) if err != nil { diff --git a/services/room-service/internal/room/service/create_room_test.go b/services/room-service/internal/room/service/create_room_test.go index 559f694d..0ca77e33 100644 --- a/services/room-service/internal/room/service/create_room_test.go +++ b/services/room-service/internal/room/service/create_room_test.go @@ -8,12 +8,15 @@ import ( roomv1 "hyapp.local/api/proto/room/v1" "hyapp/pkg/tencentim" + "hyapp/pkg/xerr" "hyapp/services/room-service/internal/integration" roomservice "hyapp/services/room-service/internal/room/service" "hyapp/services/room-service/internal/router" "hyapp/services/room-service/internal/testutil/mysqltest" ) +const testRoomCoverURL = "https://cdn.example.com/room-cover.png" + type createRoomIMPublisher struct { err error roomID string @@ -32,6 +35,32 @@ func (p *createRoomIMPublisher) PublishRoomEvent(context.Context, tencentim.Room return nil } +func TestCreateRoomRequiresRoomAvatar(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-create-room-avatar-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{ + Meta: roomservice.NewRequestMeta("room-avatar-required", 7000), + SeatCount: 10, + Mode: "voice", + RoomName: "Avatar Required", + RoomShortId: "avatar-required", + }) + if !xerr.IsCode(err, xerr.InvalidArgument) { + // 房间封面为空必须在 Room owner service 拒绝,避免 gateway 以外的内部调用创建空 cover_url 房间。 + t.Fatalf("expected INVALID_ARGUMENT without room avatar, got %v", err) + } + if _, exists, err := repository.GetRoomMeta(ctx, "room-avatar-required"); err != nil || exists { + t.Fatalf("room meta must not persist without avatar: exists=%t err=%v", exists, err) + } +} + func TestCreateRoomSynchronouslyEnsuresIMGroup(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) @@ -51,6 +80,7 @@ func TestCreateRoomSynchronouslyEnsuresIMGroup(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Sync IM Room", + RoomAvatar: testRoomCoverURL, RoomShortId: "sync-im-ok", }) if err != nil { @@ -83,6 +113,7 @@ func TestCreateRoomDoesNotPersistWhenIMGroupEnsureFails(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Sync IM Failure", + RoomAvatar: testRoomCoverURL, RoomShortId: "sync-im-fail", }); err == nil { t.Fatalf("create room must fail when IM group cannot be created") diff --git a/services/room-service/internal/room/service/follow_test.go b/services/room-service/internal/room/service/follow_test.go index 4665f438..624ca98b 100644 --- a/services/room-service/internal/room/service/follow_test.go +++ b/services/room-service/internal/room/service/follow_test.go @@ -47,6 +47,7 @@ func TestRoomFollowAffectsSnapshotAndFollowedFeed(t *testing.T) { Mode: "voice", VisibleRegionId: 1001, RoomName: "Follow Flow", + RoomAvatar: testRoomCoverURL, RoomShortId: "follow-flow", }); err != nil { t.Fatalf("create room failed: %v", err) diff --git a/services/room-service/internal/room/service/kick_test.go b/services/room-service/internal/room/service/kick_test.go index 7b440947..39f9aa2b 100644 --- a/services/room-service/internal/room/service/kick_test.go +++ b/services/room-service/internal/room/service/kick_test.go @@ -57,6 +57,7 @@ func TestKickUserRemovesPresenceBanAndRTCConnection(t *testing.T) { Mode: "voice", VisibleRegionId: 8101, RoomName: "Kick Flow", + RoomAvatar: testRoomCoverURL, RoomShortId: "kick-flow", }); err != nil { t.Fatalf("create kick room fixture failed: %v", err) @@ -122,6 +123,7 @@ func TestKickUserDurationExpiresAndAllowsJoin(t *testing.T) { Mode: "voice", VisibleRegionId: 8101, RoomName: "Kick Duration", + RoomAvatar: testRoomCoverURL, RoomShortId: "kick-duration", }); err != nil { t.Fatalf("create duration room fixture failed: %v", err) @@ -195,6 +197,7 @@ func TestListRoomBannedUsersReturnsActiveOnlyForManagers(t *testing.T) { Mode: "voice", VisibleRegionId: 8101, RoomName: "Banned Users", + RoomAvatar: testRoomCoverURL, RoomShortId: "banned-users", }); err != nil { t.Fatalf("create banned users room failed: %v", err) @@ -277,6 +280,7 @@ func TestCloseRoomByAdminEvictsCurrentUsersThroughOutboxAndRTC(t *testing.T) { Mode: "voice", VisibleRegionId: 8101, RoomName: "Close Flow", + RoomAvatar: testRoomCoverURL, RoomShortId: "close-flow", }); err != nil { t.Fatalf("create close room fixture failed: %v", err) diff --git a/services/room-service/internal/room/service/lock_test.go b/services/room-service/internal/room/service/lock_test.go index 1b663227..86456703 100644 --- a/services/room-service/internal/room/service/lock_test.go +++ b/services/room-service/internal/room/service/lock_test.go @@ -32,6 +32,7 @@ func TestRoomPasswordControlsJoinAndListLockedFlag(t *testing.T) { Mode: "voice", VisibleRegionId: 6101, RoomName: "Locked Room", + RoomAvatar: testRoomCoverURL, RoomShortId: "lock-flow", }); err != nil { t.Fatalf("create locked room fixture failed: %v", err) diff --git a/services/room-service/internal/room/service/pin_test.go b/services/room-service/internal/room/service/pin_test.go index 37d3f49c..73589e81 100644 --- a/services/room-service/internal/room/service/pin_test.go +++ b/services/room-service/internal/room/service/pin_test.go @@ -73,6 +73,7 @@ func createPinnedListRoom(t *testing.T, ctx context.Context, svc *roomservice.Se Mode: "voice", VisibleRegionId: regionID, RoomName: roomID, + RoomAvatar: testRoomCoverURL, RoomShortId: shortID, }); err != nil { t.Fatalf("create room %s failed: %v", roomID, err) diff --git a/services/room-service/internal/room/service/room_treasure_test.go b/services/room-service/internal/room/service/room_treasure_test.go index 36d9ccfd..a11c3043 100644 --- a/services/room-service/internal/room/service/room_treasure_test.go +++ b/services/room-service/internal/room/service/room_treasure_test.go @@ -549,6 +549,7 @@ func createTreasureRoom(t *testing.T, ctx context.Context, svc *roomservice.Serv Mode: "voice", VisibleRegionId: regionID, RoomName: roomID, + RoomAvatar: testRoomCoverURL, RoomShortId: roomID, }); err != nil { t.Fatalf("create treasure room failed: %v", err) diff --git a/services/room-service/internal/transport/grpc/server_test.go b/services/room-service/internal/transport/grpc/server_test.go index 0e31a1d7..48138a62 100644 --- a/services/room-service/internal/transport/grpc/server_test.go +++ b/services/room-service/internal/transport/grpc/server_test.go @@ -135,6 +135,7 @@ func TestOwnerForwardingUsesRedisRouteAndNodeRegistry(t *testing.T) { SeatCount: 10, Mode: "voice", RoomName: "Forward Room", + RoomAvatar: "https://cdn.example.com/room-cover.png", RoomShortId: "forward-short", }) if err != nil { diff --git a/services/user-service/deploy/mysql/initdb/001_user_service.sql b/services/user-service/deploy/mysql/initdb/001_user_service.sql index b9dece67..257720e5 100644 --- a/services/user-service/deploy/mysql/initdb/001_user_service.sql +++ b/services/user-service/deploy/mysql/initdb/001_user_service.sql @@ -65,6 +65,7 @@ CREATE TABLE IF NOT EXISTS users ( updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', UNIQUE KEY uk_users_default_display_user_id (app_code, default_display_user_id), UNIQUE KEY uk_users_current_display_user_id (app_code, current_display_user_id), + UNIQUE KEY uk_users_register_device_id (app_code, register_device_id), KEY idx_users_status (app_code, status), KEY idx_users_region_status (app_code, region_id, status), KEY idx_users_country_region (app_code, country, region_id) diff --git a/services/user-service/internal/service/auth/service.go b/services/user-service/internal/service/auth/service.go index 87632096..674690a0 100644 --- a/services/user-service/internal/service/auth/service.go +++ b/services/user-service/internal/service/auth/service.go @@ -58,6 +58,8 @@ type AuthRepository interface { RevokeSessionWithReason(ctx context.Context, sessionID string, revokedAtMs int64, reason string, requestID string, revokedBy string) (bool, error) // FindThirdPartyIdentity 查找 provider + subject 的绑定。 FindThirdPartyIdentity(ctx context.Context, provider string, providerSubject string) (authdomain.ThirdPartyIdentity, error) + // FindUserIDByRegisterDeviceID 查找当前 App 下已经占用注册设备号的用户。 + FindUserIDByRegisterDeviceID(ctx context.Context, appCode string, deviceID string) (int64, error) // CreateThirdPartyUser 原子创建用户、默认短号、三方身份和首个 session。 CreateThirdPartyUser(ctx context.Context, user userdomain.User, identity userdomain.Identity, thirdParty authdomain.ThirdPartyIdentity, session authdomain.Session, invite invitedomain.BindCommand) error // RecordLoginAudit 记录登录审计,主链路不会因为审计失败而失败。 diff --git a/services/user-service/internal/service/auth/service_test.go b/services/user-service/internal/service/auth/service_test.go index ed697bf4..1e167750 100644 --- a/services/user-service/internal/service/auth/service_test.go +++ b/services/user-service/internal/service/auth/service_test.go @@ -535,6 +535,39 @@ func TestThirdPartyLoginOrRegister(t *testing.T) { } } +func TestThirdPartyRegisterRejectsReusedDeviceID(t *testing.T) { + // 设备号只限制新账号注册;同一个 provider subject 的再次登录仍然可以创建新 session。 + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedCountry(t, repository, "SG") + now := time.UnixMilli(1000) + svc := newAuthService(repository, &now, []int64{900020, 900021}, []string{"100020", "100021"}) + registration := thirdPartyRegistration("ios") + registration.DeviceID = "device-one-account" + + firstToken, isNewUser, err := svc.LoginThirdParty(ctx, "wechat", "openid-device-first", registration, authservice.Meta{RequestID: "req-device-first"}) + if err != nil { + t.Fatalf("first LoginThirdParty failed: %v", err) + } + if !isNewUser || firstToken.UserID != 900020 { + t.Fatalf("unexpected first third-party result: token=%+v isNew=%v", firstToken, isNewUser) + } + + existingToken, isNewUser, err := svc.LoginThirdParty(ctx, "wechat", "openid-device-first", registration, authservice.Meta{RequestID: "req-device-existing"}) + if err != nil { + t.Fatalf("existing LoginThirdParty should not be blocked by device limit: %v", err) + } + if isNewUser || existingToken.UserID != firstToken.UserID { + t.Fatalf("expected existing third-party login, token=%+v isNew=%v", existingToken, isNewUser) + } + + _, _, err = svc.LoginThirdParty(ctx, "wechat", "openid-device-second", registration, authservice.Meta{RequestID: "req-device-second"}) + if !xerr.IsCode(err, xerr.DeviceAlreadyRegistered) { + // 第二个 provider subject 会创建新账号,必须被注册设备唯一性拦截。 + t.Fatalf("expected DEVICE_ALREADY_REGISTERED for reused device, got %v", err) + } +} + func TestThirdPartyRegisterAllowsMinimalProfileFields(t *testing.T) { // 三方首次登录只需要认证材料、设备和平台;公开资料由后续 onboarding 原子提交。 ctx := context.Background() diff --git a/services/user-service/internal/service/auth/third_party.go b/services/user-service/internal/service/auth/third_party.go index 33a7b0bf..c46949e5 100644 --- a/services/user-service/internal/service/auth/third_party.go +++ b/services/user-service/internal/service/auth/third_party.go @@ -83,6 +83,9 @@ func (s *Service) LoginThirdParty(ctx context.Context, provider string, credenti s.audit(ctx, meta, 0, loginThird, provider, resultFailed, string(xerr.CodeOf(err))) return authdomain.Token{}, false, err } + if err := s.ensureDeviceCanRegisterThirdParty(ctx, registration, meta, provider); err != nil { + return authdomain.Token{}, false, err + } registration, err = s.resolveRegistrationCountry(ctx, registration) if err != nil { return authdomain.Token{}, false, err @@ -91,6 +94,23 @@ func (s *Service) LoginThirdParty(ctx context.Context, provider string, credenti return s.createThirdPartyUser(ctx, provider, profile, registration, meta) } +func (s *Service) ensureDeviceCanRegisterThirdParty(ctx context.Context, registration authdomain.ThirdPartyRegistration, meta Meta, provider string) error { + // 设备号限制只约束“创建新账号”路径;已绑定三方身份登录不经过这里,避免把正常跨设备登录误拦。 + userID, err := s.authRepository.FindUserIDByRegisterDeviceID(ctx, registration.AppCode, registration.DeviceID) + if xerr.IsCode(err, xerr.NotFound) { + return nil + } + if err != nil { + // 设备查重失败不能退化为注册,否则并发和依赖异常都会突破一机一号约束。 + s.audit(ctx, meta, 0, loginThird, provider, resultFailed, string(xerr.CodeOf(err))) + return err + } + + // 已有任意用户占用该注册设备时拒绝创建新账号;不返回 user_id,避免客户端枚举设备归属。 + s.audit(ctx, meta, userID, loginThird, provider, resultFailed, string(xerr.DeviceAlreadyRegistered)) + return xerr.New(xerr.DeviceAlreadyRegistered, "device already registered") +} + func (s *Service) loginExistingThirdParty(ctx context.Context, identity authdomain.ThirdPartyIdentity, registration authdomain.ThirdPartyRegistration, meta Meta) (authdomain.Token, bool, error) { // 已绑定三方用户登录时仍要重新读取用户快照,确保禁用状态和靓号过期生效。 user, err := s.freshUser(ctx, identity.UserID, s.now().UnixMilli(), meta.RequestID) diff --git a/services/user-service/internal/storage/mysql/auth/common.go b/services/user-service/internal/storage/mysql/auth/common.go index f54b8077..495435b4 100644 --- a/services/user-service/internal/storage/mysql/auth/common.go +++ b/services/user-service/internal/storage/mysql/auth/common.go @@ -31,6 +31,8 @@ func mapAuthDuplicateError(err error) error { // 根据约束名或表名把重复键错误映射成稳定领域 reason。 message := mysqlErr.Message switch { + case strings.Contains(message, "uk_users_register_device_id"): + return xerr.New(xerr.DeviceAlreadyRegistered, "device already registered") case strings.Contains(message, "password_accounts"): return xerr.New(xerr.PasswordAlreadySet, "password already set") case strings.Contains(message, "third_party") || strings.Contains(message, "uk_third_party_provider_subject"): diff --git a/services/user-service/internal/storage/mysql/auth/third_party.go b/services/user-service/internal/storage/mysql/auth/third_party.go index 49f744d1..d681cdea 100644 --- a/services/user-service/internal/storage/mysql/auth/third_party.go +++ b/services/user-service/internal/storage/mysql/auth/third_party.go @@ -32,6 +32,25 @@ func (r *Repository) FindThirdPartyIdentity(ctx context.Context, provider string return identity, nil } +func (r *Repository) FindUserIDByRegisterDeviceID(ctx context.Context, appCode string, deviceID string) (int64, error) { + var userID int64 + err := r.db.QueryRowContext(ctx, ` + SELECT user_id + FROM users + WHERE app_code = ? AND register_device_id = ? + LIMIT 1 + `, appcode.Normalize(appCode), deviceID).Scan(&userID) + if err == sql.ErrNoRows { + // 未查到占用者时,service 才允许新三方身份走注册事务。 + return 0, xerr.New(xerr.NotFound, "registered device not found") + } + if err != nil { + return 0, err + } + + return userID, nil +} + // CreateThirdPartyUser 原子创建用户、默认短号、三方身份和首个 session。 func (r *Repository) CreateThirdPartyUser(ctx context.Context, user userdomain.User, identity userdomain.Identity, thirdParty authdomain.ThirdPartyIdentity, session authdomain.Session, inviteBind invitedomain.BindCommand) error { diff --git a/services/user-service/internal/testutil/mysqltest/mysqltest.go b/services/user-service/internal/testutil/mysqltest/mysqltest.go index c4279c4f..544ba51f 100644 --- a/services/user-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/user-service/internal/testutil/mysqltest/mysqltest.go @@ -290,6 +290,11 @@ func (r *Repository) FindThirdPartyIdentity(ctx context.Context, provider string return r.Repository.AuthRepository().FindThirdPartyIdentity(ctx, provider, providerSubject) } +// FindUserIDByRegisterDeviceID 让测试 wrapper 继续满足认证接口。 +func (r *Repository) FindUserIDByRegisterDeviceID(ctx context.Context, appCode string, deviceID string) (int64, error) { + return r.Repository.AuthRepository().FindUserIDByRegisterDeviceID(ctx, appCode, deviceID) +} + // CreateThirdPartyUser 让测试 wrapper 继续满足认证接口。 func (r *Repository) CreateThirdPartyUser(ctx context.Context, user userdomain.User, identity userdomain.Identity, thirdParty authdomain.ThirdPartyIdentity, session authdomain.Session, invite invitedomain.BindCommand) error { return r.Repository.AuthRepository().CreateThirdPartyUser(ctx, user, identity, thirdParty, session, invite) From d79c877ec0a0ff34e12591301a80a6ca2929acf8 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 22:57:31 +0800 Subject: [PATCH 11/28] Add salary wallet exchange flows --- api/proto/user/v1/host.pb.go | 637 +++-- api/proto/user/v1/host.proto | 12 + api/proto/user/v1/host_grpc.pb.go | 38 + api/proto/wallet/v1/wallet.pb.go | 2197 +++++++++++------ api/proto/wallet/v1/wallet.proto | 72 +- api/proto/wallet/v1/wallet_grpc.pb.go | 242 +- .../internal/modules/giftdiamond/service.go | 6 +- .../modules/hostagencypolicy/service.go | 9 +- .../modules/hostagencypolicy/service_test.go | 3 +- .../admin/internal/modules/hostorg/handler.go | 33 + .../admin/internal/modules/hostorg/reader.go | 131 + .../admin/internal/modules/hostorg/request.go | 15 + .../admin/internal/modules/hostorg/routes.go | 2 + .../admin/internal/modules/hostorg/service.go | 120 + server/admin/internal/repository/seed.go | 5 +- .../internal/client/user_client.go | 5 + .../internal/client/wallet_client.go | 15 + .../transport/http/httproutes/router.go | 14 + .../internal/transport/http/response_test.go | 284 +++ .../http/userapi/bd_leader_center_handler.go | 157 ++ .../transport/http/userapi/handler.go | 3 + .../transport/http/userapi/user_handler.go | 45 +- .../http/walletapi/app_wallet_handler.go | 73 +- .../transport/http/walletapi/handler.go | 4 + .../http/walletapi/salary_wallet_handler.go | 501 ++++ .../http/walletapi/wallet_handler.go | 9 +- .../internal/service/host/commands.go | 7 + .../internal/service/host/service.go | 16 + .../internal/storage/mysql/host/queries.go | 17 + .../internal/transport/grpc/host.go | 22 + .../mysql/initdb/001_wallet_service.sql | 24 +- .../internal/domain/ledger/ledger.go | 74 + .../internal/service/wallet/service.go | 77 +- .../internal/service/wallet/service_test.go | 349 +++ .../internal/storage/mysql/repository.go | 679 ++++- .../storage/mysql/resource_repository.go | 81 +- .../internal/testutil/mysqltest/mysqltest.go | 22 +- .../internal/transport/grpc/server.go | 74 + 38 files changed, 4835 insertions(+), 1239 deletions(-) create mode 100644 services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index c54d3b88..749e9a4b 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -2140,6 +2140,118 @@ func (x *ListBDLeaderAgenciesResponse) GetAgencies() []*Agency { return nil } +type ListBDAgenciesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + BdUserId int64 `protobuf:"varint,2,opt,name=bd_user_id,json=bdUserId,proto3" json:"bd_user_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDAgenciesRequest) Reset() { + *x = ListBDAgenciesRequest{} + mi := &file_proto_user_v1_host_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDAgenciesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDAgenciesRequest) ProtoMessage() {} + +func (x *ListBDAgenciesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[25] + 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 ListBDAgenciesRequest.ProtoReflect.Descriptor instead. +func (*ListBDAgenciesRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{25} +} + +func (x *ListBDAgenciesRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListBDAgenciesRequest) GetBdUserId() int64 { + if x != nil { + return x.BdUserId + } + return 0 +} + +func (x *ListBDAgenciesRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListBDAgenciesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListBDAgenciesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Agencies []*Agency `protobuf:"bytes,1,rep,name=agencies,proto3" json:"agencies,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListBDAgenciesResponse) Reset() { + *x = ListBDAgenciesResponse{} + mi := &file_proto_user_v1_host_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListBDAgenciesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListBDAgenciesResponse) ProtoMessage() {} + +func (x *ListBDAgenciesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[26] + 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 ListBDAgenciesResponse.ProtoReflect.Descriptor instead. +func (*ListBDAgenciesResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{26} +} + +func (x *ListBDAgenciesResponse) GetAgencies() []*Agency { + if x != nil { + return x.Agencies + } + return nil +} + type ProcessRoleInvitationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` @@ -2154,7 +2266,7 @@ type ProcessRoleInvitationRequest struct { func (x *ProcessRoleInvitationRequest) Reset() { *x = ProcessRoleInvitationRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[25] + mi := &file_proto_user_v1_host_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2166,7 +2278,7 @@ func (x *ProcessRoleInvitationRequest) String() string { func (*ProcessRoleInvitationRequest) ProtoMessage() {} func (x *ProcessRoleInvitationRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[25] + mi := &file_proto_user_v1_host_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2179,7 +2291,7 @@ func (x *ProcessRoleInvitationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ProcessRoleInvitationRequest.ProtoReflect.Descriptor instead. func (*ProcessRoleInvitationRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{25} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{27} } func (x *ProcessRoleInvitationRequest) GetMeta() *RequestMeta { @@ -2237,7 +2349,7 @@ type ProcessRoleInvitationResponse struct { func (x *ProcessRoleInvitationResponse) Reset() { *x = ProcessRoleInvitationResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[26] + mi := &file_proto_user_v1_host_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2249,7 +2361,7 @@ func (x *ProcessRoleInvitationResponse) String() string { func (*ProcessRoleInvitationResponse) ProtoMessage() {} func (x *ProcessRoleInvitationResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[26] + mi := &file_proto_user_v1_host_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2262,7 +2374,7 @@ func (x *ProcessRoleInvitationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ProcessRoleInvitationResponse.ProtoReflect.Descriptor instead. func (*ProcessRoleInvitationResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{26} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{28} } func (x *ProcessRoleInvitationResponse) GetInvitation() *RoleInvitation { @@ -2310,7 +2422,7 @@ type GetHostProfileRequest struct { func (x *GetHostProfileRequest) Reset() { *x = GetHostProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[27] + mi := &file_proto_user_v1_host_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2322,7 +2434,7 @@ func (x *GetHostProfileRequest) String() string { func (*GetHostProfileRequest) ProtoMessage() {} func (x *GetHostProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[27] + mi := &file_proto_user_v1_host_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2335,7 +2447,7 @@ func (x *GetHostProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHostProfileRequest.ProtoReflect.Descriptor instead. func (*GetHostProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{27} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{29} } func (x *GetHostProfileRequest) GetMeta() *RequestMeta { @@ -2361,7 +2473,7 @@ type GetHostProfileResponse struct { func (x *GetHostProfileResponse) Reset() { *x = GetHostProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[28] + mi := &file_proto_user_v1_host_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2373,7 +2485,7 @@ func (x *GetHostProfileResponse) String() string { func (*GetHostProfileResponse) ProtoMessage() {} func (x *GetHostProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[28] + mi := &file_proto_user_v1_host_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2386,7 +2498,7 @@ func (x *GetHostProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetHostProfileResponse.ProtoReflect.Descriptor instead. func (*GetHostProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{28} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{30} } func (x *GetHostProfileResponse) GetHostProfile() *HostProfile { @@ -2406,7 +2518,7 @@ type GetBDProfileRequest struct { func (x *GetBDProfileRequest) Reset() { *x = GetBDProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[29] + mi := &file_proto_user_v1_host_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2418,7 +2530,7 @@ func (x *GetBDProfileRequest) String() string { func (*GetBDProfileRequest) ProtoMessage() {} func (x *GetBDProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[29] + mi := &file_proto_user_v1_host_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2431,7 +2543,7 @@ func (x *GetBDProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBDProfileRequest.ProtoReflect.Descriptor instead. func (*GetBDProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{29} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{31} } func (x *GetBDProfileRequest) GetMeta() *RequestMeta { @@ -2457,7 +2569,7 @@ type GetBDProfileResponse struct { func (x *GetBDProfileResponse) Reset() { *x = GetBDProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[30] + mi := &file_proto_user_v1_host_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2469,7 +2581,7 @@ func (x *GetBDProfileResponse) String() string { func (*GetBDProfileResponse) ProtoMessage() {} func (x *GetBDProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[30] + mi := &file_proto_user_v1_host_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2482,7 +2594,7 @@ func (x *GetBDProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetBDProfileResponse.ProtoReflect.Descriptor instead. func (*GetBDProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{30} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{32} } func (x *GetBDProfileResponse) GetBdProfile() *BDProfile { @@ -2502,7 +2614,7 @@ type GetCoinSellerProfileRequest struct { func (x *GetCoinSellerProfileRequest) Reset() { *x = GetCoinSellerProfileRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[31] + mi := &file_proto_user_v1_host_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2514,7 +2626,7 @@ func (x *GetCoinSellerProfileRequest) String() string { func (*GetCoinSellerProfileRequest) ProtoMessage() {} func (x *GetCoinSellerProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[31] + mi := &file_proto_user_v1_host_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2527,7 +2639,7 @@ func (x *GetCoinSellerProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCoinSellerProfileRequest.ProtoReflect.Descriptor instead. func (*GetCoinSellerProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{31} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{33} } func (x *GetCoinSellerProfileRequest) GetMeta() *RequestMeta { @@ -2553,7 +2665,7 @@ type GetCoinSellerProfileResponse struct { func (x *GetCoinSellerProfileResponse) Reset() { *x = GetCoinSellerProfileResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[32] + mi := &file_proto_user_v1_host_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2565,7 +2677,7 @@ func (x *GetCoinSellerProfileResponse) String() string { func (*GetCoinSellerProfileResponse) ProtoMessage() {} func (x *GetCoinSellerProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[32] + mi := &file_proto_user_v1_host_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2578,7 +2690,7 @@ func (x *GetCoinSellerProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCoinSellerProfileResponse.ProtoReflect.Descriptor instead. func (*GetCoinSellerProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{32} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{34} } func (x *GetCoinSellerProfileResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -2598,7 +2710,7 @@ type ListActiveCoinSellersInMyRegionRequest struct { func (x *ListActiveCoinSellersInMyRegionRequest) Reset() { *x = ListActiveCoinSellersInMyRegionRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[33] + mi := &file_proto_user_v1_host_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2610,7 +2722,7 @@ func (x *ListActiveCoinSellersInMyRegionRequest) String() string { func (*ListActiveCoinSellersInMyRegionRequest) ProtoMessage() {} func (x *ListActiveCoinSellersInMyRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[33] + mi := &file_proto_user_v1_host_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2623,7 +2735,7 @@ func (x *ListActiveCoinSellersInMyRegionRequest) ProtoReflect() protoreflect.Mes // Deprecated: Use ListActiveCoinSellersInMyRegionRequest.ProtoReflect.Descriptor instead. func (*ListActiveCoinSellersInMyRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{33} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{35} } func (x *ListActiveCoinSellersInMyRegionRequest) GetMeta() *RequestMeta { @@ -2649,7 +2761,7 @@ type ListActiveCoinSellersInMyRegionResponse struct { func (x *ListActiveCoinSellersInMyRegionResponse) Reset() { *x = ListActiveCoinSellersInMyRegionResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[34] + mi := &file_proto_user_v1_host_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2661,7 +2773,7 @@ func (x *ListActiveCoinSellersInMyRegionResponse) String() string { func (*ListActiveCoinSellersInMyRegionResponse) ProtoMessage() {} func (x *ListActiveCoinSellersInMyRegionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[34] + mi := &file_proto_user_v1_host_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2674,7 +2786,7 @@ func (x *ListActiveCoinSellersInMyRegionResponse) ProtoReflect() protoreflect.Me // Deprecated: Use ListActiveCoinSellersInMyRegionResponse.ProtoReflect.Descriptor instead. func (*ListActiveCoinSellersInMyRegionResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{34} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{36} } func (x *ListActiveCoinSellersInMyRegionResponse) GetCoinSellers() []*CoinSellerListItem { @@ -2694,7 +2806,7 @@ type GetUserRoleSummaryRequest struct { func (x *GetUserRoleSummaryRequest) Reset() { *x = GetUserRoleSummaryRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[35] + mi := &file_proto_user_v1_host_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2706,7 +2818,7 @@ func (x *GetUserRoleSummaryRequest) String() string { func (*GetUserRoleSummaryRequest) ProtoMessage() {} func (x *GetUserRoleSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[35] + mi := &file_proto_user_v1_host_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2719,7 +2831,7 @@ func (x *GetUserRoleSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserRoleSummaryRequest.ProtoReflect.Descriptor instead. func (*GetUserRoleSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{35} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{37} } func (x *GetUserRoleSummaryRequest) GetMeta() *RequestMeta { @@ -2745,7 +2857,7 @@ type GetUserRoleSummaryResponse struct { func (x *GetUserRoleSummaryResponse) Reset() { *x = GetUserRoleSummaryResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[36] + mi := &file_proto_user_v1_host_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2757,7 +2869,7 @@ func (x *GetUserRoleSummaryResponse) String() string { func (*GetUserRoleSummaryResponse) ProtoMessage() {} func (x *GetUserRoleSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[36] + mi := &file_proto_user_v1_host_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2770,7 +2882,7 @@ func (x *GetUserRoleSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserRoleSummaryResponse.ProtoReflect.Descriptor instead. func (*GetUserRoleSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{36} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{38} } func (x *GetUserRoleSummaryResponse) GetSummary() *UserRoleSummary { @@ -2790,7 +2902,7 @@ type GetAgencyRequest struct { func (x *GetAgencyRequest) Reset() { *x = GetAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[37] + mi := &file_proto_user_v1_host_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2802,7 +2914,7 @@ func (x *GetAgencyRequest) String() string { func (*GetAgencyRequest) ProtoMessage() {} func (x *GetAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[37] + mi := &file_proto_user_v1_host_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2815,7 +2927,7 @@ func (x *GetAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyRequest.ProtoReflect.Descriptor instead. func (*GetAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{37} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{39} } func (x *GetAgencyRequest) GetMeta() *RequestMeta { @@ -2841,7 +2953,7 @@ type GetAgencyResponse struct { func (x *GetAgencyResponse) Reset() { *x = GetAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[38] + mi := &file_proto_user_v1_host_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2853,7 +2965,7 @@ func (x *GetAgencyResponse) String() string { func (*GetAgencyResponse) ProtoMessage() {} func (x *GetAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[38] + mi := &file_proto_user_v1_host_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2866,7 +2978,7 @@ func (x *GetAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyResponse.ProtoReflect.Descriptor instead. func (*GetAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{38} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{40} } func (x *GetAgencyResponse) GetAgency() *Agency { @@ -2887,7 +2999,7 @@ type CheckBusinessCapabilityRequest struct { func (x *CheckBusinessCapabilityRequest) Reset() { *x = CheckBusinessCapabilityRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[39] + mi := &file_proto_user_v1_host_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2899,7 +3011,7 @@ func (x *CheckBusinessCapabilityRequest) String() string { func (*CheckBusinessCapabilityRequest) ProtoMessage() {} func (x *CheckBusinessCapabilityRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[39] + mi := &file_proto_user_v1_host_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2912,7 +3024,7 @@ func (x *CheckBusinessCapabilityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckBusinessCapabilityRequest.ProtoReflect.Descriptor instead. func (*CheckBusinessCapabilityRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{39} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{41} } func (x *CheckBusinessCapabilityRequest) GetMeta() *RequestMeta { @@ -2946,7 +3058,7 @@ type CheckBusinessCapabilityResponse struct { func (x *CheckBusinessCapabilityResponse) Reset() { *x = CheckBusinessCapabilityResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[40] + mi := &file_proto_user_v1_host_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2958,7 +3070,7 @@ func (x *CheckBusinessCapabilityResponse) String() string { func (*CheckBusinessCapabilityResponse) ProtoMessage() {} func (x *CheckBusinessCapabilityResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[40] + mi := &file_proto_user_v1_host_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2971,7 +3083,7 @@ func (x *CheckBusinessCapabilityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckBusinessCapabilityResponse.ProtoReflect.Descriptor instead. func (*CheckBusinessCapabilityResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{40} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{42} } func (x *CheckBusinessCapabilityResponse) GetAllowed() bool { @@ -2999,7 +3111,7 @@ type GetAgencyMembersRequest struct { func (x *GetAgencyMembersRequest) Reset() { *x = GetAgencyMembersRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[41] + mi := &file_proto_user_v1_host_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3011,7 +3123,7 @@ func (x *GetAgencyMembersRequest) String() string { func (*GetAgencyMembersRequest) ProtoMessage() {} func (x *GetAgencyMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[41] + mi := &file_proto_user_v1_host_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3024,7 +3136,7 @@ func (x *GetAgencyMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyMembersRequest.ProtoReflect.Descriptor instead. func (*GetAgencyMembersRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{41} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{43} } func (x *GetAgencyMembersRequest) GetMeta() *RequestMeta { @@ -3057,7 +3169,7 @@ type GetAgencyMembersResponse struct { func (x *GetAgencyMembersResponse) Reset() { *x = GetAgencyMembersResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[42] + mi := &file_proto_user_v1_host_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3069,7 +3181,7 @@ func (x *GetAgencyMembersResponse) String() string { func (*GetAgencyMembersResponse) ProtoMessage() {} func (x *GetAgencyMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[42] + mi := &file_proto_user_v1_host_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3082,7 +3194,7 @@ func (x *GetAgencyMembersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyMembersResponse.ProtoReflect.Descriptor instead. func (*GetAgencyMembersResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{42} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{44} } func (x *GetAgencyMembersResponse) GetMemberships() []*AgencyMembership { @@ -3103,7 +3215,7 @@ type GetAgencyApplicationsRequest struct { func (x *GetAgencyApplicationsRequest) Reset() { *x = GetAgencyApplicationsRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[43] + mi := &file_proto_user_v1_host_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3115,7 +3227,7 @@ func (x *GetAgencyApplicationsRequest) String() string { func (*GetAgencyApplicationsRequest) ProtoMessage() {} func (x *GetAgencyApplicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[43] + mi := &file_proto_user_v1_host_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3128,7 +3240,7 @@ func (x *GetAgencyApplicationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyApplicationsRequest.ProtoReflect.Descriptor instead. func (*GetAgencyApplicationsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{43} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{45} } func (x *GetAgencyApplicationsRequest) GetMeta() *RequestMeta { @@ -3161,7 +3273,7 @@ type GetAgencyApplicationsResponse struct { func (x *GetAgencyApplicationsResponse) Reset() { *x = GetAgencyApplicationsResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[44] + mi := &file_proto_user_v1_host_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3173,7 +3285,7 @@ func (x *GetAgencyApplicationsResponse) String() string { func (*GetAgencyApplicationsResponse) ProtoMessage() {} func (x *GetAgencyApplicationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[44] + mi := &file_proto_user_v1_host_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3186,7 +3298,7 @@ func (x *GetAgencyApplicationsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetAgencyApplicationsResponse.ProtoReflect.Descriptor instead. func (*GetAgencyApplicationsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{44} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{46} } func (x *GetAgencyApplicationsResponse) GetApplications() []*AgencyApplication { @@ -3210,7 +3322,7 @@ type CreateBDLeaderRequest struct { func (x *CreateBDLeaderRequest) Reset() { *x = CreateBDLeaderRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[45] + mi := &file_proto_user_v1_host_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3222,7 +3334,7 @@ func (x *CreateBDLeaderRequest) String() string { func (*CreateBDLeaderRequest) ProtoMessage() {} func (x *CreateBDLeaderRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[45] + mi := &file_proto_user_v1_host_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3235,7 +3347,7 @@ func (x *CreateBDLeaderRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDLeaderRequest.ProtoReflect.Descriptor instead. func (*CreateBDLeaderRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{45} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{47} } func (x *CreateBDLeaderRequest) GetMeta() *RequestMeta { @@ -3289,7 +3401,7 @@ type CreateBDLeaderResponse struct { func (x *CreateBDLeaderResponse) Reset() { *x = CreateBDLeaderResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[46] + mi := &file_proto_user_v1_host_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3301,7 +3413,7 @@ func (x *CreateBDLeaderResponse) String() string { func (*CreateBDLeaderResponse) ProtoMessage() {} func (x *CreateBDLeaderResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[46] + mi := &file_proto_user_v1_host_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3314,7 +3426,7 @@ func (x *CreateBDLeaderResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDLeaderResponse.ProtoReflect.Descriptor instead. func (*CreateBDLeaderResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{46} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{48} } func (x *CreateBDLeaderResponse) GetBdProfile() *BDProfile { @@ -3338,7 +3450,7 @@ type CreateBDRequest struct { func (x *CreateBDRequest) Reset() { *x = CreateBDRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[47] + mi := &file_proto_user_v1_host_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3350,7 +3462,7 @@ func (x *CreateBDRequest) String() string { func (*CreateBDRequest) ProtoMessage() {} func (x *CreateBDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[47] + mi := &file_proto_user_v1_host_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3363,7 +3475,7 @@ func (x *CreateBDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDRequest.ProtoReflect.Descriptor instead. func (*CreateBDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{47} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{49} } func (x *CreateBDRequest) GetMeta() *RequestMeta { @@ -3417,7 +3529,7 @@ type CreateBDResponse struct { func (x *CreateBDResponse) Reset() { *x = CreateBDResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[48] + mi := &file_proto_user_v1_host_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3429,7 +3541,7 @@ func (x *CreateBDResponse) String() string { func (*CreateBDResponse) ProtoMessage() {} func (x *CreateBDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[48] + mi := &file_proto_user_v1_host_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3442,7 +3554,7 @@ func (x *CreateBDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateBDResponse.ProtoReflect.Descriptor instead. func (*CreateBDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{48} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{50} } func (x *CreateBDResponse) GetBdProfile() *BDProfile { @@ -3466,7 +3578,7 @@ type SetBDStatusRequest struct { func (x *SetBDStatusRequest) Reset() { *x = SetBDStatusRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[49] + mi := &file_proto_user_v1_host_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3478,7 +3590,7 @@ func (x *SetBDStatusRequest) String() string { func (*SetBDStatusRequest) ProtoMessage() {} func (x *SetBDStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[49] + mi := &file_proto_user_v1_host_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3491,7 +3603,7 @@ func (x *SetBDStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBDStatusRequest.ProtoReflect.Descriptor instead. func (*SetBDStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{49} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{51} } func (x *SetBDStatusRequest) GetMeta() *RequestMeta { @@ -3545,7 +3657,7 @@ type SetBDStatusResponse struct { func (x *SetBDStatusResponse) Reset() { *x = SetBDStatusResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[50] + mi := &file_proto_user_v1_host_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3557,7 +3669,7 @@ func (x *SetBDStatusResponse) String() string { func (*SetBDStatusResponse) ProtoMessage() {} func (x *SetBDStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[50] + mi := &file_proto_user_v1_host_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3570,7 +3682,7 @@ func (x *SetBDStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetBDStatusResponse.ProtoReflect.Descriptor instead. func (*SetBDStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{50} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{52} } func (x *SetBDStatusResponse) GetBdProfile() *BDProfile { @@ -3593,7 +3705,7 @@ type CreateCoinSellerRequest struct { func (x *CreateCoinSellerRequest) Reset() { *x = CreateCoinSellerRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[51] + mi := &file_proto_user_v1_host_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3605,7 +3717,7 @@ func (x *CreateCoinSellerRequest) String() string { func (*CreateCoinSellerRequest) ProtoMessage() {} func (x *CreateCoinSellerRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[51] + mi := &file_proto_user_v1_host_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3618,7 +3730,7 @@ func (x *CreateCoinSellerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateCoinSellerRequest.ProtoReflect.Descriptor instead. func (*CreateCoinSellerRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{51} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{53} } func (x *CreateCoinSellerRequest) GetMeta() *RequestMeta { @@ -3665,7 +3777,7 @@ type CreateCoinSellerResponse struct { func (x *CreateCoinSellerResponse) Reset() { *x = CreateCoinSellerResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[52] + mi := &file_proto_user_v1_host_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3677,7 +3789,7 @@ func (x *CreateCoinSellerResponse) String() string { func (*CreateCoinSellerResponse) ProtoMessage() {} func (x *CreateCoinSellerResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[52] + mi := &file_proto_user_v1_host_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3690,7 +3802,7 @@ func (x *CreateCoinSellerResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateCoinSellerResponse.ProtoReflect.Descriptor instead. func (*CreateCoinSellerResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{52} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{54} } func (x *CreateCoinSellerResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -3714,7 +3826,7 @@ type SetCoinSellerStatusRequest struct { func (x *SetCoinSellerStatusRequest) Reset() { *x = SetCoinSellerStatusRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[53] + mi := &file_proto_user_v1_host_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3726,7 +3838,7 @@ func (x *SetCoinSellerStatusRequest) String() string { func (*SetCoinSellerStatusRequest) ProtoMessage() {} func (x *SetCoinSellerStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[53] + mi := &file_proto_user_v1_host_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3739,7 +3851,7 @@ func (x *SetCoinSellerStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetCoinSellerStatusRequest.ProtoReflect.Descriptor instead. func (*SetCoinSellerStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{53} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{55} } func (x *SetCoinSellerStatusRequest) GetMeta() *RequestMeta { @@ -3793,7 +3905,7 @@ type SetCoinSellerStatusResponse struct { func (x *SetCoinSellerStatusResponse) Reset() { *x = SetCoinSellerStatusResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[54] + mi := &file_proto_user_v1_host_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3805,7 +3917,7 @@ func (x *SetCoinSellerStatusResponse) String() string { func (*SetCoinSellerStatusResponse) ProtoMessage() {} func (x *SetCoinSellerStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[54] + mi := &file_proto_user_v1_host_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3818,7 +3930,7 @@ func (x *SetCoinSellerStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetCoinSellerStatusResponse.ProtoReflect.Descriptor instead. func (*SetCoinSellerStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{54} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{56} } func (x *SetCoinSellerStatusResponse) GetCoinSellerProfile() *CoinSellerProfile { @@ -3845,7 +3957,7 @@ type CreateAgencyRequest struct { func (x *CreateAgencyRequest) Reset() { *x = CreateAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[55] + mi := &file_proto_user_v1_host_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3857,7 +3969,7 @@ func (x *CreateAgencyRequest) String() string { func (*CreateAgencyRequest) ProtoMessage() {} func (x *CreateAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[55] + mi := &file_proto_user_v1_host_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3870,7 +3982,7 @@ func (x *CreateAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAgencyRequest.ProtoReflect.Descriptor instead. func (*CreateAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{55} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{57} } func (x *CreateAgencyRequest) GetMeta() *RequestMeta { @@ -3947,7 +4059,7 @@ type CreateAgencyResponse struct { func (x *CreateAgencyResponse) Reset() { *x = CreateAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[56] + mi := &file_proto_user_v1_host_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3959,7 +4071,7 @@ func (x *CreateAgencyResponse) String() string { func (*CreateAgencyResponse) ProtoMessage() {} func (x *CreateAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[56] + mi := &file_proto_user_v1_host_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3972,7 +4084,7 @@ func (x *CreateAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateAgencyResponse.ProtoReflect.Descriptor instead. func (*CreateAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{56} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{58} } func (x *CreateAgencyResponse) GetAgency() *Agency { @@ -4009,7 +4121,7 @@ type CloseAgencyRequest struct { func (x *CloseAgencyRequest) Reset() { *x = CloseAgencyRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[57] + mi := &file_proto_user_v1_host_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4021,7 +4133,7 @@ func (x *CloseAgencyRequest) String() string { func (*CloseAgencyRequest) ProtoMessage() {} func (x *CloseAgencyRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[57] + mi := &file_proto_user_v1_host_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4034,7 +4146,7 @@ func (x *CloseAgencyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseAgencyRequest.ProtoReflect.Descriptor instead. func (*CloseAgencyRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{57} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{59} } func (x *CloseAgencyRequest) GetMeta() *RequestMeta { @@ -4081,7 +4193,7 @@ type CloseAgencyResponse struct { func (x *CloseAgencyResponse) Reset() { *x = CloseAgencyResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[58] + mi := &file_proto_user_v1_host_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4093,7 +4205,7 @@ func (x *CloseAgencyResponse) String() string { func (*CloseAgencyResponse) ProtoMessage() {} func (x *CloseAgencyResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[58] + mi := &file_proto_user_v1_host_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4106,7 +4218,7 @@ func (x *CloseAgencyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseAgencyResponse.ProtoReflect.Descriptor instead. func (*CloseAgencyResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{58} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{60} } func (x *CloseAgencyResponse) GetAgency() *Agency { @@ -4130,7 +4242,7 @@ type SetAgencyJoinEnabledRequest struct { func (x *SetAgencyJoinEnabledRequest) Reset() { *x = SetAgencyJoinEnabledRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[59] + mi := &file_proto_user_v1_host_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4142,7 +4254,7 @@ func (x *SetAgencyJoinEnabledRequest) String() string { func (*SetAgencyJoinEnabledRequest) ProtoMessage() {} func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[59] + mi := &file_proto_user_v1_host_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4155,7 +4267,7 @@ func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledRequest.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{59} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{61} } func (x *SetAgencyJoinEnabledRequest) GetMeta() *RequestMeta { @@ -4209,7 +4321,7 @@ type SetAgencyJoinEnabledResponse struct { func (x *SetAgencyJoinEnabledResponse) Reset() { *x = SetAgencyJoinEnabledResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[60] + mi := &file_proto_user_v1_host_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4221,7 +4333,7 @@ func (x *SetAgencyJoinEnabledResponse) String() string { func (*SetAgencyJoinEnabledResponse) ProtoMessage() {} func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[60] + mi := &file_proto_user_v1_host_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4234,7 +4346,7 @@ func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledResponse.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{60} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{62} } func (x *SetAgencyJoinEnabledResponse) GetAgency() *Agency { @@ -4459,6 +4571,14 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"Q\n" + "\x1cListBDLeaderAgenciesResponse\x121\n" + + "\bagencies\x18\x01 \x03(\v2\x15.hyapp.user.v1.AgencyR\bagencies\"\x9a\x01\n" + + "\x15ListBDAgenciesRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1c\n" + + "\n" + + "bd_user_id\x18\x02 \x01(\x03R\bbdUserId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"K\n" + + "\x16ListBDAgenciesResponse\x121\n" + "\bagencies\x18\x01 \x03(\v2\x15.hyapp.user.v1.AgencyR\bagencies\"\xe6\x01\n" + "\x1cProcessRoleInvitationRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + @@ -4618,7 +4738,7 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\fjoin_enabled\x18\x05 \x01(\bR\vjoinEnabled\x12\x16\n" + "\x06reason\x18\x06 \x01(\tR\x06reason\"M\n" + "\x1cSetAgencyJoinEnabledResponse\x12-\n" + - "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency2\xdc\x0e\n" + + "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency2\xbb\x0f\n" + "\x0fUserHostService\x12]\n" + "\x0eSearchAgencies\x12$.hyapp.user.v1.SearchAgenciesRequest\x1a%.hyapp.user.v1.SearchAgenciesResponse\x12Z\n" + "\rApplyToAgency\x12#.hyapp.user.v1.ApplyToAgencyRequest\x1a$.hyapp.user.v1.ApplyToAgencyResponse\x12x\n" + @@ -4627,7 +4747,8 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\fInviteAgency\x12\".hyapp.user.v1.InviteAgencyRequest\x1a#.hyapp.user.v1.InviteAgencyResponse\x12K\n" + "\bInviteBD\x12\x1e.hyapp.user.v1.InviteBDRequest\x1a\x1f.hyapp.user.v1.InviteBDResponse\x12`\n" + "\x0fListBDLeaderBDs\x12%.hyapp.user.v1.ListBDLeaderBDsRequest\x1a&.hyapp.user.v1.ListBDLeaderBDsResponse\x12o\n" + - "\x14ListBDLeaderAgencies\x12*.hyapp.user.v1.ListBDLeaderAgenciesRequest\x1a+.hyapp.user.v1.ListBDLeaderAgenciesResponse\x12r\n" + + "\x14ListBDLeaderAgencies\x12*.hyapp.user.v1.ListBDLeaderAgenciesRequest\x1a+.hyapp.user.v1.ListBDLeaderAgenciesResponse\x12]\n" + + "\x0eListBDAgencies\x12$.hyapp.user.v1.ListBDAgenciesRequest\x1a%.hyapp.user.v1.ListBDAgenciesResponse\x12r\n" + "\x15ProcessRoleInvitation\x12+.hyapp.user.v1.ProcessRoleInvitationRequest\x1a,.hyapp.user.v1.ProcessRoleInvitationResponse\x12]\n" + "\x0eGetHostProfile\x12$.hyapp.user.v1.GetHostProfileRequest\x1a%.hyapp.user.v1.GetHostProfileResponse\x12W\n" + "\fGetBDProfile\x12\".hyapp.user.v1.GetBDProfileRequest\x1a#.hyapp.user.v1.GetBDProfileResponse\x12o\n" + @@ -4660,7 +4781,7 @@ func file_proto_user_v1_host_proto_rawDescGZIP() []byte { return file_proto_user_v1_host_proto_rawDescData } -var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 61) +var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 63) var file_proto_user_v1_host_proto_goTypes = []any{ (*HostProfile)(nil), // 0: hyapp.user.v1.HostProfile (*Agency)(nil), // 1: hyapp.user.v1.Agency @@ -4687,162 +4808,168 @@ var file_proto_user_v1_host_proto_goTypes = []any{ (*ListBDLeaderBDsResponse)(nil), // 22: hyapp.user.v1.ListBDLeaderBDsResponse (*ListBDLeaderAgenciesRequest)(nil), // 23: hyapp.user.v1.ListBDLeaderAgenciesRequest (*ListBDLeaderAgenciesResponse)(nil), // 24: hyapp.user.v1.ListBDLeaderAgenciesResponse - (*ProcessRoleInvitationRequest)(nil), // 25: hyapp.user.v1.ProcessRoleInvitationRequest - (*ProcessRoleInvitationResponse)(nil), // 26: hyapp.user.v1.ProcessRoleInvitationResponse - (*GetHostProfileRequest)(nil), // 27: hyapp.user.v1.GetHostProfileRequest - (*GetHostProfileResponse)(nil), // 28: hyapp.user.v1.GetHostProfileResponse - (*GetBDProfileRequest)(nil), // 29: hyapp.user.v1.GetBDProfileRequest - (*GetBDProfileResponse)(nil), // 30: hyapp.user.v1.GetBDProfileResponse - (*GetCoinSellerProfileRequest)(nil), // 31: hyapp.user.v1.GetCoinSellerProfileRequest - (*GetCoinSellerProfileResponse)(nil), // 32: hyapp.user.v1.GetCoinSellerProfileResponse - (*ListActiveCoinSellersInMyRegionRequest)(nil), // 33: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - (*ListActiveCoinSellersInMyRegionResponse)(nil), // 34: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - (*GetUserRoleSummaryRequest)(nil), // 35: hyapp.user.v1.GetUserRoleSummaryRequest - (*GetUserRoleSummaryResponse)(nil), // 36: hyapp.user.v1.GetUserRoleSummaryResponse - (*GetAgencyRequest)(nil), // 37: hyapp.user.v1.GetAgencyRequest - (*GetAgencyResponse)(nil), // 38: hyapp.user.v1.GetAgencyResponse - (*CheckBusinessCapabilityRequest)(nil), // 39: hyapp.user.v1.CheckBusinessCapabilityRequest - (*CheckBusinessCapabilityResponse)(nil), // 40: hyapp.user.v1.CheckBusinessCapabilityResponse - (*GetAgencyMembersRequest)(nil), // 41: hyapp.user.v1.GetAgencyMembersRequest - (*GetAgencyMembersResponse)(nil), // 42: hyapp.user.v1.GetAgencyMembersResponse - (*GetAgencyApplicationsRequest)(nil), // 43: hyapp.user.v1.GetAgencyApplicationsRequest - (*GetAgencyApplicationsResponse)(nil), // 44: hyapp.user.v1.GetAgencyApplicationsResponse - (*CreateBDLeaderRequest)(nil), // 45: hyapp.user.v1.CreateBDLeaderRequest - (*CreateBDLeaderResponse)(nil), // 46: hyapp.user.v1.CreateBDLeaderResponse - (*CreateBDRequest)(nil), // 47: hyapp.user.v1.CreateBDRequest - (*CreateBDResponse)(nil), // 48: hyapp.user.v1.CreateBDResponse - (*SetBDStatusRequest)(nil), // 49: hyapp.user.v1.SetBDStatusRequest - (*SetBDStatusResponse)(nil), // 50: hyapp.user.v1.SetBDStatusResponse - (*CreateCoinSellerRequest)(nil), // 51: hyapp.user.v1.CreateCoinSellerRequest - (*CreateCoinSellerResponse)(nil), // 52: hyapp.user.v1.CreateCoinSellerResponse - (*SetCoinSellerStatusRequest)(nil), // 53: hyapp.user.v1.SetCoinSellerStatusRequest - (*SetCoinSellerStatusResponse)(nil), // 54: hyapp.user.v1.SetCoinSellerStatusResponse - (*CreateAgencyRequest)(nil), // 55: hyapp.user.v1.CreateAgencyRequest - (*CreateAgencyResponse)(nil), // 56: hyapp.user.v1.CreateAgencyResponse - (*CloseAgencyRequest)(nil), // 57: hyapp.user.v1.CloseAgencyRequest - (*CloseAgencyResponse)(nil), // 58: hyapp.user.v1.CloseAgencyResponse - (*SetAgencyJoinEnabledRequest)(nil), // 59: hyapp.user.v1.SetAgencyJoinEnabledRequest - (*SetAgencyJoinEnabledResponse)(nil), // 60: hyapp.user.v1.SetAgencyJoinEnabledResponse - (*RequestMeta)(nil), // 61: hyapp.user.v1.RequestMeta + (*ListBDAgenciesRequest)(nil), // 25: hyapp.user.v1.ListBDAgenciesRequest + (*ListBDAgenciesResponse)(nil), // 26: hyapp.user.v1.ListBDAgenciesResponse + (*ProcessRoleInvitationRequest)(nil), // 27: hyapp.user.v1.ProcessRoleInvitationRequest + (*ProcessRoleInvitationResponse)(nil), // 28: hyapp.user.v1.ProcessRoleInvitationResponse + (*GetHostProfileRequest)(nil), // 29: hyapp.user.v1.GetHostProfileRequest + (*GetHostProfileResponse)(nil), // 30: hyapp.user.v1.GetHostProfileResponse + (*GetBDProfileRequest)(nil), // 31: hyapp.user.v1.GetBDProfileRequest + (*GetBDProfileResponse)(nil), // 32: hyapp.user.v1.GetBDProfileResponse + (*GetCoinSellerProfileRequest)(nil), // 33: hyapp.user.v1.GetCoinSellerProfileRequest + (*GetCoinSellerProfileResponse)(nil), // 34: hyapp.user.v1.GetCoinSellerProfileResponse + (*ListActiveCoinSellersInMyRegionRequest)(nil), // 35: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + (*ListActiveCoinSellersInMyRegionResponse)(nil), // 36: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + (*GetUserRoleSummaryRequest)(nil), // 37: hyapp.user.v1.GetUserRoleSummaryRequest + (*GetUserRoleSummaryResponse)(nil), // 38: hyapp.user.v1.GetUserRoleSummaryResponse + (*GetAgencyRequest)(nil), // 39: hyapp.user.v1.GetAgencyRequest + (*GetAgencyResponse)(nil), // 40: hyapp.user.v1.GetAgencyResponse + (*CheckBusinessCapabilityRequest)(nil), // 41: hyapp.user.v1.CheckBusinessCapabilityRequest + (*CheckBusinessCapabilityResponse)(nil), // 42: hyapp.user.v1.CheckBusinessCapabilityResponse + (*GetAgencyMembersRequest)(nil), // 43: hyapp.user.v1.GetAgencyMembersRequest + (*GetAgencyMembersResponse)(nil), // 44: hyapp.user.v1.GetAgencyMembersResponse + (*GetAgencyApplicationsRequest)(nil), // 45: hyapp.user.v1.GetAgencyApplicationsRequest + (*GetAgencyApplicationsResponse)(nil), // 46: hyapp.user.v1.GetAgencyApplicationsResponse + (*CreateBDLeaderRequest)(nil), // 47: hyapp.user.v1.CreateBDLeaderRequest + (*CreateBDLeaderResponse)(nil), // 48: hyapp.user.v1.CreateBDLeaderResponse + (*CreateBDRequest)(nil), // 49: hyapp.user.v1.CreateBDRequest + (*CreateBDResponse)(nil), // 50: hyapp.user.v1.CreateBDResponse + (*SetBDStatusRequest)(nil), // 51: hyapp.user.v1.SetBDStatusRequest + (*SetBDStatusResponse)(nil), // 52: hyapp.user.v1.SetBDStatusResponse + (*CreateCoinSellerRequest)(nil), // 53: hyapp.user.v1.CreateCoinSellerRequest + (*CreateCoinSellerResponse)(nil), // 54: hyapp.user.v1.CreateCoinSellerResponse + (*SetCoinSellerStatusRequest)(nil), // 55: hyapp.user.v1.SetCoinSellerStatusRequest + (*SetCoinSellerStatusResponse)(nil), // 56: hyapp.user.v1.SetCoinSellerStatusResponse + (*CreateAgencyRequest)(nil), // 57: hyapp.user.v1.CreateAgencyRequest + (*CreateAgencyResponse)(nil), // 58: hyapp.user.v1.CreateAgencyResponse + (*CloseAgencyRequest)(nil), // 59: hyapp.user.v1.CloseAgencyRequest + (*CloseAgencyResponse)(nil), // 60: hyapp.user.v1.CloseAgencyResponse + (*SetAgencyJoinEnabledRequest)(nil), // 61: hyapp.user.v1.SetAgencyJoinEnabledRequest + (*SetAgencyJoinEnabledResponse)(nil), // 62: hyapp.user.v1.SetAgencyJoinEnabledResponse + (*RequestMeta)(nil), // 63: hyapp.user.v1.RequestMeta } var file_proto_user_v1_host_proto_depIdxs = []int32{ - 61, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 1: hyapp.user.v1.SearchAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 61, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 3: hyapp.user.v1.ApplyToAgencyResponse.application:type_name -> hyapp.user.v1.AgencyApplication - 61, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 5: hyapp.user.v1.ReviewAgencyApplicationResponse.application:type_name -> hyapp.user.v1.AgencyApplication 0, // 6: hyapp.user.v1.ReviewAgencyApplicationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 7: hyapp.user.v1.ReviewAgencyApplicationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 61, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 9: hyapp.user.v1.KickAgencyHostResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 0, // 10: hyapp.user.v1.KickAgencyHostResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 61, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 12: hyapp.user.v1.InviteAgencyResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 61, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 14: hyapp.user.v1.InviteBDResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 61, // 15: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 15: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 16: hyapp.user.v1.ListBDLeaderBDsResponse.bd_profiles:type_name -> hyapp.user.v1.BDProfile - 61, // 17: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 17: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 18: hyapp.user.v1.ListBDLeaderAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 61, // 19: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 8, // 20: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 0, // 21: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 1, // 22: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency - 6, // 23: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 2, // 24: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 61, // 25: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 0, // 26: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 61, // 27: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 28: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 61, // 29: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 30: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 61, // 31: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 4, // 32: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem - 61, // 33: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 34: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary - 61, // 35: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 36: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 61, // 37: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 61, // 38: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 6, // 39: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership - 61, // 40: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 7, // 41: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication - 61, // 42: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 43: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 61, // 44: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 45: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 61, // 46: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 2, // 47: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 61, // 48: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 49: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 61, // 50: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 3, // 51: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 61, // 52: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 53: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 0, // 54: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 6, // 55: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 61, // 56: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 57: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 61, // 58: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 59: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency - 9, // 60: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest - 11, // 61: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest - 13, // 62: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest - 15, // 63: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest - 17, // 64: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest - 19, // 65: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest - 21, // 66: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest - 23, // 67: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest - 25, // 68: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest - 27, // 69: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest - 29, // 70: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest - 31, // 71: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest - 33, // 72: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - 35, // 73: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest - 37, // 74: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest - 39, // 75: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest - 41, // 76: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest - 43, // 77: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest - 45, // 78: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest - 47, // 79: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest - 49, // 80: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest - 51, // 81: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest - 53, // 82: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest - 55, // 83: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest - 57, // 84: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest - 59, // 85: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest - 10, // 86: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse - 12, // 87: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse - 14, // 88: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse - 16, // 89: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse - 18, // 90: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse - 20, // 91: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse - 22, // 92: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse - 24, // 93: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse - 26, // 94: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse - 28, // 95: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse - 30, // 96: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse - 32, // 97: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse - 34, // 98: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - 36, // 99: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse - 38, // 100: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse - 40, // 101: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse - 42, // 102: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse - 44, // 103: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse - 46, // 104: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse - 48, // 105: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse - 50, // 106: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse - 52, // 107: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse - 54, // 108: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse - 56, // 109: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse - 58, // 110: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse - 60, // 111: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse - 86, // [86:112] is the sub-list for method output_type - 60, // [60:86] is the sub-list for method input_type - 60, // [60:60] is the sub-list for extension type_name - 60, // [60:60] is the sub-list for extension extendee - 0, // [0:60] is the sub-list for field type_name + 63, // 19: hyapp.user.v1.ListBDAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 20: hyapp.user.v1.ListBDAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency + 63, // 21: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 8, // 22: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation + 0, // 23: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 1, // 24: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency + 6, // 25: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership + 2, // 26: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 63, // 27: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 0, // 28: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 63, // 29: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 30: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 63, // 31: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 32: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 63, // 33: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 4, // 34: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem + 63, // 35: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 36: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary + 63, // 37: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 38: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 63, // 39: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 63, // 40: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 6, // 41: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership + 63, // 42: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 7, // 43: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication + 63, // 44: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 45: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 63, // 46: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 47: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 63, // 48: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 2, // 49: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile + 63, // 50: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 51: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 63, // 52: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 3, // 53: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile + 63, // 54: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 55: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 0, // 56: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile + 6, // 57: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership + 63, // 58: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 59: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 63, // 60: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 61: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency + 9, // 62: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest + 11, // 63: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest + 13, // 64: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest + 15, // 65: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest + 17, // 66: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest + 19, // 67: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest + 21, // 68: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest + 23, // 69: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest + 25, // 70: hyapp.user.v1.UserHostService.ListBDAgencies:input_type -> hyapp.user.v1.ListBDAgenciesRequest + 27, // 71: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest + 29, // 72: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest + 31, // 73: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest + 33, // 74: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest + 35, // 75: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + 37, // 76: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest + 39, // 77: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest + 41, // 78: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest + 43, // 79: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest + 45, // 80: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest + 47, // 81: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest + 49, // 82: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest + 51, // 83: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest + 53, // 84: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest + 55, // 85: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest + 57, // 86: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest + 59, // 87: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest + 61, // 88: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest + 10, // 89: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse + 12, // 90: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse + 14, // 91: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse + 16, // 92: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse + 18, // 93: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse + 20, // 94: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse + 22, // 95: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse + 24, // 96: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse + 26, // 97: hyapp.user.v1.UserHostService.ListBDAgencies:output_type -> hyapp.user.v1.ListBDAgenciesResponse + 28, // 98: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse + 30, // 99: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse + 32, // 100: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse + 34, // 101: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse + 36, // 102: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + 38, // 103: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse + 40, // 104: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse + 42, // 105: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse + 44, // 106: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse + 46, // 107: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse + 48, // 108: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse + 50, // 109: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse + 52, // 110: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse + 54, // 111: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse + 56, // 112: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse + 58, // 113: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse + 60, // 114: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse + 62, // 115: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse + 89, // [89:116] is the sub-list for method output_type + 62, // [62:89] is the sub-list for method input_type + 62, // [62:62] is the sub-list for extension type_name + 62, // [62:62] is the sub-list for extension extendee + 0, // [0:62] is the sub-list for field type_name } func init() { file_proto_user_v1_host_proto_init() } @@ -4857,7 +4984,7 @@ func file_proto_user_v1_host_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_host_proto_rawDesc), len(file_proto_user_v1_host_proto_rawDesc)), NumEnums: 0, - NumMessages: 61, + NumMessages: 63, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/user/v1/host.proto b/api/proto/user/v1/host.proto index b18edc2d..44ce416e 100644 --- a/api/proto/user/v1/host.proto +++ b/api/proto/user/v1/host.proto @@ -243,6 +243,17 @@ message ListBDLeaderAgenciesResponse { repeated Agency agencies = 1; } +message ListBDAgenciesRequest { + RequestMeta meta = 1; + int64 bd_user_id = 2; + string status = 3; + int32 page_size = 4; +} + +message ListBDAgenciesResponse { + repeated Agency agencies = 1; +} + message ProcessRoleInvitationRequest { RequestMeta meta = 1; string command_id = 2; @@ -462,6 +473,7 @@ service UserHostService { rpc InviteBD(InviteBDRequest) returns (InviteBDResponse); rpc ListBDLeaderBDs(ListBDLeaderBDsRequest) returns (ListBDLeaderBDsResponse); rpc ListBDLeaderAgencies(ListBDLeaderAgenciesRequest) returns (ListBDLeaderAgenciesResponse); + rpc ListBDAgencies(ListBDAgenciesRequest) returns (ListBDAgenciesResponse); rpc ProcessRoleInvitation(ProcessRoleInvitationRequest) returns (ProcessRoleInvitationResponse); rpc GetHostProfile(GetHostProfileRequest) returns (GetHostProfileResponse); rpc GetBDProfile(GetBDProfileRequest) returns (GetBDProfileResponse); diff --git a/api/proto/user/v1/host_grpc.pb.go b/api/proto/user/v1/host_grpc.pb.go index 7765209f..45ac7fcb 100644 --- a/api/proto/user/v1/host_grpc.pb.go +++ b/api/proto/user/v1/host_grpc.pb.go @@ -27,6 +27,7 @@ const ( UserHostService_InviteBD_FullMethodName = "/hyapp.user.v1.UserHostService/InviteBD" UserHostService_ListBDLeaderBDs_FullMethodName = "/hyapp.user.v1.UserHostService/ListBDLeaderBDs" UserHostService_ListBDLeaderAgencies_FullMethodName = "/hyapp.user.v1.UserHostService/ListBDLeaderAgencies" + UserHostService_ListBDAgencies_FullMethodName = "/hyapp.user.v1.UserHostService/ListBDAgencies" UserHostService_ProcessRoleInvitation_FullMethodName = "/hyapp.user.v1.UserHostService/ProcessRoleInvitation" UserHostService_GetHostProfile_FullMethodName = "/hyapp.user.v1.UserHostService/GetHostProfile" UserHostService_GetBDProfile_FullMethodName = "/hyapp.user.v1.UserHostService/GetBDProfile" @@ -53,6 +54,7 @@ type UserHostServiceClient interface { InviteBD(ctx context.Context, in *InviteBDRequest, opts ...grpc.CallOption) (*InviteBDResponse, error) ListBDLeaderBDs(ctx context.Context, in *ListBDLeaderBDsRequest, opts ...grpc.CallOption) (*ListBDLeaderBDsResponse, error) ListBDLeaderAgencies(ctx context.Context, in *ListBDLeaderAgenciesRequest, opts ...grpc.CallOption) (*ListBDLeaderAgenciesResponse, error) + ListBDAgencies(ctx context.Context, in *ListBDAgenciesRequest, opts ...grpc.CallOption) (*ListBDAgenciesResponse, error) ProcessRoleInvitation(ctx context.Context, in *ProcessRoleInvitationRequest, opts ...grpc.CallOption) (*ProcessRoleInvitationResponse, error) GetHostProfile(ctx context.Context, in *GetHostProfileRequest, opts ...grpc.CallOption) (*GetHostProfileResponse, error) GetBDProfile(ctx context.Context, in *GetBDProfileRequest, opts ...grpc.CallOption) (*GetBDProfileResponse, error) @@ -153,6 +155,16 @@ func (c *userHostServiceClient) ListBDLeaderAgencies(ctx context.Context, in *Li return out, nil } +func (c *userHostServiceClient) ListBDAgencies(ctx context.Context, in *ListBDAgenciesRequest, opts ...grpc.CallOption) (*ListBDAgenciesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListBDAgenciesResponse) + err := c.cc.Invoke(ctx, UserHostService_ListBDAgencies_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userHostServiceClient) ProcessRoleInvitation(ctx context.Context, in *ProcessRoleInvitationRequest, opts ...grpc.CallOption) (*ProcessRoleInvitationResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ProcessRoleInvitationResponse) @@ -267,6 +279,7 @@ type UserHostServiceServer interface { InviteBD(context.Context, *InviteBDRequest) (*InviteBDResponse, error) ListBDLeaderBDs(context.Context, *ListBDLeaderBDsRequest) (*ListBDLeaderBDsResponse, error) ListBDLeaderAgencies(context.Context, *ListBDLeaderAgenciesRequest) (*ListBDLeaderAgenciesResponse, error) + ListBDAgencies(context.Context, *ListBDAgenciesRequest) (*ListBDAgenciesResponse, error) ProcessRoleInvitation(context.Context, *ProcessRoleInvitationRequest) (*ProcessRoleInvitationResponse, error) GetHostProfile(context.Context, *GetHostProfileRequest) (*GetHostProfileResponse, error) GetBDProfile(context.Context, *GetBDProfileRequest) (*GetBDProfileResponse, error) @@ -311,6 +324,9 @@ func (UnimplementedUserHostServiceServer) ListBDLeaderBDs(context.Context, *List func (UnimplementedUserHostServiceServer) ListBDLeaderAgencies(context.Context, *ListBDLeaderAgenciesRequest) (*ListBDLeaderAgenciesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListBDLeaderAgencies not implemented") } +func (UnimplementedUserHostServiceServer) ListBDAgencies(context.Context, *ListBDAgenciesRequest) (*ListBDAgenciesResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListBDAgencies not implemented") +} func (UnimplementedUserHostServiceServer) ProcessRoleInvitation(context.Context, *ProcessRoleInvitationRequest) (*ProcessRoleInvitationResponse, error) { return nil, status.Error(codes.Unimplemented, "method ProcessRoleInvitation not implemented") } @@ -506,6 +522,24 @@ func _UserHostService_ListBDLeaderAgencies_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _UserHostService_ListBDAgencies_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListBDAgenciesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserHostServiceServer).ListBDAgencies(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserHostService_ListBDAgencies_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserHostServiceServer).ListBDAgencies(ctx, req.(*ListBDAgenciesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserHostService_ProcessRoleInvitation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ProcessRoleInvitationRequest) if err := dec(in); err != nil { @@ -725,6 +759,10 @@ var UserHostService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListBDLeaderAgencies", Handler: _UserHostService_ListBDLeaderAgencies_Handler, }, + { + MethodName: "ListBDAgencies", + Handler: _UserHostService_ListBDAgencies_Handler, + }, { MethodName: "ProcessRoleInvitation", Handler: _UserHostService_ProcessRoleInvitation_Handler, diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index 533d6dc2..1171ab46 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -33,7 +33,7 @@ type DebitGiftRequest struct { // price_version 为空时使用当前生效价格;非空时必须命中 active 价格版本。 PriceVersion string `protobuf:"bytes,7,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性。 + // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性和匹配房间贡献比例。 RegionId int64 `protobuf:"varint,9,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` // target_is_host 由 gateway 根据 user-service active host profile 注入,客户端不能直接声明。 TargetIsHost bool `protobuf:"varint,10,opt,name=target_is_host,json=targetIsHost,proto3" json:"target_is_host,omitempty"` @@ -41,7 +41,7 @@ type DebitGiftRequest struct { TargetHostRegionId int64 `protobuf:"varint,11,opt,name=target_host_region_id,json=targetHostRegionId,proto3" json:"target_host_region_id,omitempty"` // target_agency_owner_user_id 是送礼时主播归属 Agency 的 owner,用于后续代理工资结算。 TargetAgencyOwnerUserId int64 `protobuf:"varint,12,opt,name=target_agency_owner_user_id,json=targetAgencyOwnerUserId,proto3" json:"target_agency_owner_user_id,omitempty"` - // sender_region_id 是送礼用户所属区域,用于匹配礼物入主播周期钻石比例;不能用房间 visible_region_id 替代。 + // sender_region_id 是送礼用户所属区域快照;不能用房间 visible_region_id 替代。 SenderRegionId int64 `protobuf:"varint,13,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache @@ -384,17 +384,18 @@ func (x *DebitGiftTarget) GetTargetAgencyOwnerUserId() int64 { // BatchDebitGiftRequest 在一个钱包事务内完成同一 sender 对多个 target 的送礼扣费。 type BatchDebitGiftRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - SenderRegionId int64 `protobuf:"varint,9,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` - Targets []*DebitGiftTarget `protobuf:"bytes,10,rep,name=targets,proto3" json:"targets,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性和匹配房间贡献比例。 + RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + SenderRegionId int64 `protobuf:"varint,9,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` + Targets []*DebitGiftTarget `protobuf:"bytes,10,rep,name=targets,proto3" json:"targets,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1972,6 +1973,581 @@ func (x *TransferCoinFromSellerResponse) GetRechargePolicyUsdMinorAmount() int64 return 0 } +// CoinSellerSalaryExchangeRateTier 是用户工资转给币商时,按区域和美元金额命中的金币兑换区间。 +type CoinSellerSalaryExchangeRateTier struct { + state protoimpl.MessageState `protogen:"open.v1"` + RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + MinUsdMinor int64 `protobuf:"varint,2,opt,name=min_usd_minor,json=minUsdMinor,proto3" json:"min_usd_minor,omitempty"` + MaxUsdMinor int64 `protobuf:"varint,3,opt,name=max_usd_minor,json=maxUsdMinor,proto3" json:"max_usd_minor,omitempty"` + CoinPerUsd int64 `protobuf:"varint,4,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CoinSellerSalaryExchangeRateTier) Reset() { + *x = CoinSellerSalaryExchangeRateTier{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CoinSellerSalaryExchangeRateTier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CoinSellerSalaryExchangeRateTier) ProtoMessage() {} + +func (x *CoinSellerSalaryExchangeRateTier) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + 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 CoinSellerSalaryExchangeRateTier.ProtoReflect.Descriptor instead. +func (*CoinSellerSalaryExchangeRateTier) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{22} +} + +func (x *CoinSellerSalaryExchangeRateTier) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *CoinSellerSalaryExchangeRateTier) GetMinUsdMinor() int64 { + if x != nil { + return x.MinUsdMinor + } + return 0 +} + +func (x *CoinSellerSalaryExchangeRateTier) GetMaxUsdMinor() int64 { + if x != nil { + return x.MaxUsdMinor + } + return 0 +} + +func (x *CoinSellerSalaryExchangeRateTier) GetCoinPerUsd() int64 { + if x != nil { + return x.CoinPerUsd + } + return 0 +} + +func (x *CoinSellerSalaryExchangeRateTier) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CoinSellerSalaryExchangeRateTier) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +func (x *CoinSellerSalaryExchangeRateTier) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +type ListCoinSellerSalaryExchangeRateTiersRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + IncludeDisabled bool `protobuf:"varint,4,opt,name=include_disabled,json=includeDisabled,proto3" json:"include_disabled,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) Reset() { + *x = ListCoinSellerSalaryExchangeRateTiersRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCoinSellerSalaryExchangeRateTiersRequest) ProtoMessage() {} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + 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 ListCoinSellerSalaryExchangeRateTiersRequest.ProtoReflect.Descriptor instead. +func (*ListCoinSellerSalaryExchangeRateTiersRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{23} +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetIncludeDisabled() bool { + if x != nil { + return x.IncludeDisabled + } + return false +} + +type ListCoinSellerSalaryExchangeRateTiersResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tiers []*CoinSellerSalaryExchangeRateTier `protobuf:"bytes,1,rep,name=tiers,proto3" json:"tiers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCoinSellerSalaryExchangeRateTiersResponse) Reset() { + *x = ListCoinSellerSalaryExchangeRateTiersResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCoinSellerSalaryExchangeRateTiersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCoinSellerSalaryExchangeRateTiersResponse) ProtoMessage() {} + +func (x *ListCoinSellerSalaryExchangeRateTiersResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + 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 ListCoinSellerSalaryExchangeRateTiersResponse.ProtoReflect.Descriptor instead. +func (*ListCoinSellerSalaryExchangeRateTiersResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{24} +} + +func (x *ListCoinSellerSalaryExchangeRateTiersResponse) GetTiers() []*CoinSellerSalaryExchangeRateTier { + if x != nil { + return x.Tiers + } + return nil +} + +// ExchangeSalaryToCoinRequest 扣当前用户某个身份工资美元钱包,并按固定比例给同一用户加普通 COIN。 +type ExchangeSalaryToCoinRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SalaryAssetType string `protobuf:"bytes,3,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExchangeSalaryToCoinRequest) Reset() { + *x = ExchangeSalaryToCoinRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExchangeSalaryToCoinRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExchangeSalaryToCoinRequest) ProtoMessage() {} + +func (x *ExchangeSalaryToCoinRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + 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 ExchangeSalaryToCoinRequest.ProtoReflect.Descriptor instead. +func (*ExchangeSalaryToCoinRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{25} +} + +func (x *ExchangeSalaryToCoinRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *ExchangeSalaryToCoinRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ExchangeSalaryToCoinRequest) GetSalaryAssetType() string { + if x != nil { + return x.SalaryAssetType + } + return "" +} + +func (x *ExchangeSalaryToCoinRequest) GetSalaryUsdMinor() int64 { + if x != nil { + return x.SalaryUsdMinor + } + return 0 +} + +func (x *ExchangeSalaryToCoinRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *ExchangeSalaryToCoinRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +type ExchangeSalaryToCoinResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=salary_balance_after,json=salaryBalanceAfter,proto3" json:"salary_balance_after,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExchangeSalaryToCoinResponse) Reset() { + *x = ExchangeSalaryToCoinResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExchangeSalaryToCoinResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExchangeSalaryToCoinResponse) ProtoMessage() {} + +func (x *ExchangeSalaryToCoinResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + 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 ExchangeSalaryToCoinResponse.ProtoReflect.Descriptor instead. +func (*ExchangeSalaryToCoinResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{26} +} + +func (x *ExchangeSalaryToCoinResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *ExchangeSalaryToCoinResponse) GetSalaryBalanceAfter() int64 { + if x != nil { + return x.SalaryBalanceAfter + } + return 0 +} + +func (x *ExchangeSalaryToCoinResponse) GetCoinBalanceAfter() int64 { + if x != nil { + return x.CoinBalanceAfter + } + return 0 +} + +func (x *ExchangeSalaryToCoinResponse) GetSalaryUsdMinor() int64 { + if x != nil { + return x.SalaryUsdMinor + } + return 0 +} + +func (x *ExchangeSalaryToCoinResponse) GetCoinAmount() int64 { + if x != nil { + return x.CoinAmount + } + return 0 +} + +func (x *ExchangeSalaryToCoinResponse) GetCoinPerUsd() int64 { + if x != nil { + return x.CoinPerUsd + } + return 0 +} + +// TransferSalaryToCoinSellerRequest 扣当前用户某个身份工资美元钱包,并按区域区间比例给同区域币商加专用金币库存。 +type TransferSalaryToCoinSellerRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SourceUserId int64 `protobuf:"varint,2,opt,name=source_user_id,json=sourceUserId,proto3" json:"source_user_id,omitempty"` + SellerUserId int64 `protobuf:"varint,3,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + SalaryAssetType string `protobuf:"bytes,4,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,5,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TransferSalaryToCoinSellerRequest) Reset() { + *x = TransferSalaryToCoinSellerRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TransferSalaryToCoinSellerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransferSalaryToCoinSellerRequest) ProtoMessage() {} + +func (x *TransferSalaryToCoinSellerRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + 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 TransferSalaryToCoinSellerRequest.ProtoReflect.Descriptor instead. +func (*TransferSalaryToCoinSellerRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{27} +} + +func (x *TransferSalaryToCoinSellerRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *TransferSalaryToCoinSellerRequest) GetSourceUserId() int64 { + if x != nil { + return x.SourceUserId + } + return 0 +} + +func (x *TransferSalaryToCoinSellerRequest) GetSellerUserId() int64 { + if x != nil { + return x.SellerUserId + } + return 0 +} + +func (x *TransferSalaryToCoinSellerRequest) GetSalaryAssetType() string { + if x != nil { + return x.SalaryAssetType + } + return "" +} + +func (x *TransferSalaryToCoinSellerRequest) GetSalaryUsdMinor() int64 { + if x != nil { + return x.SalaryUsdMinor + } + return 0 +} + +func (x *TransferSalaryToCoinSellerRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *TransferSalaryToCoinSellerRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *TransferSalaryToCoinSellerRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +type TransferSalaryToCoinSellerResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SourceSalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=source_salary_balance_after,json=sourceSalaryBalanceAfter,proto3" json:"source_salary_balance_after,omitempty"` + SellerBalanceAfter int64 `protobuf:"varint,3,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` + RateMinUsdMinor int64 `protobuf:"varint,7,opt,name=rate_min_usd_minor,json=rateMinUsdMinor,proto3" json:"rate_min_usd_minor,omitempty"` + RateMaxUsdMinor int64 `protobuf:"varint,8,opt,name=rate_max_usd_minor,json=rateMaxUsdMinor,proto3" json:"rate_max_usd_minor,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TransferSalaryToCoinSellerResponse) Reset() { + *x = TransferSalaryToCoinSellerResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TransferSalaryToCoinSellerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TransferSalaryToCoinSellerResponse) ProtoMessage() {} + +func (x *TransferSalaryToCoinSellerResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + 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 TransferSalaryToCoinSellerResponse.ProtoReflect.Descriptor instead. +func (*TransferSalaryToCoinSellerResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{28} +} + +func (x *TransferSalaryToCoinSellerResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *TransferSalaryToCoinSellerResponse) GetSourceSalaryBalanceAfter() int64 { + if x != nil { + return x.SourceSalaryBalanceAfter + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetSellerBalanceAfter() int64 { + if x != nil { + return x.SellerBalanceAfter + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetSalaryUsdMinor() int64 { + if x != nil { + return x.SalaryUsdMinor + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetCoinAmount() int64 { + if x != nil { + return x.CoinAmount + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetCoinPerUsd() int64 { + if x != nil { + return x.CoinPerUsd + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetRateMinUsdMinor() int64 { + if x != nil { + return x.RateMinUsdMinor + } + return 0 +} + +func (x *TransferSalaryToCoinSellerResponse) GetRateMaxUsdMinor() int64 { + if x != nil { + return x.RateMaxUsdMinor + } + return 0 +} + // Resource 是资源库里可配置、可赠送、可被礼物引用的最小资源。 type Resource struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2005,7 +2581,7 @@ type Resource struct { func (x *Resource) Reset() { *x = Resource{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2017,7 +2593,7 @@ func (x *Resource) String() string { func (*Resource) ProtoMessage() {} func (x *Resource) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[22] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2030,7 +2606,7 @@ func (x *Resource) ProtoReflect() protoreflect.Message { // Deprecated: Use Resource.ProtoReflect.Descriptor instead. func (*Resource) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{22} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{29} } func (x *Resource) GetAppCode() string { @@ -2221,7 +2797,7 @@ type ResourceGroupItem struct { func (x *ResourceGroupItem) Reset() { *x = ResourceGroupItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2233,7 +2809,7 @@ func (x *ResourceGroupItem) String() string { func (*ResourceGroupItem) ProtoMessage() {} func (x *ResourceGroupItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[23] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2246,7 +2822,7 @@ func (x *ResourceGroupItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupItem.ProtoReflect.Descriptor instead. func (*ResourceGroupItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{23} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{30} } func (x *ResourceGroupItem) GetGroupItemId() int64 { @@ -2353,7 +2929,7 @@ type ResourceGroup struct { func (x *ResourceGroup) Reset() { *x = ResourceGroup{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2365,7 +2941,7 @@ func (x *ResourceGroup) String() string { func (*ResourceGroup) ProtoMessage() {} func (x *ResourceGroup) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[24] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2378,7 +2954,7 @@ func (x *ResourceGroup) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroup.ProtoReflect.Descriptor instead. func (*ResourceGroup) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{24} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{31} } func (x *ResourceGroup) GetAppCode() string { @@ -2495,7 +3071,7 @@ type GiftConfig struct { func (x *GiftConfig) Reset() { *x = GiftConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2507,7 +3083,7 @@ func (x *GiftConfig) String() string { func (*GiftConfig) ProtoMessage() {} func (x *GiftConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[25] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2520,7 +3096,7 @@ func (x *GiftConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftConfig.ProtoReflect.Descriptor instead. func (*GiftConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{25} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{32} } func (x *GiftConfig) GetAppCode() string { @@ -2695,7 +3271,7 @@ type GiftTypeConfig struct { func (x *GiftTypeConfig) Reset() { *x = GiftTypeConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2707,7 +3283,7 @@ func (x *GiftTypeConfig) String() string { func (*GiftTypeConfig) ProtoMessage() {} func (x *GiftTypeConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[26] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2720,7 +3296,7 @@ func (x *GiftTypeConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftTypeConfig.ProtoReflect.Descriptor instead. func (*GiftTypeConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{26} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{33} } func (x *GiftTypeConfig) GetAppCode() string { @@ -2816,7 +3392,7 @@ type ResourceShopItem struct { func (x *ResourceShopItem) Reset() { *x = ResourceShopItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2828,7 +3404,7 @@ func (x *ResourceShopItem) String() string { func (*ResourceShopItem) ProtoMessage() {} func (x *ResourceShopItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[27] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2841,7 +3417,7 @@ func (x *ResourceShopItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItem.ProtoReflect.Descriptor instead. func (*ResourceShopItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{27} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{34} } func (x *ResourceShopItem) GetAppCode() string { @@ -2971,7 +3547,7 @@ type UserResourceEntitlement struct { func (x *UserResourceEntitlement) Reset() { *x = UserResourceEntitlement{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2983,7 +3559,7 @@ func (x *UserResourceEntitlement) String() string { func (*UserResourceEntitlement) ProtoMessage() {} func (x *UserResourceEntitlement) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[28] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2996,7 +3572,7 @@ func (x *UserResourceEntitlement) ProtoReflect() protoreflect.Message { // Deprecated: Use UserResourceEntitlement.ProtoReflect.Descriptor instead. func (*UserResourceEntitlement) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{28} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{35} } func (x *UserResourceEntitlement) GetAppCode() string { @@ -3115,7 +3691,7 @@ type ResourceGrantItem struct { func (x *ResourceGrantItem) Reset() { *x = ResourceGrantItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3127,7 +3703,7 @@ func (x *ResourceGrantItem) String() string { func (*ResourceGrantItem) ProtoMessage() {} func (x *ResourceGrantItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[29] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3140,7 +3716,7 @@ func (x *ResourceGrantItem) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrantItem.ProtoReflect.Descriptor instead. func (*ResourceGrantItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{29} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{36} } func (x *ResourceGrantItem) GetGrantItemId() int64 { @@ -3234,7 +3810,7 @@ type ResourceGrant struct { func (x *ResourceGrant) Reset() { *x = ResourceGrant{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3246,7 +3822,7 @@ func (x *ResourceGrant) String() string { func (*ResourceGrant) ProtoMessage() {} func (x *ResourceGrant) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[30] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3259,7 +3835,7 @@ func (x *ResourceGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrant.ProtoReflect.Descriptor instead. func (*ResourceGrant) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{30} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{37} } func (x *ResourceGrant) GetAppCode() string { @@ -3368,7 +3944,7 @@ type ResourceGroupItemInput struct { func (x *ResourceGroupItemInput) Reset() { *x = ResourceGroupItemInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3380,7 +3956,7 @@ func (x *ResourceGroupItemInput) String() string { func (*ResourceGroupItemInput) ProtoMessage() {} func (x *ResourceGroupItemInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[31] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3393,7 +3969,7 @@ func (x *ResourceGroupItemInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupItemInput.ProtoReflect.Descriptor instead. func (*ResourceGroupItemInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{31} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{38} } func (x *ResourceGroupItemInput) GetResourceId() int64 { @@ -3462,7 +4038,7 @@ type ListResourcesRequest struct { func (x *ListResourcesRequest) Reset() { *x = ListResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3474,7 +4050,7 @@ func (x *ListResourcesRequest) String() string { func (*ListResourcesRequest) ProtoMessage() {} func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[32] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3487,7 +4063,7 @@ func (x *ListResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesRequest.ProtoReflect.Descriptor instead. func (*ListResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{32} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{39} } func (x *ListResourcesRequest) GetRequestId() string { @@ -3563,7 +4139,7 @@ type ListResourcesResponse struct { func (x *ListResourcesResponse) Reset() { *x = ListResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3575,7 +4151,7 @@ func (x *ListResourcesResponse) String() string { func (*ListResourcesResponse) ProtoMessage() {} func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[33] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3588,7 +4164,7 @@ func (x *ListResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourcesResponse.ProtoReflect.Descriptor instead. func (*ListResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{33} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{40} } func (x *ListResourcesResponse) GetResources() []*Resource { @@ -3616,7 +4192,7 @@ type GetResourceRequest struct { func (x *GetResourceRequest) Reset() { *x = GetResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3628,7 +4204,7 @@ func (x *GetResourceRequest) String() string { func (*GetResourceRequest) ProtoMessage() {} func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[34] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3641,7 +4217,7 @@ func (x *GetResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceRequest.ProtoReflect.Descriptor instead. func (*GetResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{34} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{41} } func (x *GetResourceRequest) GetRequestId() string { @@ -3674,7 +4250,7 @@ type GetResourceResponse struct { func (x *GetResourceResponse) Reset() { *x = GetResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3686,7 +4262,7 @@ func (x *GetResourceResponse) String() string { func (*GetResourceResponse) ProtoMessage() {} func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[35] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3699,7 +4275,7 @@ func (x *GetResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceResponse.ProtoReflect.Descriptor instead. func (*GetResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{35} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{42} } func (x *GetResourceResponse) GetResource() *Resource { @@ -3738,7 +4314,7 @@ type CreateResourceRequest struct { func (x *CreateResourceRequest) Reset() { *x = CreateResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3750,7 +4326,7 @@ func (x *CreateResourceRequest) String() string { func (*CreateResourceRequest) ProtoMessage() {} func (x *CreateResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[36] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3763,7 +4339,7 @@ func (x *CreateResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateResourceRequest.ProtoReflect.Descriptor instead. func (*CreateResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{36} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{43} } func (x *CreateResourceRequest) GetRequestId() string { @@ -3943,7 +4519,7 @@ type UpdateResourceRequest struct { func (x *UpdateResourceRequest) Reset() { *x = UpdateResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3955,7 +4531,7 @@ func (x *UpdateResourceRequest) String() string { func (*UpdateResourceRequest) ProtoMessage() {} func (x *UpdateResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[37] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3968,7 +4544,7 @@ func (x *UpdateResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourceRequest.ProtoReflect.Descriptor instead. func (*UpdateResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{37} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{44} } func (x *UpdateResourceRequest) GetRequestId() string { @@ -4138,7 +4714,7 @@ type SetResourceStatusRequest struct { func (x *SetResourceStatusRequest) Reset() { *x = SetResourceStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4150,7 +4726,7 @@ func (x *SetResourceStatusRequest) String() string { func (*SetResourceStatusRequest) ProtoMessage() {} func (x *SetResourceStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[38] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4163,7 +4739,7 @@ func (x *SetResourceStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{38} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{45} } func (x *SetResourceStatusRequest) GetRequestId() string { @@ -4210,7 +4786,7 @@ type ResourceResponse struct { func (x *ResourceResponse) Reset() { *x = ResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4222,7 +4798,7 @@ func (x *ResourceResponse) String() string { func (*ResourceResponse) ProtoMessage() {} func (x *ResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[39] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4235,7 +4811,7 @@ func (x *ResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceResponse.ProtoReflect.Descriptor instead. func (*ResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{39} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{46} } func (x *ResourceResponse) GetResource() *Resource { @@ -4260,7 +4836,7 @@ type ListResourceGroupsRequest struct { func (x *ListResourceGroupsRequest) Reset() { *x = ListResourceGroupsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4272,7 +4848,7 @@ func (x *ListResourceGroupsRequest) String() string { func (*ListResourceGroupsRequest) ProtoMessage() {} func (x *ListResourceGroupsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[40] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4285,7 +4861,7 @@ func (x *ListResourceGroupsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGroupsRequest.ProtoReflect.Descriptor instead. func (*ListResourceGroupsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{40} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{47} } func (x *ListResourceGroupsRequest) GetRequestId() string { @@ -4347,7 +4923,7 @@ type ListResourceGroupsResponse struct { func (x *ListResourceGroupsResponse) Reset() { *x = ListResourceGroupsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4359,7 +4935,7 @@ func (x *ListResourceGroupsResponse) String() string { func (*ListResourceGroupsResponse) ProtoMessage() {} func (x *ListResourceGroupsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[41] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4372,7 +4948,7 @@ func (x *ListResourceGroupsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGroupsResponse.ProtoReflect.Descriptor instead. func (*ListResourceGroupsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{41} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{48} } func (x *ListResourceGroupsResponse) GetGroups() []*ResourceGroup { @@ -4400,7 +4976,7 @@ type GetResourceGroupRequest struct { func (x *GetResourceGroupRequest) Reset() { *x = GetResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4412,7 +4988,7 @@ func (x *GetResourceGroupRequest) String() string { func (*GetResourceGroupRequest) ProtoMessage() {} func (x *GetResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[42] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4425,7 +5001,7 @@ func (x *GetResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceGroupRequest.ProtoReflect.Descriptor instead. func (*GetResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{42} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{49} } func (x *GetResourceGroupRequest) GetRequestId() string { @@ -4458,7 +5034,7 @@ type GetResourceGroupResponse struct { func (x *GetResourceGroupResponse) Reset() { *x = GetResourceGroupResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4470,7 +5046,7 @@ func (x *GetResourceGroupResponse) String() string { func (*GetResourceGroupResponse) ProtoMessage() {} func (x *GetResourceGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[43] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4483,7 +5059,7 @@ func (x *GetResourceGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetResourceGroupResponse.ProtoReflect.Descriptor instead. func (*GetResourceGroupResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{43} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{50} } func (x *GetResourceGroupResponse) GetGroup() *ResourceGroup { @@ -4510,7 +5086,7 @@ type CreateResourceGroupRequest struct { func (x *CreateResourceGroupRequest) Reset() { *x = CreateResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4522,7 +5098,7 @@ func (x *CreateResourceGroupRequest) String() string { func (*CreateResourceGroupRequest) ProtoMessage() {} func (x *CreateResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[44] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4535,7 +5111,7 @@ func (x *CreateResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateResourceGroupRequest.ProtoReflect.Descriptor instead. func (*CreateResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{44} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{51} } func (x *CreateResourceGroupRequest) GetRequestId() string { @@ -4619,7 +5195,7 @@ type UpdateResourceGroupRequest struct { func (x *UpdateResourceGroupRequest) Reset() { *x = UpdateResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4631,7 +5207,7 @@ func (x *UpdateResourceGroupRequest) String() string { func (*UpdateResourceGroupRequest) ProtoMessage() {} func (x *UpdateResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[45] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4644,7 +5220,7 @@ func (x *UpdateResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateResourceGroupRequest.ProtoReflect.Descriptor instead. func (*UpdateResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{45} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{52} } func (x *UpdateResourceGroupRequest) GetRequestId() string { @@ -4730,7 +5306,7 @@ type SetResourceGroupStatusRequest struct { func (x *SetResourceGroupStatusRequest) Reset() { *x = SetResourceGroupStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4742,7 +5318,7 @@ func (x *SetResourceGroupStatusRequest) String() string { func (*SetResourceGroupStatusRequest) ProtoMessage() {} func (x *SetResourceGroupStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[46] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4755,7 +5331,7 @@ func (x *SetResourceGroupStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceGroupStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceGroupStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{46} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{53} } func (x *SetResourceGroupStatusRequest) GetRequestId() string { @@ -4802,7 +5378,7 @@ type ResourceGroupResponse struct { func (x *ResourceGroupResponse) Reset() { *x = ResourceGroupResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4814,7 +5390,7 @@ func (x *ResourceGroupResponse) String() string { func (*ResourceGroupResponse) ProtoMessage() {} func (x *ResourceGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[47] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4827,7 +5403,7 @@ func (x *ResourceGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGroupResponse.ProtoReflect.Descriptor instead. func (*ResourceGroupResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{47} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{54} } func (x *ResourceGroupResponse) GetGroup() *ResourceGroup { @@ -4854,7 +5430,7 @@ type ListGiftConfigsRequest struct { func (x *ListGiftConfigsRequest) Reset() { *x = ListGiftConfigsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4866,7 +5442,7 @@ func (x *ListGiftConfigsRequest) String() string { func (*ListGiftConfigsRequest) ProtoMessage() {} func (x *ListGiftConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[48] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4879,7 +5455,7 @@ func (x *ListGiftConfigsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftConfigsRequest.ProtoReflect.Descriptor instead. func (*ListGiftConfigsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{48} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{55} } func (x *ListGiftConfigsRequest) GetRequestId() string { @@ -4955,7 +5531,7 @@ type ListGiftConfigsResponse struct { func (x *ListGiftConfigsResponse) Reset() { *x = ListGiftConfigsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4967,7 +5543,7 @@ func (x *ListGiftConfigsResponse) String() string { func (*ListGiftConfigsResponse) ProtoMessage() {} func (x *ListGiftConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[49] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4980,7 +5556,7 @@ func (x *ListGiftConfigsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftConfigsResponse.ProtoReflect.Descriptor instead. func (*ListGiftConfigsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{49} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{56} } func (x *ListGiftConfigsResponse) GetGifts() []*GiftConfig { @@ -5009,7 +5585,7 @@ type ListGiftTypeConfigsRequest struct { func (x *ListGiftTypeConfigsRequest) Reset() { *x = ListGiftTypeConfigsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5021,7 +5597,7 @@ func (x *ListGiftTypeConfigsRequest) String() string { func (*ListGiftTypeConfigsRequest) ProtoMessage() {} func (x *ListGiftTypeConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[50] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5034,7 +5610,7 @@ func (x *ListGiftTypeConfigsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftTypeConfigsRequest.ProtoReflect.Descriptor instead. func (*ListGiftTypeConfigsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{50} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{57} } func (x *ListGiftTypeConfigsRequest) GetRequestId() string { @@ -5074,7 +5650,7 @@ type ListGiftTypeConfigsResponse struct { func (x *ListGiftTypeConfigsResponse) Reset() { *x = ListGiftTypeConfigsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5086,7 +5662,7 @@ func (x *ListGiftTypeConfigsResponse) String() string { func (*ListGiftTypeConfigsResponse) ProtoMessage() {} func (x *ListGiftTypeConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[51] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5099,7 +5675,7 @@ func (x *ListGiftTypeConfigsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListGiftTypeConfigsResponse.ProtoReflect.Descriptor instead. func (*ListGiftTypeConfigsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{51} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{58} } func (x *ListGiftTypeConfigsResponse) GetGiftTypes() []*GiftTypeConfig { @@ -5125,7 +5701,7 @@ type UpsertGiftTypeConfigRequest struct { func (x *UpsertGiftTypeConfigRequest) Reset() { *x = UpsertGiftTypeConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5137,7 +5713,7 @@ func (x *UpsertGiftTypeConfigRequest) String() string { func (*UpsertGiftTypeConfigRequest) ProtoMessage() {} func (x *UpsertGiftTypeConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[52] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5150,7 +5726,7 @@ func (x *UpsertGiftTypeConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertGiftTypeConfigRequest.ProtoReflect.Descriptor instead. func (*UpsertGiftTypeConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{52} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{59} } func (x *UpsertGiftTypeConfigRequest) GetRequestId() string { @@ -5218,7 +5794,7 @@ type GiftTypeConfigResponse struct { func (x *GiftTypeConfigResponse) Reset() { *x = GiftTypeConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5230,7 +5806,7 @@ func (x *GiftTypeConfigResponse) String() string { func (*GiftTypeConfigResponse) ProtoMessage() {} func (x *GiftTypeConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[53] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5243,7 +5819,7 @@ func (x *GiftTypeConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftTypeConfigResponse.ProtoReflect.Descriptor instead. func (*GiftTypeConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{53} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{60} } func (x *GiftTypeConfigResponse) GetGiftType() *GiftTypeConfig { @@ -5281,7 +5857,7 @@ type CreateGiftConfigRequest struct { func (x *CreateGiftConfigRequest) Reset() { *x = CreateGiftConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5293,7 +5869,7 @@ func (x *CreateGiftConfigRequest) String() string { func (*CreateGiftConfigRequest) ProtoMessage() {} func (x *CreateGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[54] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5306,7 +5882,7 @@ func (x *CreateGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateGiftConfigRequest.ProtoReflect.Descriptor instead. func (*CreateGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{54} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{61} } func (x *CreateGiftConfigRequest) GetRequestId() string { @@ -5477,7 +6053,7 @@ type UpdateGiftConfigRequest struct { func (x *UpdateGiftConfigRequest) Reset() { *x = UpdateGiftConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5489,7 +6065,7 @@ func (x *UpdateGiftConfigRequest) String() string { func (*UpdateGiftConfigRequest) ProtoMessage() {} func (x *UpdateGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[55] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5502,7 +6078,7 @@ func (x *UpdateGiftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateGiftConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateGiftConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{55} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{62} } func (x *UpdateGiftConfigRequest) GetRequestId() string { @@ -5658,7 +6234,7 @@ type SetGiftConfigStatusRequest struct { func (x *SetGiftConfigStatusRequest) Reset() { *x = SetGiftConfigStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5670,7 +6246,7 @@ func (x *SetGiftConfigStatusRequest) String() string { func (*SetGiftConfigStatusRequest) ProtoMessage() {} func (x *SetGiftConfigStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[56] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5683,7 +6259,7 @@ func (x *SetGiftConfigStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetGiftConfigStatusRequest.ProtoReflect.Descriptor instead. func (*SetGiftConfigStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{56} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{63} } func (x *SetGiftConfigStatusRequest) GetRequestId() string { @@ -5730,7 +6306,7 @@ type GiftConfigResponse struct { func (x *GiftConfigResponse) Reset() { *x = GiftConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5742,7 +6318,7 @@ func (x *GiftConfigResponse) String() string { func (*GiftConfigResponse) ProtoMessage() {} func (x *GiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[57] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5755,7 +6331,7 @@ func (x *GiftConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftConfigResponse.ProtoReflect.Descriptor instead. func (*GiftConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{57} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{64} } func (x *GiftConfigResponse) GetGift() *GiftConfig { @@ -5782,7 +6358,7 @@ type GrantResourceRequest struct { func (x *GrantResourceRequest) Reset() { *x = GrantResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5794,7 +6370,7 @@ func (x *GrantResourceRequest) String() string { func (*GrantResourceRequest) ProtoMessage() {} func (x *GrantResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[58] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5807,7 +6383,7 @@ func (x *GrantResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantResourceRequest.ProtoReflect.Descriptor instead. func (*GrantResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{58} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{65} } func (x *GrantResourceRequest) GetCommandId() string { @@ -5888,7 +6464,7 @@ type GrantResourceGroupRequest struct { func (x *GrantResourceGroupRequest) Reset() { *x = GrantResourceGroupRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5900,7 +6476,7 @@ func (x *GrantResourceGroupRequest) String() string { func (*GrantResourceGroupRequest) ProtoMessage() {} func (x *GrantResourceGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[59] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5913,7 +6489,7 @@ func (x *GrantResourceGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantResourceGroupRequest.ProtoReflect.Descriptor instead. func (*GrantResourceGroupRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{59} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{66} } func (x *GrantResourceGroupRequest) GetCommandId() string { @@ -5974,7 +6550,7 @@ type ResourceGrantResponse struct { func (x *ResourceGrantResponse) Reset() { *x = ResourceGrantResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5986,7 +6562,7 @@ func (x *ResourceGrantResponse) String() string { func (*ResourceGrantResponse) ProtoMessage() {} func (x *ResourceGrantResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[60] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5999,7 +6575,7 @@ func (x *ResourceGrantResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceGrantResponse.ProtoReflect.Descriptor instead. func (*ResourceGrantResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{60} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{67} } func (x *ResourceGrantResponse) GetGrant() *ResourceGrant { @@ -6022,7 +6598,7 @@ type ListUserResourcesRequest struct { func (x *ListUserResourcesRequest) Reset() { *x = ListUserResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6034,7 +6610,7 @@ func (x *ListUserResourcesRequest) String() string { func (*ListUserResourcesRequest) ProtoMessage() {} func (x *ListUserResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[61] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6047,7 +6623,7 @@ func (x *ListUserResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserResourcesRequest.ProtoReflect.Descriptor instead. func (*ListUserResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{61} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{68} } func (x *ListUserResourcesRequest) GetRequestId() string { @@ -6094,7 +6670,7 @@ type ListUserResourcesResponse struct { func (x *ListUserResourcesResponse) Reset() { *x = ListUserResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6106,7 +6682,7 @@ func (x *ListUserResourcesResponse) String() string { func (*ListUserResourcesResponse) ProtoMessage() {} func (x *ListUserResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[62] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6119,7 +6695,7 @@ func (x *ListUserResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListUserResourcesResponse.ProtoReflect.Descriptor instead. func (*ListUserResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{62} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{69} } func (x *ListUserResourcesResponse) GetResources() []*UserResourceEntitlement { @@ -6142,7 +6718,7 @@ type EquipUserResourceRequest struct { func (x *EquipUserResourceRequest) Reset() { *x = EquipUserResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6154,7 +6730,7 @@ func (x *EquipUserResourceRequest) String() string { func (*EquipUserResourceRequest) ProtoMessage() {} func (x *EquipUserResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[63] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6167,7 +6743,7 @@ func (x *EquipUserResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EquipUserResourceRequest.ProtoReflect.Descriptor instead. func (*EquipUserResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{63} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{70} } func (x *EquipUserResourceRequest) GetRequestId() string { @@ -6214,7 +6790,7 @@ type EquipUserResourceResponse struct { func (x *EquipUserResourceResponse) Reset() { *x = EquipUserResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6226,7 +6802,7 @@ func (x *EquipUserResourceResponse) String() string { func (*EquipUserResourceResponse) ProtoMessage() {} func (x *EquipUserResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[64] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6239,7 +6815,7 @@ func (x *EquipUserResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EquipUserResourceResponse.ProtoReflect.Descriptor instead. func (*EquipUserResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{64} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{71} } func (x *EquipUserResourceResponse) GetResource() *UserResourceEntitlement { @@ -6261,7 +6837,7 @@ type UnequipUserResourceRequest struct { func (x *UnequipUserResourceRequest) Reset() { *x = UnequipUserResourceRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6273,7 +6849,7 @@ func (x *UnequipUserResourceRequest) String() string { func (*UnequipUserResourceRequest) ProtoMessage() {} func (x *UnequipUserResourceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[65] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6286,7 +6862,7 @@ func (x *UnequipUserResourceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnequipUserResourceRequest.ProtoReflect.Descriptor instead. func (*UnequipUserResourceRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{65} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{72} } func (x *UnequipUserResourceRequest) GetRequestId() string { @@ -6328,7 +6904,7 @@ type UnequipUserResourceResponse struct { func (x *UnequipUserResourceResponse) Reset() { *x = UnequipUserResourceResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6340,7 +6916,7 @@ func (x *UnequipUserResourceResponse) String() string { func (*UnequipUserResourceResponse) ProtoMessage() {} func (x *UnequipUserResourceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[66] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6353,7 +6929,7 @@ func (x *UnequipUserResourceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnequipUserResourceResponse.ProtoReflect.Descriptor instead. func (*UnequipUserResourceResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{66} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{73} } func (x *UnequipUserResourceResponse) GetResourceType() string { @@ -6389,7 +6965,7 @@ type BatchGetUserEquippedResourcesRequest struct { func (x *BatchGetUserEquippedResourcesRequest) Reset() { *x = BatchGetUserEquippedResourcesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6401,7 +6977,7 @@ func (x *BatchGetUserEquippedResourcesRequest) String() string { func (*BatchGetUserEquippedResourcesRequest) ProtoMessage() {} func (x *BatchGetUserEquippedResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[67] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6414,7 +6990,7 @@ func (x *BatchGetUserEquippedResourcesRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use BatchGetUserEquippedResourcesRequest.ProtoReflect.Descriptor instead. func (*BatchGetUserEquippedResourcesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{67} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{74} } func (x *BatchGetUserEquippedResourcesRequest) GetRequestId() string { @@ -6455,7 +7031,7 @@ type UserEquippedResources struct { func (x *UserEquippedResources) Reset() { *x = UserEquippedResources{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6467,7 +7043,7 @@ func (x *UserEquippedResources) String() string { func (*UserEquippedResources) ProtoMessage() {} func (x *UserEquippedResources) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[68] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6480,7 +7056,7 @@ func (x *UserEquippedResources) ProtoReflect() protoreflect.Message { // Deprecated: Use UserEquippedResources.ProtoReflect.Descriptor instead. func (*UserEquippedResources) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{68} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{75} } func (x *UserEquippedResources) GetUserId() int64 { @@ -6506,7 +7082,7 @@ type BatchGetUserEquippedResourcesResponse struct { func (x *BatchGetUserEquippedResourcesResponse) Reset() { *x = BatchGetUserEquippedResourcesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6518,7 +7094,7 @@ func (x *BatchGetUserEquippedResourcesResponse) String() string { func (*BatchGetUserEquippedResourcesResponse) ProtoMessage() {} func (x *BatchGetUserEquippedResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[69] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6531,7 +7107,7 @@ func (x *BatchGetUserEquippedResourcesResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use BatchGetUserEquippedResourcesResponse.ProtoReflect.Descriptor instead. func (*BatchGetUserEquippedResourcesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{69} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{76} } func (x *BatchGetUserEquippedResourcesResponse) GetUsers() []*UserEquippedResources { @@ -6555,7 +7131,7 @@ type ListResourceGrantsRequest struct { func (x *ListResourceGrantsRequest) Reset() { *x = ListResourceGrantsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6567,7 +7143,7 @@ func (x *ListResourceGrantsRequest) String() string { func (*ListResourceGrantsRequest) ProtoMessage() {} func (x *ListResourceGrantsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[70] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6580,7 +7156,7 @@ func (x *ListResourceGrantsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGrantsRequest.ProtoReflect.Descriptor instead. func (*ListResourceGrantsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{70} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{77} } func (x *ListResourceGrantsRequest) GetRequestId() string { @@ -6635,7 +7211,7 @@ type ListResourceGrantsResponse struct { func (x *ListResourceGrantsResponse) Reset() { *x = ListResourceGrantsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6647,7 +7223,7 @@ func (x *ListResourceGrantsResponse) String() string { func (*ListResourceGrantsResponse) ProtoMessage() {} func (x *ListResourceGrantsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[71] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6660,7 +7236,7 @@ func (x *ListResourceGrantsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceGrantsResponse.ProtoReflect.Descriptor instead. func (*ListResourceGrantsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{71} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{78} } func (x *ListResourceGrantsResponse) GetGrants() []*ResourceGrant { @@ -6692,7 +7268,7 @@ type ResourceShopItemInput struct { func (x *ResourceShopItemInput) Reset() { *x = ResourceShopItemInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6704,7 +7280,7 @@ func (x *ResourceShopItemInput) String() string { func (*ResourceShopItemInput) ProtoMessage() {} func (x *ResourceShopItemInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[72] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6717,7 +7293,7 @@ func (x *ResourceShopItemInput) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItemInput.ProtoReflect.Descriptor instead. func (*ResourceShopItemInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{72} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{79} } func (x *ResourceShopItemInput) GetShopItemId() int64 { @@ -6785,7 +7361,7 @@ type ListResourceShopItemsRequest struct { func (x *ListResourceShopItemsRequest) Reset() { *x = ListResourceShopItemsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6797,7 +7373,7 @@ func (x *ListResourceShopItemsRequest) String() string { func (*ListResourceShopItemsRequest) ProtoMessage() {} func (x *ListResourceShopItemsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[73] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6810,7 +7386,7 @@ func (x *ListResourceShopItemsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceShopItemsRequest.ProtoReflect.Descriptor instead. func (*ListResourceShopItemsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{73} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{80} } func (x *ListResourceShopItemsRequest) GetRequestId() string { @@ -6879,7 +7455,7 @@ type ListResourceShopItemsResponse struct { func (x *ListResourceShopItemsResponse) Reset() { *x = ListResourceShopItemsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6891,7 +7467,7 @@ func (x *ListResourceShopItemsResponse) String() string { func (*ListResourceShopItemsResponse) ProtoMessage() {} func (x *ListResourceShopItemsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[74] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6904,7 +7480,7 @@ func (x *ListResourceShopItemsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListResourceShopItemsResponse.ProtoReflect.Descriptor instead. func (*ListResourceShopItemsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{74} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{81} } func (x *ListResourceShopItemsResponse) GetItems() []*ResourceShopItem { @@ -6933,7 +7509,7 @@ type UpsertResourceShopItemsRequest struct { func (x *UpsertResourceShopItemsRequest) Reset() { *x = UpsertResourceShopItemsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6945,7 +7521,7 @@ func (x *UpsertResourceShopItemsRequest) String() string { func (*UpsertResourceShopItemsRequest) ProtoMessage() {} func (x *UpsertResourceShopItemsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[75] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6958,7 +7534,7 @@ func (x *UpsertResourceShopItemsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertResourceShopItemsRequest.ProtoReflect.Descriptor instead. func (*UpsertResourceShopItemsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{75} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{82} } func (x *UpsertResourceShopItemsRequest) GetRequestId() string { @@ -6998,7 +7574,7 @@ type UpsertResourceShopItemsResponse struct { func (x *UpsertResourceShopItemsResponse) Reset() { *x = UpsertResourceShopItemsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7010,7 +7586,7 @@ func (x *UpsertResourceShopItemsResponse) String() string { func (*UpsertResourceShopItemsResponse) ProtoMessage() {} func (x *UpsertResourceShopItemsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[76] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7023,7 +7599,7 @@ func (x *UpsertResourceShopItemsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertResourceShopItemsResponse.ProtoReflect.Descriptor instead. func (*UpsertResourceShopItemsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{76} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{83} } func (x *UpsertResourceShopItemsResponse) GetItems() []*ResourceShopItem { @@ -7046,7 +7622,7 @@ type SetResourceShopItemStatusRequest struct { func (x *SetResourceShopItemStatusRequest) Reset() { *x = SetResourceShopItemStatusRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7058,7 +7634,7 @@ func (x *SetResourceShopItemStatusRequest) String() string { func (*SetResourceShopItemStatusRequest) ProtoMessage() {} func (x *SetResourceShopItemStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[77] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7071,7 +7647,7 @@ func (x *SetResourceShopItemStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetResourceShopItemStatusRequest.ProtoReflect.Descriptor instead. func (*SetResourceShopItemStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{77} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{84} } func (x *SetResourceShopItemStatusRequest) GetRequestId() string { @@ -7118,7 +7694,7 @@ type ResourceShopItemResponse struct { func (x *ResourceShopItemResponse) Reset() { *x = ResourceShopItemResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7130,7 +7706,7 @@ func (x *ResourceShopItemResponse) String() string { func (*ResourceShopItemResponse) ProtoMessage() {} func (x *ResourceShopItemResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[78] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7143,7 +7719,7 @@ func (x *ResourceShopItemResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceShopItemResponse.ProtoReflect.Descriptor instead. func (*ResourceShopItemResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{78} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{85} } func (x *ResourceShopItemResponse) GetItem() *ResourceShopItem { @@ -7165,7 +7741,7 @@ type PurchaseResourceShopItemRequest struct { func (x *PurchaseResourceShopItemRequest) Reset() { *x = PurchaseResourceShopItemRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7177,7 +7753,7 @@ func (x *PurchaseResourceShopItemRequest) String() string { func (*PurchaseResourceShopItemRequest) ProtoMessage() {} func (x *PurchaseResourceShopItemRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[79] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7190,7 +7766,7 @@ func (x *PurchaseResourceShopItemRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseResourceShopItemRequest.ProtoReflect.Descriptor instead. func (*PurchaseResourceShopItemRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{79} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{86} } func (x *PurchaseResourceShopItemRequest) GetCommandId() string { @@ -7236,7 +7812,7 @@ type PurchaseResourceShopItemResponse struct { func (x *PurchaseResourceShopItemResponse) Reset() { *x = PurchaseResourceShopItemResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7248,7 +7824,7 @@ func (x *PurchaseResourceShopItemResponse) String() string { func (*PurchaseResourceShopItemResponse) ProtoMessage() {} func (x *PurchaseResourceShopItemResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[80] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7261,7 +7837,7 @@ func (x *PurchaseResourceShopItemResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseResourceShopItemResponse.ProtoReflect.Descriptor instead. func (*PurchaseResourceShopItemResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{80} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{87} } func (x *PurchaseResourceShopItemResponse) GetOrderId() string { @@ -7339,7 +7915,7 @@ type RechargeBill struct { func (x *RechargeBill) Reset() { *x = RechargeBill{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7351,7 +7927,7 @@ func (x *RechargeBill) String() string { func (*RechargeBill) ProtoMessage() {} func (x *RechargeBill) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[81] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7364,7 +7940,7 @@ func (x *RechargeBill) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeBill.ProtoReflect.Descriptor instead. func (*RechargeBill) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{81} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{88} } func (x *RechargeBill) GetAppCode() string { @@ -7513,7 +8089,7 @@ type ListRechargeBillsRequest struct { func (x *ListRechargeBillsRequest) Reset() { *x = ListRechargeBillsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7525,7 +8101,7 @@ func (x *ListRechargeBillsRequest) String() string { func (*ListRechargeBillsRequest) ProtoMessage() {} func (x *ListRechargeBillsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[82] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7538,7 +8114,7 @@ func (x *ListRechargeBillsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeBillsRequest.ProtoReflect.Descriptor instead. func (*ListRechargeBillsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{82} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{89} } func (x *ListRechargeBillsRequest) GetRequestId() string { @@ -7635,7 +8211,7 @@ type ListRechargeBillsResponse struct { func (x *ListRechargeBillsResponse) Reset() { *x = ListRechargeBillsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7647,7 +8223,7 @@ func (x *ListRechargeBillsResponse) String() string { func (*ListRechargeBillsResponse) ProtoMessage() {} func (x *ListRechargeBillsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[83] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7660,7 +8236,7 @@ func (x *ListRechargeBillsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeBillsResponse.ProtoReflect.Descriptor instead. func (*ListRechargeBillsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{83} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{90} } func (x *ListRechargeBillsResponse) GetBills() []*RechargeBill { @@ -7688,7 +8264,7 @@ type WalletFeatureFlags struct { func (x *WalletFeatureFlags) Reset() { *x = WalletFeatureFlags{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7700,7 +8276,7 @@ func (x *WalletFeatureFlags) String() string { func (*WalletFeatureFlags) ProtoMessage() {} func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[84] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7713,7 +8289,7 @@ func (x *WalletFeatureFlags) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletFeatureFlags.ProtoReflect.Descriptor instead. func (*WalletFeatureFlags) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{84} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{91} } func (x *WalletFeatureFlags) GetRechargeEnabled() bool { @@ -7741,7 +8317,7 @@ type GetWalletOverviewRequest struct { func (x *GetWalletOverviewRequest) Reset() { *x = GetWalletOverviewRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7753,7 +8329,7 @@ func (x *GetWalletOverviewRequest) String() string { func (*GetWalletOverviewRequest) ProtoMessage() {} func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[85] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7766,7 +8342,7 @@ func (x *GetWalletOverviewRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewRequest.ProtoReflect.Descriptor instead. func (*GetWalletOverviewRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{85} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{92} } func (x *GetWalletOverviewRequest) GetRequestId() string { @@ -7800,7 +8376,7 @@ type GetWalletOverviewResponse struct { func (x *GetWalletOverviewResponse) Reset() { *x = GetWalletOverviewResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7812,7 +8388,7 @@ func (x *GetWalletOverviewResponse) String() string { func (*GetWalletOverviewResponse) ProtoMessage() {} func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[86] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7825,7 +8401,7 @@ func (x *GetWalletOverviewResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletOverviewResponse.ProtoReflect.Descriptor instead. func (*GetWalletOverviewResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{86} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{93} } func (x *GetWalletOverviewResponse) GetBalances() []*AssetBalance { @@ -7853,7 +8429,7 @@ type WalletValueSummary struct { func (x *WalletValueSummary) Reset() { *x = WalletValueSummary{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7865,7 +8441,7 @@ func (x *WalletValueSummary) String() string { func (*WalletValueSummary) ProtoMessage() {} func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[87] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7878,7 +8454,7 @@ func (x *WalletValueSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletValueSummary.ProtoReflect.Descriptor instead. func (*WalletValueSummary) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{87} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{94} } func (x *WalletValueSummary) GetCoinAmount() int64 { @@ -7906,7 +8482,7 @@ type GetWalletValueSummaryRequest struct { func (x *GetWalletValueSummaryRequest) Reset() { *x = GetWalletValueSummaryRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7918,7 +8494,7 @@ func (x *GetWalletValueSummaryRequest) String() string { func (*GetWalletValueSummaryRequest) ProtoMessage() {} func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[88] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7931,7 +8507,7 @@ func (x *GetWalletValueSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryRequest.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{88} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} } func (x *GetWalletValueSummaryRequest) GetRequestId() string { @@ -7964,7 +8540,7 @@ type GetWalletValueSummaryResponse struct { func (x *GetWalletValueSummaryResponse) Reset() { *x = GetWalletValueSummaryResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7976,7 +8552,7 @@ func (x *GetWalletValueSummaryResponse) String() string { func (*GetWalletValueSummaryResponse) ProtoMessage() {} func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[89] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7989,7 +8565,7 @@ func (x *GetWalletValueSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetWalletValueSummaryResponse.ProtoReflect.Descriptor instead. func (*GetWalletValueSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{89} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} } func (x *GetWalletValueSummaryResponse) GetSummary() *WalletValueSummary { @@ -8026,7 +8602,7 @@ type GiftWallItem struct { func (x *GiftWallItem) Reset() { *x = GiftWallItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8038,7 +8614,7 @@ func (x *GiftWallItem) String() string { func (*GiftWallItem) ProtoMessage() {} func (x *GiftWallItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[90] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8051,7 +8627,7 @@ func (x *GiftWallItem) ProtoReflect() protoreflect.Message { // Deprecated: Use GiftWallItem.ProtoReflect.Descriptor instead. func (*GiftWallItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{90} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} } func (x *GiftWallItem) GetGiftId() string { @@ -8191,7 +8767,7 @@ type GetUserGiftWallRequest struct { func (x *GetUserGiftWallRequest) Reset() { *x = GetUserGiftWallRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8203,7 +8779,7 @@ func (x *GetUserGiftWallRequest) String() string { func (*GetUserGiftWallRequest) ProtoMessage() {} func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[91] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8216,7 +8792,7 @@ func (x *GetUserGiftWallRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallRequest.ProtoReflect.Descriptor instead. func (*GetUserGiftWallRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{91} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} } func (x *GetUserGiftWallRequest) GetRequestId() string { @@ -8256,7 +8832,7 @@ type GetUserGiftWallResponse struct { func (x *GetUserGiftWallResponse) Reset() { *x = GetUserGiftWallResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8268,7 +8844,7 @@ func (x *GetUserGiftWallResponse) String() string { func (*GetUserGiftWallResponse) ProtoMessage() {} func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[92] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8281,7 +8857,7 @@ func (x *GetUserGiftWallResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserGiftWallResponse.ProtoReflect.Descriptor instead. func (*GetUserGiftWallResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{92} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} } func (x *GetUserGiftWallResponse) GetItems() []*GiftWallItem { @@ -8370,7 +8946,7 @@ type RechargeProduct struct { func (x *RechargeProduct) Reset() { *x = RechargeProduct{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8382,7 +8958,7 @@ func (x *RechargeProduct) String() string { func (*RechargeProduct) ProtoMessage() {} func (x *RechargeProduct) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[93] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8395,7 +8971,7 @@ func (x *RechargeProduct) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProduct.ProtoReflect.Descriptor instead. func (*RechargeProduct) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{93} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} } func (x *RechargeProduct) GetProductId() int64 { @@ -8559,7 +9135,7 @@ type ListRechargeProductsRequest struct { func (x *ListRechargeProductsRequest) Reset() { *x = ListRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8571,7 +9147,7 @@ func (x *ListRechargeProductsRequest) String() string { func (*ListRechargeProductsRequest) ProtoMessage() {} func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[94] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8584,7 +9160,7 @@ func (x *ListRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{94} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} } func (x *ListRechargeProductsRequest) GetRequestId() string { @@ -8632,7 +9208,7 @@ type ListRechargeProductsResponse struct { func (x *ListRechargeProductsResponse) Reset() { *x = ListRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8644,7 +9220,7 @@ func (x *ListRechargeProductsResponse) String() string { func (*ListRechargeProductsResponse) ProtoMessage() {} func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[95] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8657,7 +9233,7 @@ func (x *ListRechargeProductsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{95} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} } func (x *ListRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -8693,7 +9269,7 @@ type ConfirmGooglePaymentRequest struct { func (x *ConfirmGooglePaymentRequest) Reset() { *x = ConfirmGooglePaymentRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8705,7 +9281,7 @@ func (x *ConfirmGooglePaymentRequest) String() string { func (*ConfirmGooglePaymentRequest) ProtoMessage() {} func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[96] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8718,7 +9294,7 @@ func (x *ConfirmGooglePaymentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentRequest.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{96} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} } func (x *ConfirmGooglePaymentRequest) GetRequestId() string { @@ -8815,7 +9391,7 @@ type ConfirmGooglePaymentResponse struct { func (x *ConfirmGooglePaymentResponse) Reset() { *x = ConfirmGooglePaymentResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8827,7 +9403,7 @@ func (x *ConfirmGooglePaymentResponse) String() string { func (*ConfirmGooglePaymentResponse) ProtoMessage() {} func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[97] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8840,7 +9416,7 @@ func (x *ConfirmGooglePaymentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmGooglePaymentResponse.ProtoReflect.Descriptor instead. func (*ConfirmGooglePaymentResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{97} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} } func (x *ConfirmGooglePaymentResponse) GetPaymentOrderId() string { @@ -8923,7 +9499,7 @@ type ListAdminRechargeProductsRequest struct { func (x *ListAdminRechargeProductsRequest) Reset() { *x = ListAdminRechargeProductsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8935,7 +9511,7 @@ func (x *ListAdminRechargeProductsRequest) String() string { func (*ListAdminRechargeProductsRequest) ProtoMessage() {} func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[98] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8948,7 +9524,7 @@ func (x *ListAdminRechargeProductsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminRechargeProductsRequest.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{98} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} } func (x *ListAdminRechargeProductsRequest) GetRequestId() string { @@ -9017,7 +9593,7 @@ type ListAdminRechargeProductsResponse struct { func (x *ListAdminRechargeProductsResponse) Reset() { *x = ListAdminRechargeProductsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9029,7 +9605,7 @@ func (x *ListAdminRechargeProductsResponse) String() string { func (*ListAdminRechargeProductsResponse) ProtoMessage() {} func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[99] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9042,7 +9618,7 @@ func (x *ListAdminRechargeProductsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListAdminRechargeProductsResponse.ProtoReflect.Descriptor instead. func (*ListAdminRechargeProductsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{99} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} } func (x *ListAdminRechargeProductsResponse) GetProducts() []*RechargeProduct { @@ -9078,7 +9654,7 @@ type CreateRechargeProductRequest struct { func (x *CreateRechargeProductRequest) Reset() { *x = CreateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9090,7 +9666,7 @@ func (x *CreateRechargeProductRequest) String() string { func (*CreateRechargeProductRequest) ProtoMessage() {} func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[100] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9103,7 +9679,7 @@ func (x *CreateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*CreateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{100} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} } func (x *CreateRechargeProductRequest) GetRequestId() string { @@ -9195,7 +9771,7 @@ type UpdateRechargeProductRequest struct { func (x *UpdateRechargeProductRequest) Reset() { *x = UpdateRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9207,7 +9783,7 @@ func (x *UpdateRechargeProductRequest) String() string { func (*UpdateRechargeProductRequest) ProtoMessage() {} func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[101] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9220,7 +9796,7 @@ func (x *UpdateRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRechargeProductRequest.ProtoReflect.Descriptor instead. func (*UpdateRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{101} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} } func (x *UpdateRechargeProductRequest) GetRequestId() string { @@ -9312,7 +9888,7 @@ type DeleteRechargeProductRequest struct { func (x *DeleteRechargeProductRequest) Reset() { *x = DeleteRechargeProductRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9324,7 +9900,7 @@ func (x *DeleteRechargeProductRequest) String() string { func (*DeleteRechargeProductRequest) ProtoMessage() {} func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[102] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9337,7 +9913,7 @@ func (x *DeleteRechargeProductRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductRequest.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{102} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} } func (x *DeleteRechargeProductRequest) GetRequestId() string { @@ -9377,7 +9953,7 @@ type RechargeProductResponse struct { func (x *RechargeProductResponse) Reset() { *x = RechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9389,7 +9965,7 @@ func (x *RechargeProductResponse) String() string { func (*RechargeProductResponse) ProtoMessage() {} func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[103] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9402,7 +9978,7 @@ func (x *RechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RechargeProductResponse.ProtoReflect.Descriptor instead. func (*RechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{103} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} } func (x *RechargeProductResponse) GetProduct() *RechargeProduct { @@ -9421,7 +9997,7 @@ type DeleteRechargeProductResponse struct { func (x *DeleteRechargeProductResponse) Reset() { *x = DeleteRechargeProductResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9433,7 +10009,7 @@ func (x *DeleteRechargeProductResponse) String() string { func (*DeleteRechargeProductResponse) ProtoMessage() {} func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[104] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9446,7 +10022,7 @@ func (x *DeleteRechargeProductResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteRechargeProductResponse.ProtoReflect.Descriptor instead. func (*DeleteRechargeProductResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{104} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} } func (x *DeleteRechargeProductResponse) GetDeleted() bool { @@ -9470,7 +10046,7 @@ type DiamondExchangeRule struct { func (x *DiamondExchangeRule) Reset() { *x = DiamondExchangeRule{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9482,7 +10058,7 @@ func (x *DiamondExchangeRule) String() string { func (*DiamondExchangeRule) ProtoMessage() {} func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[105] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9495,7 +10071,7 @@ func (x *DiamondExchangeRule) ProtoReflect() protoreflect.Message { // Deprecated: Use DiamondExchangeRule.ProtoReflect.Descriptor instead. func (*DiamondExchangeRule) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{105} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} } func (x *DiamondExchangeRule) GetExchangeType() string { @@ -9551,7 +10127,7 @@ type GetDiamondExchangeConfigRequest struct { func (x *GetDiamondExchangeConfigRequest) Reset() { *x = GetDiamondExchangeConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9563,7 +10139,7 @@ func (x *GetDiamondExchangeConfigRequest) String() string { func (*GetDiamondExchangeConfigRequest) ProtoMessage() {} func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[106] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9576,7 +10152,7 @@ func (x *GetDiamondExchangeConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigRequest.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{106} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} } func (x *GetDiamondExchangeConfigRequest) GetRequestId() string { @@ -9609,7 +10185,7 @@ type GetDiamondExchangeConfigResponse struct { func (x *GetDiamondExchangeConfigResponse) Reset() { *x = GetDiamondExchangeConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9621,7 +10197,7 @@ func (x *GetDiamondExchangeConfigResponse) String() string { func (*GetDiamondExchangeConfigResponse) ProtoMessage() {} func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[107] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9634,7 +10210,7 @@ func (x *GetDiamondExchangeConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDiamondExchangeConfigResponse.ProtoReflect.Descriptor instead. func (*GetDiamondExchangeConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{107} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} } func (x *GetDiamondExchangeConfigResponse) GetRules() []*DiamondExchangeRule { @@ -9664,7 +10240,7 @@ type WalletTransaction struct { func (x *WalletTransaction) Reset() { *x = WalletTransaction{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9676,7 +10252,7 @@ func (x *WalletTransaction) String() string { func (*WalletTransaction) ProtoMessage() {} func (x *WalletTransaction) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[108] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9689,7 +10265,7 @@ func (x *WalletTransaction) ProtoReflect() protoreflect.Message { // Deprecated: Use WalletTransaction.ProtoReflect.Descriptor instead. func (*WalletTransaction) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{108} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} } func (x *WalletTransaction) GetEntryId() int64 { @@ -9783,7 +10359,7 @@ type ListWalletTransactionsRequest struct { func (x *ListWalletTransactionsRequest) Reset() { *x = ListWalletTransactionsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9795,7 +10371,7 @@ func (x *ListWalletTransactionsRequest) String() string { func (*ListWalletTransactionsRequest) ProtoMessage() {} func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[109] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9808,7 +10384,7 @@ func (x *ListWalletTransactionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsRequest.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{109} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} } func (x *ListWalletTransactionsRequest) GetRequestId() string { @@ -9863,7 +10439,7 @@ type ListWalletTransactionsResponse struct { func (x *ListWalletTransactionsResponse) Reset() { *x = ListWalletTransactionsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9875,7 +10451,7 @@ func (x *ListWalletTransactionsResponse) String() string { func (*ListWalletTransactionsResponse) ProtoMessage() {} func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[110] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9888,7 +10464,7 @@ func (x *ListWalletTransactionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListWalletTransactionsResponse.ProtoReflect.Descriptor instead. func (*ListWalletTransactionsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{110} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} } func (x *ListWalletTransactionsResponse) GetTransactions() []*WalletTransaction { @@ -9922,7 +10498,7 @@ type VipRewardItem struct { func (x *VipRewardItem) Reset() { *x = VipRewardItem{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9934,7 +10510,7 @@ func (x *VipRewardItem) String() string { func (*VipRewardItem) ProtoMessage() {} func (x *VipRewardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[111] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9947,7 +10523,7 @@ func (x *VipRewardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use VipRewardItem.ProtoReflect.Descriptor instead. func (*VipRewardItem) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{111} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} } func (x *VipRewardItem) GetResourceId() int64 { @@ -10036,7 +10612,7 @@ type VipLevel struct { func (x *VipLevel) Reset() { *x = VipLevel{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10048,7 +10624,7 @@ func (x *VipLevel) String() string { func (*VipLevel) ProtoMessage() {} func (x *VipLevel) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[112] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10061,7 +10637,7 @@ func (x *VipLevel) ProtoReflect() protoreflect.Message { // Deprecated: Use VipLevel.ProtoReflect.Descriptor instead. func (*VipLevel) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{112} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} } func (x *VipLevel) GetLevel() int32 { @@ -10184,7 +10760,7 @@ type UserVip struct { func (x *UserVip) Reset() { *x = UserVip{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10196,7 +10772,7 @@ func (x *UserVip) String() string { func (*UserVip) ProtoMessage() {} func (x *UserVip) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[113] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10209,7 +10785,7 @@ func (x *UserVip) ProtoReflect() protoreflect.Message { // Deprecated: Use UserVip.ProtoReflect.Descriptor instead. func (*UserVip) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{113} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} } func (x *UserVip) GetUserId() int64 { @@ -10272,7 +10848,7 @@ type ListVipPackagesRequest struct { func (x *ListVipPackagesRequest) Reset() { *x = ListVipPackagesRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10284,7 +10860,7 @@ func (x *ListVipPackagesRequest) String() string { func (*ListVipPackagesRequest) ProtoMessage() {} func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[114] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10297,7 +10873,7 @@ func (x *ListVipPackagesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesRequest.ProtoReflect.Descriptor instead. func (*ListVipPackagesRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{114} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} } func (x *ListVipPackagesRequest) GetRequestId() string { @@ -10331,7 +10907,7 @@ type ListVipPackagesResponse struct { func (x *ListVipPackagesResponse) Reset() { *x = ListVipPackagesResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10343,7 +10919,7 @@ func (x *ListVipPackagesResponse) String() string { func (*ListVipPackagesResponse) ProtoMessage() {} func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[115] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10356,7 +10932,7 @@ func (x *ListVipPackagesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListVipPackagesResponse.ProtoReflect.Descriptor instead. func (*ListVipPackagesResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{115} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} } func (x *ListVipPackagesResponse) GetCurrentVip() *UserVip { @@ -10384,7 +10960,7 @@ type GetMyVipRequest struct { func (x *GetMyVipRequest) Reset() { *x = GetMyVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10396,7 +10972,7 @@ func (x *GetMyVipRequest) String() string { func (*GetMyVipRequest) ProtoMessage() {} func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[116] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10409,7 +10985,7 @@ func (x *GetMyVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipRequest.ProtoReflect.Descriptor instead. func (*GetMyVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{116} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} } func (x *GetMyVipRequest) GetRequestId() string { @@ -10442,7 +11018,7 @@ type GetMyVipResponse struct { func (x *GetMyVipResponse) Reset() { *x = GetMyVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10454,7 +11030,7 @@ func (x *GetMyVipResponse) String() string { func (*GetMyVipResponse) ProtoMessage() {} func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[117] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10467,7 +11043,7 @@ func (x *GetMyVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyVipResponse.ProtoReflect.Descriptor instead. func (*GetMyVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{117} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} } func (x *GetMyVipResponse) GetVip() *UserVip { @@ -10489,7 +11065,7 @@ type PurchaseVipRequest struct { func (x *PurchaseVipRequest) Reset() { *x = PurchaseVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10501,7 +11077,7 @@ func (x *PurchaseVipRequest) String() string { func (*PurchaseVipRequest) ProtoMessage() {} func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[118] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10514,7 +11090,7 @@ func (x *PurchaseVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipRequest.ProtoReflect.Descriptor instead. func (*PurchaseVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{118} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} } func (x *PurchaseVipRequest) GetCommandId() string { @@ -10559,7 +11135,7 @@ type PurchaseVipResponse struct { func (x *PurchaseVipResponse) Reset() { *x = PurchaseVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10571,7 +11147,7 @@ func (x *PurchaseVipResponse) String() string { func (*PurchaseVipResponse) ProtoMessage() {} func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[119] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10584,7 +11160,7 @@ func (x *PurchaseVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PurchaseVipResponse.ProtoReflect.Descriptor instead. func (*PurchaseVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{119} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} } func (x *PurchaseVipResponse) GetOrderId() string { @@ -10644,7 +11220,7 @@ type GrantVipRequest struct { func (x *GrantVipRequest) Reset() { *x = GrantVipRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10656,7 +11232,7 @@ func (x *GrantVipRequest) String() string { func (*GrantVipRequest) ProtoMessage() {} func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[120] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10669,7 +11245,7 @@ func (x *GrantVipRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipRequest.ProtoReflect.Descriptor instead. func (*GrantVipRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{120} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} } func (x *GrantVipRequest) GetCommandId() string { @@ -10733,7 +11309,7 @@ type GrantVipResponse struct { func (x *GrantVipResponse) Reset() { *x = GrantVipResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10745,7 +11321,7 @@ func (x *GrantVipResponse) String() string { func (*GrantVipResponse) ProtoMessage() {} func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[121] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10758,7 +11334,7 @@ func (x *GrantVipResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GrantVipResponse.ProtoReflect.Descriptor instead. func (*GrantVipResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{121} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} } func (x *GrantVipResponse) GetTransactionId() string { @@ -10805,7 +11381,7 @@ type AdminVipLevelInput struct { func (x *AdminVipLevelInput) Reset() { *x = AdminVipLevelInput{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10817,7 +11393,7 @@ func (x *AdminVipLevelInput) String() string { func (*AdminVipLevelInput) ProtoMessage() {} func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[122] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10830,7 +11406,7 @@ func (x *AdminVipLevelInput) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminVipLevelInput.ProtoReflect.Descriptor instead. func (*AdminVipLevelInput) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{122} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} } func (x *AdminVipLevelInput) GetLevel() int32 { @@ -10899,7 +11475,7 @@ type ListAdminVipLevelsRequest struct { func (x *ListAdminVipLevelsRequest) Reset() { *x = ListAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10911,7 +11487,7 @@ func (x *ListAdminVipLevelsRequest) String() string { func (*ListAdminVipLevelsRequest) ProtoMessage() {} func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[123] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10924,7 +11500,7 @@ func (x *ListAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{123} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} } func (x *ListAdminVipLevelsRequest) GetRequestId() string { @@ -10951,7 +11527,7 @@ type ListAdminVipLevelsResponse struct { func (x *ListAdminVipLevelsResponse) Reset() { *x = ListAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10963,7 +11539,7 @@ func (x *ListAdminVipLevelsResponse) String() string { func (*ListAdminVipLevelsResponse) ProtoMessage() {} func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[124] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10976,7 +11552,7 @@ func (x *ListAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*ListAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{124} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} } func (x *ListAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -11005,7 +11581,7 @@ type UpdateAdminVipLevelsRequest struct { func (x *UpdateAdminVipLevelsRequest) Reset() { *x = UpdateAdminVipLevelsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11017,7 +11593,7 @@ func (x *UpdateAdminVipLevelsRequest) String() string { func (*UpdateAdminVipLevelsRequest) ProtoMessage() {} func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[125] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11030,7 +11606,7 @@ func (x *UpdateAdminVipLevelsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsRequest.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{125} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} } func (x *UpdateAdminVipLevelsRequest) GetRequestId() string { @@ -11071,7 +11647,7 @@ type UpdateAdminVipLevelsResponse struct { func (x *UpdateAdminVipLevelsResponse) Reset() { *x = UpdateAdminVipLevelsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11083,7 +11659,7 @@ func (x *UpdateAdminVipLevelsResponse) String() string { func (*UpdateAdminVipLevelsResponse) ProtoMessage() {} func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[126] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11096,7 +11672,7 @@ func (x *UpdateAdminVipLevelsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateAdminVipLevelsResponse.ProtoReflect.Descriptor instead. func (*UpdateAdminVipLevelsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{126} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} } func (x *UpdateAdminVipLevelsResponse) GetLevels() []*VipLevel { @@ -11130,7 +11706,7 @@ type CreditTaskRewardRequest struct { func (x *CreditTaskRewardRequest) Reset() { *x = CreditTaskRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11142,7 +11718,7 @@ func (x *CreditTaskRewardRequest) String() string { func (*CreditTaskRewardRequest) ProtoMessage() {} func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[127] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11155,7 +11731,7 @@ func (x *CreditTaskRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardRequest.ProtoReflect.Descriptor instead. func (*CreditTaskRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{127} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} } func (x *CreditTaskRewardRequest) GetCommandId() string { @@ -11227,7 +11803,7 @@ type CreditTaskRewardResponse struct { func (x *CreditTaskRewardResponse) Reset() { *x = CreditTaskRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11239,7 +11815,7 @@ func (x *CreditTaskRewardResponse) String() string { func (*CreditTaskRewardResponse) ProtoMessage() {} func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[128] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11252,7 +11828,7 @@ func (x *CreditTaskRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditTaskRewardResponse.ProtoReflect.Descriptor instead. func (*CreditTaskRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{128} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} } func (x *CreditTaskRewardResponse) GetTransactionId() string { @@ -11302,7 +11878,7 @@ type CreditLuckyGiftRewardRequest struct { func (x *CreditLuckyGiftRewardRequest) Reset() { *x = CreditLuckyGiftRewardRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11314,7 +11890,7 @@ func (x *CreditLuckyGiftRewardRequest) String() string { func (*CreditLuckyGiftRewardRequest) ProtoMessage() {} func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[129] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11327,7 +11903,7 @@ func (x *CreditLuckyGiftRewardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardRequest.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{129} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} } func (x *CreditLuckyGiftRewardRequest) GetCommandId() string { @@ -11413,7 +11989,7 @@ type CreditLuckyGiftRewardResponse struct { func (x *CreditLuckyGiftRewardResponse) Reset() { *x = CreditLuckyGiftRewardResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11425,7 +12001,7 @@ func (x *CreditLuckyGiftRewardResponse) String() string { func (*CreditLuckyGiftRewardResponse) ProtoMessage() {} func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[130] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11438,7 +12014,7 @@ func (x *CreditLuckyGiftRewardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreditLuckyGiftRewardResponse.ProtoReflect.Descriptor instead. func (*CreditLuckyGiftRewardResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{130} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} } func (x *CreditLuckyGiftRewardResponse) GetTransactionId() string { @@ -11490,7 +12066,7 @@ type ApplyGameCoinChangeRequest struct { func (x *ApplyGameCoinChangeRequest) Reset() { *x = ApplyGameCoinChangeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11502,7 +12078,7 @@ func (x *ApplyGameCoinChangeRequest) String() string { func (*ApplyGameCoinChangeRequest) ProtoMessage() {} func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[131] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11515,7 +12091,7 @@ func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeRequest.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{131} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} } func (x *ApplyGameCoinChangeRequest) GetRequestId() string { @@ -11614,7 +12190,7 @@ type ApplyGameCoinChangeResponse struct { func (x *ApplyGameCoinChangeResponse) Reset() { *x = ApplyGameCoinChangeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11626,7 +12202,7 @@ func (x *ApplyGameCoinChangeResponse) String() string { func (*ApplyGameCoinChangeResponse) ProtoMessage() {} func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[132] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11639,7 +12215,7 @@ func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeResponse.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{132} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} } func (x *ApplyGameCoinChangeResponse) GetWalletTransactionId() string { @@ -11682,7 +12258,7 @@ type RedPacketConfig struct { func (x *RedPacketConfig) Reset() { *x = RedPacketConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11694,7 +12270,7 @@ func (x *RedPacketConfig) String() string { func (*RedPacketConfig) ProtoMessage() {} func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[133] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11707,7 +12283,7 @@ func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketConfig.ProtoReflect.Descriptor instead. func (*RedPacketConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{133} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} } func (x *RedPacketConfig) GetAppCode() string { @@ -11806,7 +12382,7 @@ type RedPacketClaim struct { func (x *RedPacketClaim) Reset() { *x = RedPacketClaim{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11818,7 +12394,7 @@ func (x *RedPacketClaim) String() string { func (*RedPacketClaim) ProtoMessage() {} func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[134] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11831,7 +12407,7 @@ func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketClaim.ProtoReflect.Descriptor instead. func (*RedPacketClaim) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{134} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} } func (x *RedPacketClaim) GetAppCode() string { @@ -11941,7 +12517,7 @@ type RedPacket struct { func (x *RedPacket) Reset() { *x = RedPacket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11953,7 +12529,7 @@ func (x *RedPacket) String() string { func (*RedPacket) ProtoMessage() {} func (x *RedPacket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[135] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11966,7 +12542,7 @@ func (x *RedPacket) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacket.ProtoReflect.Descriptor instead. func (*RedPacket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{135} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} } func (x *RedPacket) GetAppCode() string { @@ -12133,7 +12709,7 @@ type GetRedPacketConfigRequest struct { func (x *GetRedPacketConfigRequest) Reset() { *x = GetRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12145,7 +12721,7 @@ func (x *GetRedPacketConfigRequest) String() string { func (*GetRedPacketConfigRequest) ProtoMessage() {} func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[136] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12158,7 +12734,7 @@ func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{136} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} } func (x *GetRedPacketConfigRequest) GetRequestId() string { @@ -12185,7 +12761,7 @@ type GetRedPacketConfigResponse struct { func (x *GetRedPacketConfigResponse) Reset() { *x = GetRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12197,7 +12773,7 @@ func (x *GetRedPacketConfigResponse) String() string { func (*GetRedPacketConfigResponse) ProtoMessage() {} func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[137] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12210,7 +12786,7 @@ func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{137} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} } func (x *GetRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -12245,7 +12821,7 @@ type UpdateRedPacketConfigRequest struct { func (x *UpdateRedPacketConfigRequest) Reset() { *x = UpdateRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12257,7 +12833,7 @@ func (x *UpdateRedPacketConfigRequest) String() string { func (*UpdateRedPacketConfigRequest) ProtoMessage() {} func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12270,7 +12846,7 @@ func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} } func (x *UpdateRedPacketConfigRequest) GetRequestId() string { @@ -12353,7 +12929,7 @@ type UpdateRedPacketConfigResponse struct { func (x *UpdateRedPacketConfigResponse) Reset() { *x = UpdateRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12365,7 +12941,7 @@ func (x *UpdateRedPacketConfigResponse) String() string { func (*UpdateRedPacketConfigResponse) ProtoMessage() {} func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12378,7 +12954,7 @@ func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} } func (x *UpdateRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -12412,7 +12988,7 @@ type CreateRedPacketRequest struct { func (x *CreateRedPacketRequest) Reset() { *x = CreateRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12424,7 +13000,7 @@ func (x *CreateRedPacketRequest) String() string { func (*CreateRedPacketRequest) ProtoMessage() {} func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12437,7 +13013,7 @@ func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketRequest.ProtoReflect.Descriptor instead. func (*CreateRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} } func (x *CreateRedPacketRequest) GetRequestId() string { @@ -12514,7 +13090,7 @@ type CreateRedPacketResponse struct { func (x *CreateRedPacketResponse) Reset() { *x = CreateRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12526,7 +13102,7 @@ func (x *CreateRedPacketResponse) String() string { func (*CreateRedPacketResponse) ProtoMessage() {} func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12539,7 +13115,7 @@ func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketResponse.ProtoReflect.Descriptor instead. func (*CreateRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} } func (x *CreateRedPacketResponse) GetPacket() *RedPacket { @@ -12576,7 +13152,7 @@ type ClaimRedPacketRequest struct { func (x *ClaimRedPacketRequest) Reset() { *x = ClaimRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12588,7 +13164,7 @@ func (x *ClaimRedPacketRequest) String() string { func (*ClaimRedPacketRequest) ProtoMessage() {} func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12601,7 +13177,7 @@ func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketRequest.ProtoReflect.Descriptor instead. func (*ClaimRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} } func (x *ClaimRedPacketRequest) GetRequestId() string { @@ -12651,7 +13227,7 @@ type ClaimRedPacketResponse struct { func (x *ClaimRedPacketResponse) Reset() { *x = ClaimRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12663,7 +13239,7 @@ func (x *ClaimRedPacketResponse) String() string { func (*ClaimRedPacketResponse) ProtoMessage() {} func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12676,7 +13252,7 @@ func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketResponse.ProtoReflect.Descriptor instead. func (*ClaimRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} } func (x *ClaimRedPacketResponse) GetClaim() *RedPacketClaim { @@ -12727,7 +13303,7 @@ type ListRedPacketsRequest struct { func (x *ListRedPacketsRequest) Reset() { *x = ListRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12739,7 +13315,7 @@ func (x *ListRedPacketsRequest) String() string { func (*ListRedPacketsRequest) ProtoMessage() {} func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12752,7 +13328,7 @@ func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ListRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} } func (x *ListRedPacketsRequest) GetRequestId() string { @@ -12850,7 +13426,7 @@ type ListRedPacketsResponse struct { func (x *ListRedPacketsResponse) Reset() { *x = ListRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12862,7 +13438,7 @@ func (x *ListRedPacketsResponse) String() string { func (*ListRedPacketsResponse) ProtoMessage() {} func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12875,7 +13451,7 @@ func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ListRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} } func (x *ListRedPacketsResponse) GetPackets() []*RedPacket { @@ -12912,7 +13488,7 @@ type GetRedPacketRequest struct { func (x *GetRedPacketRequest) Reset() { *x = GetRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12924,7 +13500,7 @@ func (x *GetRedPacketRequest) String() string { func (*GetRedPacketRequest) ProtoMessage() {} func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12937,7 +13513,7 @@ func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} } func (x *GetRedPacketRequest) GetRequestId() string { @@ -12985,7 +13561,7 @@ type GetRedPacketResponse struct { func (x *GetRedPacketResponse) Reset() { *x = GetRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12997,7 +13573,7 @@ func (x *GetRedPacketResponse) String() string { func (*GetRedPacketResponse) ProtoMessage() {} func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13010,7 +13586,7 @@ func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{154} } func (x *GetRedPacketResponse) GetPacket() *RedPacket { @@ -13038,7 +13614,7 @@ type ExpireRedPacketsRequest struct { func (x *ExpireRedPacketsRequest) Reset() { *x = ExpireRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13050,7 +13626,7 @@ func (x *ExpireRedPacketsRequest) String() string { func (*ExpireRedPacketsRequest) ProtoMessage() {} func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13063,7 +13639,7 @@ func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{155} } func (x *ExpireRedPacketsRequest) GetRequestId() string { @@ -13098,7 +13674,7 @@ type ExpireRedPacketsResponse struct { func (x *ExpireRedPacketsResponse) Reset() { *x = ExpireRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13110,7 +13686,7 @@ func (x *ExpireRedPacketsResponse) String() string { func (*ExpireRedPacketsResponse) ProtoMessage() {} func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13123,7 +13699,7 @@ func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{156} } func (x *ExpireRedPacketsResponse) GetExpiredCount() int32 { @@ -13159,7 +13735,7 @@ type RetryRedPacketRefundRequest struct { func (x *RetryRedPacketRefundRequest) Reset() { *x = RetryRedPacketRefundRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13171,7 +13747,7 @@ func (x *RetryRedPacketRefundRequest) String() string { func (*RetryRedPacketRefundRequest) ProtoMessage() {} func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13184,7 +13760,7 @@ func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundRequest.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{157} } func (x *RetryRedPacketRefundRequest) GetRequestId() string { @@ -13226,7 +13802,7 @@ type RetryRedPacketRefundResponse struct { func (x *RetryRedPacketRefundResponse) Reset() { *x = RetryRedPacketRefundResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13238,7 +13814,7 @@ func (x *RetryRedPacketRefundResponse) String() string { func (*RetryRedPacketRefundResponse) ProtoMessage() {} func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13251,7 +13827,7 @@ func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundResponse.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{158} } func (x *RetryRedPacketRefundResponse) GetPacket() *RedPacket { @@ -13290,7 +13866,7 @@ type CronBatchRequest struct { func (x *CronBatchRequest) Reset() { *x = CronBatchRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13302,7 +13878,7 @@ func (x *CronBatchRequest) String() string { func (*CronBatchRequest) ProtoMessage() {} func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13315,7 +13891,7 @@ func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchRequest.ProtoReflect.Descriptor instead. func (*CronBatchRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{159} } func (x *CronBatchRequest) GetRequestId() string { @@ -13374,7 +13950,7 @@ type CronBatchResponse struct { func (x *CronBatchResponse) Reset() { *x = CronBatchResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13386,7 +13962,7 @@ func (x *CronBatchResponse) String() string { func (*CronBatchResponse) ProtoMessage() {} func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13399,7 +13975,7 @@ func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchResponse.ProtoReflect.Descriptor instead. func (*CronBatchResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{160} } func (x *CronBatchResponse) GetClaimedCount() int32 { @@ -13636,7 +14212,63 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x17recharge_policy_version\x18\b \x01(\tR\x15rechargePolicyVersion\x12=\n" + "\x1brecharge_policy_coin_amount\x18\t \x01(\x03R\x18rechargePolicyCoinAmount\x12F\n" + " recharge_policy_usd_minor_amount\x18\n" + - " \x01(\x03R\x1crechargePolicyUsdMinorAmount\"\xe7\x06\n" + + " \x01(\x03R\x1crechargePolicyUsdMinorAmount\"\x84\x02\n" + + " CoinSellerSalaryExchangeRateTier\x12\x1b\n" + + "\tregion_id\x18\x01 \x01(\x03R\bregionId\x12\"\n" + + "\rmin_usd_minor\x18\x02 \x01(\x03R\vminUsdMinor\x12\"\n" + + "\rmax_usd_minor\x18\x03 \x01(\x03R\vmaxUsdMinor\x12 \n" + + "\fcoin_per_usd\x18\x04 \x01(\x03R\n" + + "coinPerUsd\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\x06 \x01(\x05R\tsortOrder\x12\"\n" + + "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\"\xb0\x01\n" + + ",ListCoinSellerSalaryExchangeRateTiersRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12)\n" + + "\x10include_disabled\x18\x04 \x01(\bR\x0fincludeDisabled\"x\n" + + "-ListCoinSellerSalaryExchangeRateTiersResponse\x12G\n" + + "\x05tiers\x18\x01 \x03(\v21.hyapp.wallet.v1.CoinSellerSalaryExchangeRateTierR\x05tiers\"\xde\x01\n" + + "\x1bExchangeSalaryToCoinRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12*\n" + + "\x11salary_asset_type\x18\x03 \x01(\tR\x0fsalaryAssetType\x12(\n" + + "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\x12\x19\n" + + "\bapp_code\x18\x06 \x01(\tR\aappCode\"\x92\x02\n" + + "\x1cExchangeSalaryToCoinResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x120\n" + + "\x14salary_balance_after\x18\x02 \x01(\x03R\x12salaryBalanceAfter\x12,\n" + + "\x12coin_balance_after\x18\x03 \x01(\x03R\x10coinBalanceAfter\x12(\n" + + "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x1f\n" + + "\vcoin_amount\x18\x05 \x01(\x03R\n" + + "coinAmount\x12 \n" + + "\fcoin_per_usd\x18\x06 \x01(\x03R\n" + + "coinPerUsd\"\xb4\x02\n" + + "!TransferSalaryToCoinSellerRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + + "\x0esource_user_id\x18\x02 \x01(\x03R\fsourceUserId\x12$\n" + + "\x0eseller_user_id\x18\x03 \x01(\x03R\fsellerUserId\x12*\n" + + "\x11salary_asset_type\x18\x04 \x01(\tR\x0fsalaryAssetType\x12(\n" + + "\x10salary_usd_minor\x18\x05 \x01(\x03R\x0esalaryUsdMinor\x12\x1b\n" + + "\tregion_id\x18\x06 \x01(\x03R\bregionId\x12\x16\n" + + "\x06reason\x18\a \x01(\tR\x06reason\x12\x19\n" + + "\bapp_code\x18\b \x01(\tR\aappCode\"\x83\x03\n" + + "\"TransferSalaryToCoinSellerResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12=\n" + + "\x1bsource_salary_balance_after\x18\x02 \x01(\x03R\x18sourceSalaryBalanceAfter\x120\n" + + "\x14seller_balance_after\x18\x03 \x01(\x03R\x12sellerBalanceAfter\x12(\n" + + "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x1f\n" + + "\vcoin_amount\x18\x05 \x01(\x03R\n" + + "coinAmount\x12 \n" + + "\fcoin_per_usd\x18\x06 \x01(\x03R\n" + + "coinPerUsd\x12+\n" + + "\x12rate_min_usd_minor\x18\a \x01(\x03R\x0frateMinUsdMinor\x12+\n" + + "\x12rate_max_usd_minor\x18\b \x01(\x03R\x0frateMaxUsdMinor\"\xe7\x06\n" + "\bResource\x12\x19\n" + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1f\n" + "\vresource_id\x18\x02 \x01(\x03R\n" + @@ -14821,7 +15453,7 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x11WalletCronService\x12n\n" + "%ProcessHostSalaryDailySettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12r\n" + ")ProcessHostSalaryHalfMonthSettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12g\n" + - "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\xe26\n" + + "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\x88:\n" + "\rWalletService\x12R\n" + "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12a\n" + "\x0eBatchDebitGift\x12&.hyapp.wallet.v1.BatchDebitGiftRequest\x1a'.hyapp.wallet.v1.BatchDebitGiftResponse\x12X\n" + @@ -14830,7 +15462,10 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x15GetHostSalaryProgress\x12-.hyapp.wallet.v1.GetHostSalaryProgressRequest\x1a..hyapp.wallet.v1.GetHostSalaryProgressResponse\x12g\n" + "\x10AdminCreditAsset\x12(.hyapp.wallet.v1.AdminCreditAssetRequest\x1a).hyapp.wallet.v1.AdminCreditAssetResponse\x12\x85\x01\n" + "\x1aAdminCreditCoinSellerStock\x122.hyapp.wallet.v1.AdminCreditCoinSellerStockRequest\x1a3.hyapp.wallet.v1.AdminCreditCoinSellerStockResponse\x12y\n" + - "\x16TransferCoinFromSeller\x12..hyapp.wallet.v1.TransferCoinFromSellerRequest\x1a/.hyapp.wallet.v1.TransferCoinFromSellerResponse\x12^\n" + + "\x16TransferCoinFromSeller\x12..hyapp.wallet.v1.TransferCoinFromSellerRequest\x1a/.hyapp.wallet.v1.TransferCoinFromSellerResponse\x12\xa6\x01\n" + + "%ListCoinSellerSalaryExchangeRateTiers\x12=.hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest\x1a>.hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse\x12s\n" + + "\x14ExchangeSalaryToCoin\x12,.hyapp.wallet.v1.ExchangeSalaryToCoinRequest\x1a-.hyapp.wallet.v1.ExchangeSalaryToCoinResponse\x12\x85\x01\n" + + "\x1aTransferSalaryToCoinSeller\x122.hyapp.wallet.v1.TransferSalaryToCoinSellerRequest\x1a3.hyapp.wallet.v1.TransferSalaryToCoinSellerResponse\x12^\n" + "\rListResources\x12%.hyapp.wallet.v1.ListResourcesRequest\x1a&.hyapp.wallet.v1.ListResourcesResponse\x12X\n" + "\vGetResource\x12#.hyapp.wallet.v1.GetResourceRequest\x1a$.hyapp.wallet.v1.GetResourceResponse\x12[\n" + "\x0eCreateResource\x12&.hyapp.wallet.v1.CreateResourceRequest\x1a!.hyapp.wallet.v1.ResourceResponse\x12[\n" + @@ -14900,162 +15535,169 @@ func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 154) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 161) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ - (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest - (*DebitGiftResponse)(nil), // 1: hyapp.wallet.v1.DebitGiftResponse - (*DebitGiftTarget)(nil), // 2: hyapp.wallet.v1.DebitGiftTarget - (*BatchDebitGiftRequest)(nil), // 3: hyapp.wallet.v1.BatchDebitGiftRequest - (*BatchDebitGiftReceipt)(nil), // 4: hyapp.wallet.v1.BatchDebitGiftReceipt - (*BatchDebitGiftResponse)(nil), // 5: hyapp.wallet.v1.BatchDebitGiftResponse - (*AssetBalance)(nil), // 6: hyapp.wallet.v1.AssetBalance - (*GetBalancesRequest)(nil), // 7: hyapp.wallet.v1.GetBalancesRequest - (*GetBalancesResponse)(nil), // 8: hyapp.wallet.v1.GetBalancesResponse - (*HostSalaryPolicyLevel)(nil), // 9: hyapp.wallet.v1.HostSalaryPolicyLevel - (*HostSalaryPolicy)(nil), // 10: hyapp.wallet.v1.HostSalaryPolicy - (*GetActiveHostSalaryPolicyRequest)(nil), // 11: hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest - (*GetActiveHostSalaryPolicyResponse)(nil), // 12: hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse - (*HostSalaryProgress)(nil), // 13: hyapp.wallet.v1.HostSalaryProgress - (*GetHostSalaryProgressRequest)(nil), // 14: hyapp.wallet.v1.GetHostSalaryProgressRequest - (*GetHostSalaryProgressResponse)(nil), // 15: hyapp.wallet.v1.GetHostSalaryProgressResponse - (*AdminCreditAssetRequest)(nil), // 16: hyapp.wallet.v1.AdminCreditAssetRequest - (*AdminCreditAssetResponse)(nil), // 17: hyapp.wallet.v1.AdminCreditAssetResponse - (*AdminCreditCoinSellerStockRequest)(nil), // 18: hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - (*AdminCreditCoinSellerStockResponse)(nil), // 19: hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - (*TransferCoinFromSellerRequest)(nil), // 20: hyapp.wallet.v1.TransferCoinFromSellerRequest - (*TransferCoinFromSellerResponse)(nil), // 21: hyapp.wallet.v1.TransferCoinFromSellerResponse - (*Resource)(nil), // 22: hyapp.wallet.v1.Resource - (*ResourceGroupItem)(nil), // 23: hyapp.wallet.v1.ResourceGroupItem - (*ResourceGroup)(nil), // 24: hyapp.wallet.v1.ResourceGroup - (*GiftConfig)(nil), // 25: hyapp.wallet.v1.GiftConfig - (*GiftTypeConfig)(nil), // 26: hyapp.wallet.v1.GiftTypeConfig - (*ResourceShopItem)(nil), // 27: hyapp.wallet.v1.ResourceShopItem - (*UserResourceEntitlement)(nil), // 28: hyapp.wallet.v1.UserResourceEntitlement - (*ResourceGrantItem)(nil), // 29: hyapp.wallet.v1.ResourceGrantItem - (*ResourceGrant)(nil), // 30: hyapp.wallet.v1.ResourceGrant - (*ResourceGroupItemInput)(nil), // 31: hyapp.wallet.v1.ResourceGroupItemInput - (*ListResourcesRequest)(nil), // 32: hyapp.wallet.v1.ListResourcesRequest - (*ListResourcesResponse)(nil), // 33: hyapp.wallet.v1.ListResourcesResponse - (*GetResourceRequest)(nil), // 34: hyapp.wallet.v1.GetResourceRequest - (*GetResourceResponse)(nil), // 35: hyapp.wallet.v1.GetResourceResponse - (*CreateResourceRequest)(nil), // 36: hyapp.wallet.v1.CreateResourceRequest - (*UpdateResourceRequest)(nil), // 37: hyapp.wallet.v1.UpdateResourceRequest - (*SetResourceStatusRequest)(nil), // 38: hyapp.wallet.v1.SetResourceStatusRequest - (*ResourceResponse)(nil), // 39: hyapp.wallet.v1.ResourceResponse - (*ListResourceGroupsRequest)(nil), // 40: hyapp.wallet.v1.ListResourceGroupsRequest - (*ListResourceGroupsResponse)(nil), // 41: hyapp.wallet.v1.ListResourceGroupsResponse - (*GetResourceGroupRequest)(nil), // 42: hyapp.wallet.v1.GetResourceGroupRequest - (*GetResourceGroupResponse)(nil), // 43: hyapp.wallet.v1.GetResourceGroupResponse - (*CreateResourceGroupRequest)(nil), // 44: hyapp.wallet.v1.CreateResourceGroupRequest - (*UpdateResourceGroupRequest)(nil), // 45: hyapp.wallet.v1.UpdateResourceGroupRequest - (*SetResourceGroupStatusRequest)(nil), // 46: hyapp.wallet.v1.SetResourceGroupStatusRequest - (*ResourceGroupResponse)(nil), // 47: hyapp.wallet.v1.ResourceGroupResponse - (*ListGiftConfigsRequest)(nil), // 48: hyapp.wallet.v1.ListGiftConfigsRequest - (*ListGiftConfigsResponse)(nil), // 49: hyapp.wallet.v1.ListGiftConfigsResponse - (*ListGiftTypeConfigsRequest)(nil), // 50: hyapp.wallet.v1.ListGiftTypeConfigsRequest - (*ListGiftTypeConfigsResponse)(nil), // 51: hyapp.wallet.v1.ListGiftTypeConfigsResponse - (*UpsertGiftTypeConfigRequest)(nil), // 52: hyapp.wallet.v1.UpsertGiftTypeConfigRequest - (*GiftTypeConfigResponse)(nil), // 53: hyapp.wallet.v1.GiftTypeConfigResponse - (*CreateGiftConfigRequest)(nil), // 54: hyapp.wallet.v1.CreateGiftConfigRequest - (*UpdateGiftConfigRequest)(nil), // 55: hyapp.wallet.v1.UpdateGiftConfigRequest - (*SetGiftConfigStatusRequest)(nil), // 56: hyapp.wallet.v1.SetGiftConfigStatusRequest - (*GiftConfigResponse)(nil), // 57: hyapp.wallet.v1.GiftConfigResponse - (*GrantResourceRequest)(nil), // 58: hyapp.wallet.v1.GrantResourceRequest - (*GrantResourceGroupRequest)(nil), // 59: hyapp.wallet.v1.GrantResourceGroupRequest - (*ResourceGrantResponse)(nil), // 60: hyapp.wallet.v1.ResourceGrantResponse - (*ListUserResourcesRequest)(nil), // 61: hyapp.wallet.v1.ListUserResourcesRequest - (*ListUserResourcesResponse)(nil), // 62: hyapp.wallet.v1.ListUserResourcesResponse - (*EquipUserResourceRequest)(nil), // 63: hyapp.wallet.v1.EquipUserResourceRequest - (*EquipUserResourceResponse)(nil), // 64: hyapp.wallet.v1.EquipUserResourceResponse - (*UnequipUserResourceRequest)(nil), // 65: hyapp.wallet.v1.UnequipUserResourceRequest - (*UnequipUserResourceResponse)(nil), // 66: hyapp.wallet.v1.UnequipUserResourceResponse - (*BatchGetUserEquippedResourcesRequest)(nil), // 67: hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - (*UserEquippedResources)(nil), // 68: hyapp.wallet.v1.UserEquippedResources - (*BatchGetUserEquippedResourcesResponse)(nil), // 69: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - (*ListResourceGrantsRequest)(nil), // 70: hyapp.wallet.v1.ListResourceGrantsRequest - (*ListResourceGrantsResponse)(nil), // 71: hyapp.wallet.v1.ListResourceGrantsResponse - (*ResourceShopItemInput)(nil), // 72: hyapp.wallet.v1.ResourceShopItemInput - (*ListResourceShopItemsRequest)(nil), // 73: hyapp.wallet.v1.ListResourceShopItemsRequest - (*ListResourceShopItemsResponse)(nil), // 74: hyapp.wallet.v1.ListResourceShopItemsResponse - (*UpsertResourceShopItemsRequest)(nil), // 75: hyapp.wallet.v1.UpsertResourceShopItemsRequest - (*UpsertResourceShopItemsResponse)(nil), // 76: hyapp.wallet.v1.UpsertResourceShopItemsResponse - (*SetResourceShopItemStatusRequest)(nil), // 77: hyapp.wallet.v1.SetResourceShopItemStatusRequest - (*ResourceShopItemResponse)(nil), // 78: hyapp.wallet.v1.ResourceShopItemResponse - (*PurchaseResourceShopItemRequest)(nil), // 79: hyapp.wallet.v1.PurchaseResourceShopItemRequest - (*PurchaseResourceShopItemResponse)(nil), // 80: hyapp.wallet.v1.PurchaseResourceShopItemResponse - (*RechargeBill)(nil), // 81: hyapp.wallet.v1.RechargeBill - (*ListRechargeBillsRequest)(nil), // 82: hyapp.wallet.v1.ListRechargeBillsRequest - (*ListRechargeBillsResponse)(nil), // 83: hyapp.wallet.v1.ListRechargeBillsResponse - (*WalletFeatureFlags)(nil), // 84: hyapp.wallet.v1.WalletFeatureFlags - (*GetWalletOverviewRequest)(nil), // 85: hyapp.wallet.v1.GetWalletOverviewRequest - (*GetWalletOverviewResponse)(nil), // 86: hyapp.wallet.v1.GetWalletOverviewResponse - (*WalletValueSummary)(nil), // 87: hyapp.wallet.v1.WalletValueSummary - (*GetWalletValueSummaryRequest)(nil), // 88: hyapp.wallet.v1.GetWalletValueSummaryRequest - (*GetWalletValueSummaryResponse)(nil), // 89: hyapp.wallet.v1.GetWalletValueSummaryResponse - (*GiftWallItem)(nil), // 90: hyapp.wallet.v1.GiftWallItem - (*GetUserGiftWallRequest)(nil), // 91: hyapp.wallet.v1.GetUserGiftWallRequest - (*GetUserGiftWallResponse)(nil), // 92: hyapp.wallet.v1.GetUserGiftWallResponse - (*RechargeProduct)(nil), // 93: hyapp.wallet.v1.RechargeProduct - (*ListRechargeProductsRequest)(nil), // 94: hyapp.wallet.v1.ListRechargeProductsRequest - (*ListRechargeProductsResponse)(nil), // 95: hyapp.wallet.v1.ListRechargeProductsResponse - (*ConfirmGooglePaymentRequest)(nil), // 96: hyapp.wallet.v1.ConfirmGooglePaymentRequest - (*ConfirmGooglePaymentResponse)(nil), // 97: hyapp.wallet.v1.ConfirmGooglePaymentResponse - (*ListAdminRechargeProductsRequest)(nil), // 98: hyapp.wallet.v1.ListAdminRechargeProductsRequest - (*ListAdminRechargeProductsResponse)(nil), // 99: hyapp.wallet.v1.ListAdminRechargeProductsResponse - (*CreateRechargeProductRequest)(nil), // 100: hyapp.wallet.v1.CreateRechargeProductRequest - (*UpdateRechargeProductRequest)(nil), // 101: hyapp.wallet.v1.UpdateRechargeProductRequest - (*DeleteRechargeProductRequest)(nil), // 102: hyapp.wallet.v1.DeleteRechargeProductRequest - (*RechargeProductResponse)(nil), // 103: hyapp.wallet.v1.RechargeProductResponse - (*DeleteRechargeProductResponse)(nil), // 104: hyapp.wallet.v1.DeleteRechargeProductResponse - (*DiamondExchangeRule)(nil), // 105: hyapp.wallet.v1.DiamondExchangeRule - (*GetDiamondExchangeConfigRequest)(nil), // 106: hyapp.wallet.v1.GetDiamondExchangeConfigRequest - (*GetDiamondExchangeConfigResponse)(nil), // 107: hyapp.wallet.v1.GetDiamondExchangeConfigResponse - (*WalletTransaction)(nil), // 108: hyapp.wallet.v1.WalletTransaction - (*ListWalletTransactionsRequest)(nil), // 109: hyapp.wallet.v1.ListWalletTransactionsRequest - (*ListWalletTransactionsResponse)(nil), // 110: hyapp.wallet.v1.ListWalletTransactionsResponse - (*VipRewardItem)(nil), // 111: hyapp.wallet.v1.VipRewardItem - (*VipLevel)(nil), // 112: hyapp.wallet.v1.VipLevel - (*UserVip)(nil), // 113: hyapp.wallet.v1.UserVip - (*ListVipPackagesRequest)(nil), // 114: hyapp.wallet.v1.ListVipPackagesRequest - (*ListVipPackagesResponse)(nil), // 115: hyapp.wallet.v1.ListVipPackagesResponse - (*GetMyVipRequest)(nil), // 116: hyapp.wallet.v1.GetMyVipRequest - (*GetMyVipResponse)(nil), // 117: hyapp.wallet.v1.GetMyVipResponse - (*PurchaseVipRequest)(nil), // 118: hyapp.wallet.v1.PurchaseVipRequest - (*PurchaseVipResponse)(nil), // 119: hyapp.wallet.v1.PurchaseVipResponse - (*GrantVipRequest)(nil), // 120: hyapp.wallet.v1.GrantVipRequest - (*GrantVipResponse)(nil), // 121: hyapp.wallet.v1.GrantVipResponse - (*AdminVipLevelInput)(nil), // 122: hyapp.wallet.v1.AdminVipLevelInput - (*ListAdminVipLevelsRequest)(nil), // 123: hyapp.wallet.v1.ListAdminVipLevelsRequest - (*ListAdminVipLevelsResponse)(nil), // 124: hyapp.wallet.v1.ListAdminVipLevelsResponse - (*UpdateAdminVipLevelsRequest)(nil), // 125: hyapp.wallet.v1.UpdateAdminVipLevelsRequest - (*UpdateAdminVipLevelsResponse)(nil), // 126: hyapp.wallet.v1.UpdateAdminVipLevelsResponse - (*CreditTaskRewardRequest)(nil), // 127: hyapp.wallet.v1.CreditTaskRewardRequest - (*CreditTaskRewardResponse)(nil), // 128: hyapp.wallet.v1.CreditTaskRewardResponse - (*CreditLuckyGiftRewardRequest)(nil), // 129: hyapp.wallet.v1.CreditLuckyGiftRewardRequest - (*CreditLuckyGiftRewardResponse)(nil), // 130: hyapp.wallet.v1.CreditLuckyGiftRewardResponse - (*ApplyGameCoinChangeRequest)(nil), // 131: hyapp.wallet.v1.ApplyGameCoinChangeRequest - (*ApplyGameCoinChangeResponse)(nil), // 132: hyapp.wallet.v1.ApplyGameCoinChangeResponse - (*RedPacketConfig)(nil), // 133: hyapp.wallet.v1.RedPacketConfig - (*RedPacketClaim)(nil), // 134: hyapp.wallet.v1.RedPacketClaim - (*RedPacket)(nil), // 135: hyapp.wallet.v1.RedPacket - (*GetRedPacketConfigRequest)(nil), // 136: hyapp.wallet.v1.GetRedPacketConfigRequest - (*GetRedPacketConfigResponse)(nil), // 137: hyapp.wallet.v1.GetRedPacketConfigResponse - (*UpdateRedPacketConfigRequest)(nil), // 138: hyapp.wallet.v1.UpdateRedPacketConfigRequest - (*UpdateRedPacketConfigResponse)(nil), // 139: hyapp.wallet.v1.UpdateRedPacketConfigResponse - (*CreateRedPacketRequest)(nil), // 140: hyapp.wallet.v1.CreateRedPacketRequest - (*CreateRedPacketResponse)(nil), // 141: hyapp.wallet.v1.CreateRedPacketResponse - (*ClaimRedPacketRequest)(nil), // 142: hyapp.wallet.v1.ClaimRedPacketRequest - (*ClaimRedPacketResponse)(nil), // 143: hyapp.wallet.v1.ClaimRedPacketResponse - (*ListRedPacketsRequest)(nil), // 144: hyapp.wallet.v1.ListRedPacketsRequest - (*ListRedPacketsResponse)(nil), // 145: hyapp.wallet.v1.ListRedPacketsResponse - (*GetRedPacketRequest)(nil), // 146: hyapp.wallet.v1.GetRedPacketRequest - (*GetRedPacketResponse)(nil), // 147: hyapp.wallet.v1.GetRedPacketResponse - (*ExpireRedPacketsRequest)(nil), // 148: hyapp.wallet.v1.ExpireRedPacketsRequest - (*ExpireRedPacketsResponse)(nil), // 149: hyapp.wallet.v1.ExpireRedPacketsResponse - (*RetryRedPacketRefundRequest)(nil), // 150: hyapp.wallet.v1.RetryRedPacketRefundRequest - (*RetryRedPacketRefundResponse)(nil), // 151: hyapp.wallet.v1.RetryRedPacketRefundResponse - (*CronBatchRequest)(nil), // 152: hyapp.wallet.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 153: hyapp.wallet.v1.CronBatchResponse + (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest + (*DebitGiftResponse)(nil), // 1: hyapp.wallet.v1.DebitGiftResponse + (*DebitGiftTarget)(nil), // 2: hyapp.wallet.v1.DebitGiftTarget + (*BatchDebitGiftRequest)(nil), // 3: hyapp.wallet.v1.BatchDebitGiftRequest + (*BatchDebitGiftReceipt)(nil), // 4: hyapp.wallet.v1.BatchDebitGiftReceipt + (*BatchDebitGiftResponse)(nil), // 5: hyapp.wallet.v1.BatchDebitGiftResponse + (*AssetBalance)(nil), // 6: hyapp.wallet.v1.AssetBalance + (*GetBalancesRequest)(nil), // 7: hyapp.wallet.v1.GetBalancesRequest + (*GetBalancesResponse)(nil), // 8: hyapp.wallet.v1.GetBalancesResponse + (*HostSalaryPolicyLevel)(nil), // 9: hyapp.wallet.v1.HostSalaryPolicyLevel + (*HostSalaryPolicy)(nil), // 10: hyapp.wallet.v1.HostSalaryPolicy + (*GetActiveHostSalaryPolicyRequest)(nil), // 11: hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + (*GetActiveHostSalaryPolicyResponse)(nil), // 12: hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + (*HostSalaryProgress)(nil), // 13: hyapp.wallet.v1.HostSalaryProgress + (*GetHostSalaryProgressRequest)(nil), // 14: hyapp.wallet.v1.GetHostSalaryProgressRequest + (*GetHostSalaryProgressResponse)(nil), // 15: hyapp.wallet.v1.GetHostSalaryProgressResponse + (*AdminCreditAssetRequest)(nil), // 16: hyapp.wallet.v1.AdminCreditAssetRequest + (*AdminCreditAssetResponse)(nil), // 17: hyapp.wallet.v1.AdminCreditAssetResponse + (*AdminCreditCoinSellerStockRequest)(nil), // 18: hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + (*AdminCreditCoinSellerStockResponse)(nil), // 19: hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + (*TransferCoinFromSellerRequest)(nil), // 20: hyapp.wallet.v1.TransferCoinFromSellerRequest + (*TransferCoinFromSellerResponse)(nil), // 21: hyapp.wallet.v1.TransferCoinFromSellerResponse + (*CoinSellerSalaryExchangeRateTier)(nil), // 22: hyapp.wallet.v1.CoinSellerSalaryExchangeRateTier + (*ListCoinSellerSalaryExchangeRateTiersRequest)(nil), // 23: hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest + (*ListCoinSellerSalaryExchangeRateTiersResponse)(nil), // 24: hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse + (*ExchangeSalaryToCoinRequest)(nil), // 25: hyapp.wallet.v1.ExchangeSalaryToCoinRequest + (*ExchangeSalaryToCoinResponse)(nil), // 26: hyapp.wallet.v1.ExchangeSalaryToCoinResponse + (*TransferSalaryToCoinSellerRequest)(nil), // 27: hyapp.wallet.v1.TransferSalaryToCoinSellerRequest + (*TransferSalaryToCoinSellerResponse)(nil), // 28: hyapp.wallet.v1.TransferSalaryToCoinSellerResponse + (*Resource)(nil), // 29: hyapp.wallet.v1.Resource + (*ResourceGroupItem)(nil), // 30: hyapp.wallet.v1.ResourceGroupItem + (*ResourceGroup)(nil), // 31: hyapp.wallet.v1.ResourceGroup + (*GiftConfig)(nil), // 32: hyapp.wallet.v1.GiftConfig + (*GiftTypeConfig)(nil), // 33: hyapp.wallet.v1.GiftTypeConfig + (*ResourceShopItem)(nil), // 34: hyapp.wallet.v1.ResourceShopItem + (*UserResourceEntitlement)(nil), // 35: hyapp.wallet.v1.UserResourceEntitlement + (*ResourceGrantItem)(nil), // 36: hyapp.wallet.v1.ResourceGrantItem + (*ResourceGrant)(nil), // 37: hyapp.wallet.v1.ResourceGrant + (*ResourceGroupItemInput)(nil), // 38: hyapp.wallet.v1.ResourceGroupItemInput + (*ListResourcesRequest)(nil), // 39: hyapp.wallet.v1.ListResourcesRequest + (*ListResourcesResponse)(nil), // 40: hyapp.wallet.v1.ListResourcesResponse + (*GetResourceRequest)(nil), // 41: hyapp.wallet.v1.GetResourceRequest + (*GetResourceResponse)(nil), // 42: hyapp.wallet.v1.GetResourceResponse + (*CreateResourceRequest)(nil), // 43: hyapp.wallet.v1.CreateResourceRequest + (*UpdateResourceRequest)(nil), // 44: hyapp.wallet.v1.UpdateResourceRequest + (*SetResourceStatusRequest)(nil), // 45: hyapp.wallet.v1.SetResourceStatusRequest + (*ResourceResponse)(nil), // 46: hyapp.wallet.v1.ResourceResponse + (*ListResourceGroupsRequest)(nil), // 47: hyapp.wallet.v1.ListResourceGroupsRequest + (*ListResourceGroupsResponse)(nil), // 48: hyapp.wallet.v1.ListResourceGroupsResponse + (*GetResourceGroupRequest)(nil), // 49: hyapp.wallet.v1.GetResourceGroupRequest + (*GetResourceGroupResponse)(nil), // 50: hyapp.wallet.v1.GetResourceGroupResponse + (*CreateResourceGroupRequest)(nil), // 51: hyapp.wallet.v1.CreateResourceGroupRequest + (*UpdateResourceGroupRequest)(nil), // 52: hyapp.wallet.v1.UpdateResourceGroupRequest + (*SetResourceGroupStatusRequest)(nil), // 53: hyapp.wallet.v1.SetResourceGroupStatusRequest + (*ResourceGroupResponse)(nil), // 54: hyapp.wallet.v1.ResourceGroupResponse + (*ListGiftConfigsRequest)(nil), // 55: hyapp.wallet.v1.ListGiftConfigsRequest + (*ListGiftConfigsResponse)(nil), // 56: hyapp.wallet.v1.ListGiftConfigsResponse + (*ListGiftTypeConfigsRequest)(nil), // 57: hyapp.wallet.v1.ListGiftTypeConfigsRequest + (*ListGiftTypeConfigsResponse)(nil), // 58: hyapp.wallet.v1.ListGiftTypeConfigsResponse + (*UpsertGiftTypeConfigRequest)(nil), // 59: hyapp.wallet.v1.UpsertGiftTypeConfigRequest + (*GiftTypeConfigResponse)(nil), // 60: hyapp.wallet.v1.GiftTypeConfigResponse + (*CreateGiftConfigRequest)(nil), // 61: hyapp.wallet.v1.CreateGiftConfigRequest + (*UpdateGiftConfigRequest)(nil), // 62: hyapp.wallet.v1.UpdateGiftConfigRequest + (*SetGiftConfigStatusRequest)(nil), // 63: hyapp.wallet.v1.SetGiftConfigStatusRequest + (*GiftConfigResponse)(nil), // 64: hyapp.wallet.v1.GiftConfigResponse + (*GrantResourceRequest)(nil), // 65: hyapp.wallet.v1.GrantResourceRequest + (*GrantResourceGroupRequest)(nil), // 66: hyapp.wallet.v1.GrantResourceGroupRequest + (*ResourceGrantResponse)(nil), // 67: hyapp.wallet.v1.ResourceGrantResponse + (*ListUserResourcesRequest)(nil), // 68: hyapp.wallet.v1.ListUserResourcesRequest + (*ListUserResourcesResponse)(nil), // 69: hyapp.wallet.v1.ListUserResourcesResponse + (*EquipUserResourceRequest)(nil), // 70: hyapp.wallet.v1.EquipUserResourceRequest + (*EquipUserResourceResponse)(nil), // 71: hyapp.wallet.v1.EquipUserResourceResponse + (*UnequipUserResourceRequest)(nil), // 72: hyapp.wallet.v1.UnequipUserResourceRequest + (*UnequipUserResourceResponse)(nil), // 73: hyapp.wallet.v1.UnequipUserResourceResponse + (*BatchGetUserEquippedResourcesRequest)(nil), // 74: hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + (*UserEquippedResources)(nil), // 75: hyapp.wallet.v1.UserEquippedResources + (*BatchGetUserEquippedResourcesResponse)(nil), // 76: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + (*ListResourceGrantsRequest)(nil), // 77: hyapp.wallet.v1.ListResourceGrantsRequest + (*ListResourceGrantsResponse)(nil), // 78: hyapp.wallet.v1.ListResourceGrantsResponse + (*ResourceShopItemInput)(nil), // 79: hyapp.wallet.v1.ResourceShopItemInput + (*ListResourceShopItemsRequest)(nil), // 80: hyapp.wallet.v1.ListResourceShopItemsRequest + (*ListResourceShopItemsResponse)(nil), // 81: hyapp.wallet.v1.ListResourceShopItemsResponse + (*UpsertResourceShopItemsRequest)(nil), // 82: hyapp.wallet.v1.UpsertResourceShopItemsRequest + (*UpsertResourceShopItemsResponse)(nil), // 83: hyapp.wallet.v1.UpsertResourceShopItemsResponse + (*SetResourceShopItemStatusRequest)(nil), // 84: hyapp.wallet.v1.SetResourceShopItemStatusRequest + (*ResourceShopItemResponse)(nil), // 85: hyapp.wallet.v1.ResourceShopItemResponse + (*PurchaseResourceShopItemRequest)(nil), // 86: hyapp.wallet.v1.PurchaseResourceShopItemRequest + (*PurchaseResourceShopItemResponse)(nil), // 87: hyapp.wallet.v1.PurchaseResourceShopItemResponse + (*RechargeBill)(nil), // 88: hyapp.wallet.v1.RechargeBill + (*ListRechargeBillsRequest)(nil), // 89: hyapp.wallet.v1.ListRechargeBillsRequest + (*ListRechargeBillsResponse)(nil), // 90: hyapp.wallet.v1.ListRechargeBillsResponse + (*WalletFeatureFlags)(nil), // 91: hyapp.wallet.v1.WalletFeatureFlags + (*GetWalletOverviewRequest)(nil), // 92: hyapp.wallet.v1.GetWalletOverviewRequest + (*GetWalletOverviewResponse)(nil), // 93: hyapp.wallet.v1.GetWalletOverviewResponse + (*WalletValueSummary)(nil), // 94: hyapp.wallet.v1.WalletValueSummary + (*GetWalletValueSummaryRequest)(nil), // 95: hyapp.wallet.v1.GetWalletValueSummaryRequest + (*GetWalletValueSummaryResponse)(nil), // 96: hyapp.wallet.v1.GetWalletValueSummaryResponse + (*GiftWallItem)(nil), // 97: hyapp.wallet.v1.GiftWallItem + (*GetUserGiftWallRequest)(nil), // 98: hyapp.wallet.v1.GetUserGiftWallRequest + (*GetUserGiftWallResponse)(nil), // 99: hyapp.wallet.v1.GetUserGiftWallResponse + (*RechargeProduct)(nil), // 100: hyapp.wallet.v1.RechargeProduct + (*ListRechargeProductsRequest)(nil), // 101: hyapp.wallet.v1.ListRechargeProductsRequest + (*ListRechargeProductsResponse)(nil), // 102: hyapp.wallet.v1.ListRechargeProductsResponse + (*ConfirmGooglePaymentRequest)(nil), // 103: hyapp.wallet.v1.ConfirmGooglePaymentRequest + (*ConfirmGooglePaymentResponse)(nil), // 104: hyapp.wallet.v1.ConfirmGooglePaymentResponse + (*ListAdminRechargeProductsRequest)(nil), // 105: hyapp.wallet.v1.ListAdminRechargeProductsRequest + (*ListAdminRechargeProductsResponse)(nil), // 106: hyapp.wallet.v1.ListAdminRechargeProductsResponse + (*CreateRechargeProductRequest)(nil), // 107: hyapp.wallet.v1.CreateRechargeProductRequest + (*UpdateRechargeProductRequest)(nil), // 108: hyapp.wallet.v1.UpdateRechargeProductRequest + (*DeleteRechargeProductRequest)(nil), // 109: hyapp.wallet.v1.DeleteRechargeProductRequest + (*RechargeProductResponse)(nil), // 110: hyapp.wallet.v1.RechargeProductResponse + (*DeleteRechargeProductResponse)(nil), // 111: hyapp.wallet.v1.DeleteRechargeProductResponse + (*DiamondExchangeRule)(nil), // 112: hyapp.wallet.v1.DiamondExchangeRule + (*GetDiamondExchangeConfigRequest)(nil), // 113: hyapp.wallet.v1.GetDiamondExchangeConfigRequest + (*GetDiamondExchangeConfigResponse)(nil), // 114: hyapp.wallet.v1.GetDiamondExchangeConfigResponse + (*WalletTransaction)(nil), // 115: hyapp.wallet.v1.WalletTransaction + (*ListWalletTransactionsRequest)(nil), // 116: hyapp.wallet.v1.ListWalletTransactionsRequest + (*ListWalletTransactionsResponse)(nil), // 117: hyapp.wallet.v1.ListWalletTransactionsResponse + (*VipRewardItem)(nil), // 118: hyapp.wallet.v1.VipRewardItem + (*VipLevel)(nil), // 119: hyapp.wallet.v1.VipLevel + (*UserVip)(nil), // 120: hyapp.wallet.v1.UserVip + (*ListVipPackagesRequest)(nil), // 121: hyapp.wallet.v1.ListVipPackagesRequest + (*ListVipPackagesResponse)(nil), // 122: hyapp.wallet.v1.ListVipPackagesResponse + (*GetMyVipRequest)(nil), // 123: hyapp.wallet.v1.GetMyVipRequest + (*GetMyVipResponse)(nil), // 124: hyapp.wallet.v1.GetMyVipResponse + (*PurchaseVipRequest)(nil), // 125: hyapp.wallet.v1.PurchaseVipRequest + (*PurchaseVipResponse)(nil), // 126: hyapp.wallet.v1.PurchaseVipResponse + (*GrantVipRequest)(nil), // 127: hyapp.wallet.v1.GrantVipRequest + (*GrantVipResponse)(nil), // 128: hyapp.wallet.v1.GrantVipResponse + (*AdminVipLevelInput)(nil), // 129: hyapp.wallet.v1.AdminVipLevelInput + (*ListAdminVipLevelsRequest)(nil), // 130: hyapp.wallet.v1.ListAdminVipLevelsRequest + (*ListAdminVipLevelsResponse)(nil), // 131: hyapp.wallet.v1.ListAdminVipLevelsResponse + (*UpdateAdminVipLevelsRequest)(nil), // 132: hyapp.wallet.v1.UpdateAdminVipLevelsRequest + (*UpdateAdminVipLevelsResponse)(nil), // 133: hyapp.wallet.v1.UpdateAdminVipLevelsResponse + (*CreditTaskRewardRequest)(nil), // 134: hyapp.wallet.v1.CreditTaskRewardRequest + (*CreditTaskRewardResponse)(nil), // 135: hyapp.wallet.v1.CreditTaskRewardResponse + (*CreditLuckyGiftRewardRequest)(nil), // 136: hyapp.wallet.v1.CreditLuckyGiftRewardRequest + (*CreditLuckyGiftRewardResponse)(nil), // 137: hyapp.wallet.v1.CreditLuckyGiftRewardResponse + (*ApplyGameCoinChangeRequest)(nil), // 138: hyapp.wallet.v1.ApplyGameCoinChangeRequest + (*ApplyGameCoinChangeResponse)(nil), // 139: hyapp.wallet.v1.ApplyGameCoinChangeResponse + (*RedPacketConfig)(nil), // 140: hyapp.wallet.v1.RedPacketConfig + (*RedPacketClaim)(nil), // 141: hyapp.wallet.v1.RedPacketClaim + (*RedPacket)(nil), // 142: hyapp.wallet.v1.RedPacket + (*GetRedPacketConfigRequest)(nil), // 143: hyapp.wallet.v1.GetRedPacketConfigRequest + (*GetRedPacketConfigResponse)(nil), // 144: hyapp.wallet.v1.GetRedPacketConfigResponse + (*UpdateRedPacketConfigRequest)(nil), // 145: hyapp.wallet.v1.UpdateRedPacketConfigRequest + (*UpdateRedPacketConfigResponse)(nil), // 146: hyapp.wallet.v1.UpdateRedPacketConfigResponse + (*CreateRedPacketRequest)(nil), // 147: hyapp.wallet.v1.CreateRedPacketRequest + (*CreateRedPacketResponse)(nil), // 148: hyapp.wallet.v1.CreateRedPacketResponse + (*ClaimRedPacketRequest)(nil), // 149: hyapp.wallet.v1.ClaimRedPacketRequest + (*ClaimRedPacketResponse)(nil), // 150: hyapp.wallet.v1.ClaimRedPacketResponse + (*ListRedPacketsRequest)(nil), // 151: hyapp.wallet.v1.ListRedPacketsRequest + (*ListRedPacketsResponse)(nil), // 152: hyapp.wallet.v1.ListRedPacketsResponse + (*GetRedPacketRequest)(nil), // 153: hyapp.wallet.v1.GetRedPacketRequest + (*GetRedPacketResponse)(nil), // 154: hyapp.wallet.v1.GetRedPacketResponse + (*ExpireRedPacketsRequest)(nil), // 155: hyapp.wallet.v1.ExpireRedPacketsRequest + (*ExpireRedPacketsResponse)(nil), // 156: hyapp.wallet.v1.ExpireRedPacketsResponse + (*RetryRedPacketRefundRequest)(nil), // 157: hyapp.wallet.v1.RetryRedPacketRefundRequest + (*RetryRedPacketRefundResponse)(nil), // 158: hyapp.wallet.v1.RetryRedPacketRefundResponse + (*CronBatchRequest)(nil), // 159: hyapp.wallet.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 160: hyapp.wallet.v1.CronBatchResponse } var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 2, // 0: hyapp.wallet.v1.BatchDebitGiftRequest.targets:type_name -> hyapp.wallet.v1.DebitGiftTarget @@ -15067,210 +15709,217 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 10, // 6: hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse.policy:type_name -> hyapp.wallet.v1.HostSalaryPolicy 13, // 7: hyapp.wallet.v1.GetHostSalaryProgressResponse.progress:type_name -> hyapp.wallet.v1.HostSalaryProgress 6, // 8: hyapp.wallet.v1.AdminCreditAssetResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 22, // 9: hyapp.wallet.v1.ResourceGroupItem.resource:type_name -> hyapp.wallet.v1.Resource - 23, // 10: hyapp.wallet.v1.ResourceGroup.items:type_name -> hyapp.wallet.v1.ResourceGroupItem - 22, // 11: hyapp.wallet.v1.GiftConfig.resource:type_name -> hyapp.wallet.v1.Resource - 22, // 12: hyapp.wallet.v1.ResourceShopItem.resource:type_name -> hyapp.wallet.v1.Resource - 22, // 13: hyapp.wallet.v1.UserResourceEntitlement.resource:type_name -> hyapp.wallet.v1.Resource - 29, // 14: hyapp.wallet.v1.ResourceGrant.items:type_name -> hyapp.wallet.v1.ResourceGrantItem - 22, // 15: hyapp.wallet.v1.ListResourcesResponse.resources:type_name -> hyapp.wallet.v1.Resource - 22, // 16: hyapp.wallet.v1.GetResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource - 22, // 17: hyapp.wallet.v1.ResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource - 24, // 18: hyapp.wallet.v1.ListResourceGroupsResponse.groups:type_name -> hyapp.wallet.v1.ResourceGroup - 24, // 19: hyapp.wallet.v1.GetResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup - 31, // 20: hyapp.wallet.v1.CreateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput - 31, // 21: hyapp.wallet.v1.UpdateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput - 24, // 22: hyapp.wallet.v1.ResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup - 25, // 23: hyapp.wallet.v1.ListGiftConfigsResponse.gifts:type_name -> hyapp.wallet.v1.GiftConfig - 26, // 24: hyapp.wallet.v1.ListGiftTypeConfigsResponse.gift_types:type_name -> hyapp.wallet.v1.GiftTypeConfig - 26, // 25: hyapp.wallet.v1.GiftTypeConfigResponse.gift_type:type_name -> hyapp.wallet.v1.GiftTypeConfig - 25, // 26: hyapp.wallet.v1.GiftConfigResponse.gift:type_name -> hyapp.wallet.v1.GiftConfig - 30, // 27: hyapp.wallet.v1.ResourceGrantResponse.grant:type_name -> hyapp.wallet.v1.ResourceGrant - 28, // 28: hyapp.wallet.v1.ListUserResourcesResponse.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 28, // 29: hyapp.wallet.v1.EquipUserResourceResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 28, // 30: hyapp.wallet.v1.UserEquippedResources.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 68, // 31: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse.users:type_name -> hyapp.wallet.v1.UserEquippedResources - 30, // 32: hyapp.wallet.v1.ListResourceGrantsResponse.grants:type_name -> hyapp.wallet.v1.ResourceGrant - 27, // 33: hyapp.wallet.v1.ListResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem - 72, // 34: hyapp.wallet.v1.UpsertResourceShopItemsRequest.items:type_name -> hyapp.wallet.v1.ResourceShopItemInput - 27, // 35: hyapp.wallet.v1.UpsertResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem - 27, // 36: hyapp.wallet.v1.ResourceShopItemResponse.item:type_name -> hyapp.wallet.v1.ResourceShopItem - 27, // 37: hyapp.wallet.v1.PurchaseResourceShopItemResponse.shop_item:type_name -> hyapp.wallet.v1.ResourceShopItem - 28, // 38: hyapp.wallet.v1.PurchaseResourceShopItemResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement - 6, // 39: hyapp.wallet.v1.PurchaseResourceShopItemResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 81, // 40: hyapp.wallet.v1.ListRechargeBillsResponse.bills:type_name -> hyapp.wallet.v1.RechargeBill - 6, // 41: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance - 84, // 42: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags - 87, // 43: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary - 22, // 44: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource - 90, // 45: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem - 93, // 46: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 6, // 47: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 93, // 48: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct - 93, // 49: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct - 105, // 50: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule - 108, // 51: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction - 111, // 52: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 113, // 53: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip - 112, // 54: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel - 113, // 55: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 113, // 56: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 111, // 57: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 113, // 58: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip - 111, // 59: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem - 112, // 60: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 122, // 61: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput - 112, // 62: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel - 6, // 63: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 6, // 64: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 134, // 65: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 133, // 66: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 133, // 67: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 135, // 68: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 134, // 69: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 135, // 70: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 135, // 71: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 135, // 72: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 135, // 73: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 152, // 74: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 152, // 75: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 152, // 76: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 0, // 77: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 3, // 78: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest - 7, // 79: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 11, // 80: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest - 14, // 81: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest - 16, // 82: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 18, // 83: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 20, // 84: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 32, // 85: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 34, // 86: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 36, // 87: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 37, // 88: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 38, // 89: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 40, // 90: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 42, // 91: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 44, // 92: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 45, // 93: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 46, // 94: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 48, // 95: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 50, // 96: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 54, // 97: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 55, // 98: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 56, // 99: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 52, // 100: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 58, // 101: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 59, // 102: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 61, // 103: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 63, // 104: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 65, // 105: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest - 67, // 106: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - 70, // 107: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 73, // 108: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 75, // 109: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 77, // 110: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 79, // 111: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 82, // 112: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 85, // 113: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 88, // 114: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 91, // 115: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 94, // 116: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 96, // 117: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 98, // 118: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 100, // 119: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 101, // 120: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 102, // 121: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 106, // 122: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 109, // 123: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 114, // 124: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 116, // 125: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 118, // 126: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 120, // 127: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 123, // 128: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 125, // 129: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 127, // 130: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 129, // 131: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 131, // 132: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 136, // 133: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 138, // 134: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 140, // 135: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 142, // 136: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 144, // 137: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 146, // 138: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 148, // 139: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 150, // 140: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 153, // 141: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 153, // 142: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 153, // 143: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 1, // 144: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 5, // 145: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse - 8, // 146: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 12, // 147: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse - 15, // 148: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse - 17, // 149: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 19, // 150: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 21, // 151: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 33, // 152: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 35, // 153: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 39, // 154: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 39, // 155: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 39, // 156: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 41, // 157: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 43, // 158: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 47, // 159: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 47, // 160: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 47, // 161: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 49, // 162: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 51, // 163: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 57, // 164: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 57, // 165: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 57, // 166: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 53, // 167: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 60, // 168: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 60, // 169: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 62, // 170: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 64, // 171: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 66, // 172: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse - 69, // 173: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - 71, // 174: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 74, // 175: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 76, // 176: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 78, // 177: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 80, // 178: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 83, // 179: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 86, // 180: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 89, // 181: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 92, // 182: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 95, // 183: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 97, // 184: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 99, // 185: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 103, // 186: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 103, // 187: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 104, // 188: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 107, // 189: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 110, // 190: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 115, // 191: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 117, // 192: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 119, // 193: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 121, // 194: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 124, // 195: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 126, // 196: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 128, // 197: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 130, // 198: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 132, // 199: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 137, // 200: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 139, // 201: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 141, // 202: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 143, // 203: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 145, // 204: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 147, // 205: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 149, // 206: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 151, // 207: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 141, // [141:208] is the sub-list for method output_type - 74, // [74:141] is the sub-list for method input_type - 74, // [74:74] is the sub-list for extension type_name - 74, // [74:74] is the sub-list for extension extendee - 0, // [0:74] is the sub-list for field type_name + 22, // 9: hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse.tiers:type_name -> hyapp.wallet.v1.CoinSellerSalaryExchangeRateTier + 29, // 10: hyapp.wallet.v1.ResourceGroupItem.resource:type_name -> hyapp.wallet.v1.Resource + 30, // 11: hyapp.wallet.v1.ResourceGroup.items:type_name -> hyapp.wallet.v1.ResourceGroupItem + 29, // 12: hyapp.wallet.v1.GiftConfig.resource:type_name -> hyapp.wallet.v1.Resource + 29, // 13: hyapp.wallet.v1.ResourceShopItem.resource:type_name -> hyapp.wallet.v1.Resource + 29, // 14: hyapp.wallet.v1.UserResourceEntitlement.resource:type_name -> hyapp.wallet.v1.Resource + 36, // 15: hyapp.wallet.v1.ResourceGrant.items:type_name -> hyapp.wallet.v1.ResourceGrantItem + 29, // 16: hyapp.wallet.v1.ListResourcesResponse.resources:type_name -> hyapp.wallet.v1.Resource + 29, // 17: hyapp.wallet.v1.GetResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource + 29, // 18: hyapp.wallet.v1.ResourceResponse.resource:type_name -> hyapp.wallet.v1.Resource + 31, // 19: hyapp.wallet.v1.ListResourceGroupsResponse.groups:type_name -> hyapp.wallet.v1.ResourceGroup + 31, // 20: hyapp.wallet.v1.GetResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup + 38, // 21: hyapp.wallet.v1.CreateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput + 38, // 22: hyapp.wallet.v1.UpdateResourceGroupRequest.items:type_name -> hyapp.wallet.v1.ResourceGroupItemInput + 31, // 23: hyapp.wallet.v1.ResourceGroupResponse.group:type_name -> hyapp.wallet.v1.ResourceGroup + 32, // 24: hyapp.wallet.v1.ListGiftConfigsResponse.gifts:type_name -> hyapp.wallet.v1.GiftConfig + 33, // 25: hyapp.wallet.v1.ListGiftTypeConfigsResponse.gift_types:type_name -> hyapp.wallet.v1.GiftTypeConfig + 33, // 26: hyapp.wallet.v1.GiftTypeConfigResponse.gift_type:type_name -> hyapp.wallet.v1.GiftTypeConfig + 32, // 27: hyapp.wallet.v1.GiftConfigResponse.gift:type_name -> hyapp.wallet.v1.GiftConfig + 37, // 28: hyapp.wallet.v1.ResourceGrantResponse.grant:type_name -> hyapp.wallet.v1.ResourceGrant + 35, // 29: hyapp.wallet.v1.ListUserResourcesResponse.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 35, // 30: hyapp.wallet.v1.EquipUserResourceResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 35, // 31: hyapp.wallet.v1.UserEquippedResources.resources:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 75, // 32: hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse.users:type_name -> hyapp.wallet.v1.UserEquippedResources + 37, // 33: hyapp.wallet.v1.ListResourceGrantsResponse.grants:type_name -> hyapp.wallet.v1.ResourceGrant + 34, // 34: hyapp.wallet.v1.ListResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem + 79, // 35: hyapp.wallet.v1.UpsertResourceShopItemsRequest.items:type_name -> hyapp.wallet.v1.ResourceShopItemInput + 34, // 36: hyapp.wallet.v1.UpsertResourceShopItemsResponse.items:type_name -> hyapp.wallet.v1.ResourceShopItem + 34, // 37: hyapp.wallet.v1.ResourceShopItemResponse.item:type_name -> hyapp.wallet.v1.ResourceShopItem + 34, // 38: hyapp.wallet.v1.PurchaseResourceShopItemResponse.shop_item:type_name -> hyapp.wallet.v1.ResourceShopItem + 35, // 39: hyapp.wallet.v1.PurchaseResourceShopItemResponse.resource:type_name -> hyapp.wallet.v1.UserResourceEntitlement + 6, // 40: hyapp.wallet.v1.PurchaseResourceShopItemResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 88, // 41: hyapp.wallet.v1.ListRechargeBillsResponse.bills:type_name -> hyapp.wallet.v1.RechargeBill + 6, // 42: hyapp.wallet.v1.GetWalletOverviewResponse.balances:type_name -> hyapp.wallet.v1.AssetBalance + 91, // 43: hyapp.wallet.v1.GetWalletOverviewResponse.feature_flags:type_name -> hyapp.wallet.v1.WalletFeatureFlags + 94, // 44: hyapp.wallet.v1.GetWalletValueSummaryResponse.summary:type_name -> hyapp.wallet.v1.WalletValueSummary + 29, // 45: hyapp.wallet.v1.GiftWallItem.resource:type_name -> hyapp.wallet.v1.Resource + 97, // 46: hyapp.wallet.v1.GetUserGiftWallResponse.items:type_name -> hyapp.wallet.v1.GiftWallItem + 100, // 47: hyapp.wallet.v1.ListRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 6, // 48: hyapp.wallet.v1.ConfirmGooglePaymentResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 100, // 49: hyapp.wallet.v1.ListAdminRechargeProductsResponse.products:type_name -> hyapp.wallet.v1.RechargeProduct + 100, // 50: hyapp.wallet.v1.RechargeProductResponse.product:type_name -> hyapp.wallet.v1.RechargeProduct + 112, // 51: hyapp.wallet.v1.GetDiamondExchangeConfigResponse.rules:type_name -> hyapp.wallet.v1.DiamondExchangeRule + 115, // 52: hyapp.wallet.v1.ListWalletTransactionsResponse.transactions:type_name -> hyapp.wallet.v1.WalletTransaction + 118, // 53: hyapp.wallet.v1.VipLevel.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 120, // 54: hyapp.wallet.v1.ListVipPackagesResponse.current_vip:type_name -> hyapp.wallet.v1.UserVip + 119, // 55: hyapp.wallet.v1.ListVipPackagesResponse.packages:type_name -> hyapp.wallet.v1.VipLevel + 120, // 56: hyapp.wallet.v1.GetMyVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 120, // 57: hyapp.wallet.v1.PurchaseVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 118, // 58: hyapp.wallet.v1.PurchaseVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 120, // 59: hyapp.wallet.v1.GrantVipResponse.vip:type_name -> hyapp.wallet.v1.UserVip + 118, // 60: hyapp.wallet.v1.GrantVipResponse.reward_items:type_name -> hyapp.wallet.v1.VipRewardItem + 119, // 61: hyapp.wallet.v1.ListAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 129, // 62: hyapp.wallet.v1.UpdateAdminVipLevelsRequest.levels:type_name -> hyapp.wallet.v1.AdminVipLevelInput + 119, // 63: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel + 6, // 64: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 6, // 65: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 141, // 66: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 140, // 67: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 140, // 68: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 142, // 69: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 141, // 70: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 142, // 71: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 142, // 72: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 142, // 73: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 142, // 74: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 159, // 75: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 159, // 76: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 159, // 77: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 0, // 78: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 3, // 79: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest + 7, // 80: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 11, // 81: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + 14, // 82: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest + 16, // 83: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 18, // 84: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 20, // 85: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 23, // 86: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest + 25, // 87: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest + 27, // 88: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest + 39, // 89: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 41, // 90: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 43, // 91: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 44, // 92: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 45, // 93: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 47, // 94: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 49, // 95: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 51, // 96: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 52, // 97: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 53, // 98: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 55, // 99: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 57, // 100: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 61, // 101: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 62, // 102: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 63, // 103: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 59, // 104: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 65, // 105: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 66, // 106: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 68, // 107: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 70, // 108: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 72, // 109: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest + 74, // 110: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + 77, // 111: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 80, // 112: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 82, // 113: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 84, // 114: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 86, // 115: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 89, // 116: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 92, // 117: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 95, // 118: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 98, // 119: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 101, // 120: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 103, // 121: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 105, // 122: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 107, // 123: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 108, // 124: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 109, // 125: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 113, // 126: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 116, // 127: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 121, // 128: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 123, // 129: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 125, // 130: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 127, // 131: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 130, // 132: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 132, // 133: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 134, // 134: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 136, // 135: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 138, // 136: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 143, // 137: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 145, // 138: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 147, // 139: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 149, // 140: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 151, // 141: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 153, // 142: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 155, // 143: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 157, // 144: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 160, // 145: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 160, // 146: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 160, // 147: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 1, // 148: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 5, // 149: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse + 8, // 150: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 12, // 151: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + 15, // 152: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse + 17, // 153: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 19, // 154: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 21, // 155: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 24, // 156: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse + 26, // 157: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse + 28, // 158: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse + 40, // 159: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 42, // 160: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 46, // 161: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 46, // 162: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 46, // 163: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 48, // 164: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 50, // 165: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 54, // 166: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 54, // 167: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 54, // 168: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 56, // 169: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 58, // 170: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 64, // 171: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 64, // 172: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 64, // 173: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 60, // 174: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 67, // 175: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 67, // 176: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 69, // 177: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 71, // 178: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 73, // 179: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse + 76, // 180: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + 78, // 181: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 81, // 182: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 83, // 183: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 85, // 184: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 87, // 185: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 90, // 186: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 93, // 187: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 96, // 188: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 99, // 189: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 102, // 190: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 104, // 191: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 106, // 192: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 110, // 193: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 110, // 194: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 111, // 195: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 114, // 196: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 117, // 197: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 122, // 198: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 124, // 199: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 126, // 200: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 128, // 201: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 131, // 202: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 133, // 203: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 135, // 204: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 137, // 205: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 139, // 206: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 144, // 207: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 146, // 208: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 148, // 209: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 150, // 210: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 152, // 211: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 154, // 212: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 156, // 213: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 158, // 214: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 145, // [145:215] is the sub-list for method output_type + 75, // [75:145] is the sub-list for method input_type + 75, // [75:75] is the sub-list for extension type_name + 75, // [75:75] is the sub-list for extension extendee + 0, // [0:75] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -15278,15 +15927,15 @@ func file_proto_wallet_v1_wallet_proto_init() { if File_proto_wallet_v1_wallet_proto != nil { return } - file_proto_wallet_v1_wallet_proto_msgTypes[36].OneofWrappers = []any{} - file_proto_wallet_v1_wallet_proto_msgTypes[37].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[43].OneofWrappers = []any{} + file_proto_wallet_v1_wallet_proto_msgTypes[44].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), NumEnums: 0, - NumMessages: 154, + NumMessages: 161, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 07b9154f..7bad52ac 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -15,7 +15,7 @@ message DebitGiftRequest { // price_version 为空时使用当前生效价格;非空时必须命中 active 价格版本。 string price_version = 7; string app_code = 8; - // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性。 + // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性和匹配房间贡献比例。 int64 region_id = 9; // target_is_host 由 gateway 根据 user-service active host profile 注入,客户端不能直接声明。 bool target_is_host = 10; @@ -23,7 +23,7 @@ message DebitGiftRequest { int64 target_host_region_id = 11; // target_agency_owner_user_id 是送礼时主播归属 Agency 的 owner,用于后续代理工资结算。 int64 target_agency_owner_user_id = 12; - // sender_region_id 是送礼用户所属区域,用于匹配礼物入主播周期钻石比例;不能用房间 visible_region_id 替代。 + // sender_region_id 是送礼用户所属区域快照;不能用房间 visible_region_id 替代。 int64 sender_region_id = 13; } @@ -65,6 +65,7 @@ message BatchDebitGiftRequest { int32 gift_count = 5; string price_version = 6; string app_code = 7; + // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性和匹配房间贡献比例。 int64 region_id = 8; int64 sender_region_id = 9; repeated DebitGiftTarget targets = 10; @@ -235,6 +236,70 @@ message TransferCoinFromSellerResponse { int64 recharge_policy_usd_minor_amount = 10; } +// CoinSellerSalaryExchangeRateTier 是用户工资转给币商时,按区域和美元金额命中的金币兑换区间。 +message CoinSellerSalaryExchangeRateTier { + int64 region_id = 1; + int64 min_usd_minor = 2; + int64 max_usd_minor = 3; + int64 coin_per_usd = 4; + string status = 5; + int32 sort_order = 6; + int64 updated_at_ms = 7; +} + +message ListCoinSellerSalaryExchangeRateTiersRequest { + string request_id = 1; + string app_code = 2; + int64 region_id = 3; + bool include_disabled = 4; +} + +message ListCoinSellerSalaryExchangeRateTiersResponse { + repeated CoinSellerSalaryExchangeRateTier tiers = 1; +} + +// ExchangeSalaryToCoinRequest 扣当前用户某个身份工资美元钱包,并按固定比例给同一用户加普通 COIN。 +message ExchangeSalaryToCoinRequest { + string command_id = 1; + int64 user_id = 2; + string salary_asset_type = 3; + int64 salary_usd_minor = 4; + string reason = 5; + string app_code = 6; +} + +message ExchangeSalaryToCoinResponse { + string transaction_id = 1; + int64 salary_balance_after = 2; + int64 coin_balance_after = 3; + int64 salary_usd_minor = 4; + int64 coin_amount = 5; + int64 coin_per_usd = 6; +} + +// TransferSalaryToCoinSellerRequest 扣当前用户某个身份工资美元钱包,并按区域区间比例给同区域币商加专用金币库存。 +message TransferSalaryToCoinSellerRequest { + string command_id = 1; + int64 source_user_id = 2; + int64 seller_user_id = 3; + string salary_asset_type = 4; + int64 salary_usd_minor = 5; + int64 region_id = 6; + string reason = 7; + string app_code = 8; +} + +message TransferSalaryToCoinSellerResponse { + string transaction_id = 1; + int64 source_salary_balance_after = 2; + int64 seller_balance_after = 3; + int64 salary_usd_minor = 4; + int64 coin_amount = 5; + int64 coin_per_usd = 6; + int64 rate_min_usd_minor = 7; + int64 rate_max_usd_minor = 8; +} + // Resource 是资源库里可配置、可赠送、可被礼物引用的最小资源。 message Resource { string app_code = 1; @@ -1502,6 +1567,9 @@ service WalletService { rpc AdminCreditAsset(AdminCreditAssetRequest) returns (AdminCreditAssetResponse); rpc AdminCreditCoinSellerStock(AdminCreditCoinSellerStockRequest) returns (AdminCreditCoinSellerStockResponse); rpc TransferCoinFromSeller(TransferCoinFromSellerRequest) returns (TransferCoinFromSellerResponse); + rpc ListCoinSellerSalaryExchangeRateTiers(ListCoinSellerSalaryExchangeRateTiersRequest) returns (ListCoinSellerSalaryExchangeRateTiersResponse); + rpc ExchangeSalaryToCoin(ExchangeSalaryToCoinRequest) returns (ExchangeSalaryToCoinResponse); + rpc TransferSalaryToCoinSeller(TransferSalaryToCoinSellerRequest) returns (TransferSalaryToCoinSellerResponse); rpc ListResources(ListResourcesRequest) returns (ListResourcesResponse); rpc GetResource(GetResourceRequest) returns (GetResourceResponse); rpc CreateResource(CreateResourceRequest) returns (ResourceResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 7cacab6e..ad9fcccb 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -201,70 +201,73 @@ var WalletCronService_ServiceDesc = grpc.ServiceDesc{ } const ( - WalletService_DebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/DebitGift" - WalletService_BatchDebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchDebitGift" - WalletService_GetBalances_FullMethodName = "/hyapp.wallet.v1.WalletService/GetBalances" - WalletService_GetActiveHostSalaryPolicy_FullMethodName = "/hyapp.wallet.v1.WalletService/GetActiveHostSalaryPolicy" - WalletService_GetHostSalaryProgress_FullMethodName = "/hyapp.wallet.v1.WalletService/GetHostSalaryProgress" - WalletService_AdminCreditAsset_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditAsset" - WalletService_AdminCreditCoinSellerStock_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditCoinSellerStock" - WalletService_TransferCoinFromSeller_FullMethodName = "/hyapp.wallet.v1.WalletService/TransferCoinFromSeller" - WalletService_ListResources_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResources" - WalletService_GetResource_FullMethodName = "/hyapp.wallet.v1.WalletService/GetResource" - WalletService_CreateResource_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateResource" - WalletService_UpdateResource_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateResource" - WalletService_SetResourceStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceStatus" - WalletService_ListResourceGroups_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceGroups" - WalletService_GetResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GetResourceGroup" - WalletService_CreateResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateResourceGroup" - WalletService_UpdateResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateResourceGroup" - WalletService_SetResourceGroupStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceGroupStatus" - WalletService_ListGiftConfigs_FullMethodName = "/hyapp.wallet.v1.WalletService/ListGiftConfigs" - WalletService_ListGiftTypeConfigs_FullMethodName = "/hyapp.wallet.v1.WalletService/ListGiftTypeConfigs" - WalletService_CreateGiftConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateGiftConfig" - WalletService_UpdateGiftConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateGiftConfig" - WalletService_SetGiftConfigStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetGiftConfigStatus" - WalletService_UpsertGiftTypeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpsertGiftTypeConfig" - WalletService_GrantResource_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantResource" - WalletService_GrantResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantResourceGroup" - WalletService_ListUserResources_FullMethodName = "/hyapp.wallet.v1.WalletService/ListUserResources" - WalletService_EquipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/EquipUserResource" - WalletService_UnequipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/UnequipUserResource" - WalletService_BatchGetUserEquippedResources_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchGetUserEquippedResources" - WalletService_ListResourceGrants_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceGrants" - WalletService_ListResourceShopItems_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceShopItems" - WalletService_UpsertResourceShopItems_FullMethodName = "/hyapp.wallet.v1.WalletService/UpsertResourceShopItems" - WalletService_SetResourceShopItemStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceShopItemStatus" - WalletService_PurchaseResourceShopItem_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseResourceShopItem" - WalletService_ListRechargeBills_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRechargeBills" - WalletService_GetWalletOverview_FullMethodName = "/hyapp.wallet.v1.WalletService/GetWalletOverview" - WalletService_GetWalletValueSummary_FullMethodName = "/hyapp.wallet.v1.WalletService/GetWalletValueSummary" - WalletService_GetUserGiftWall_FullMethodName = "/hyapp.wallet.v1.WalletService/GetUserGiftWall" - WalletService_ListRechargeProducts_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRechargeProducts" - WalletService_ConfirmGooglePayment_FullMethodName = "/hyapp.wallet.v1.WalletService/ConfirmGooglePayment" - WalletService_ListAdminRechargeProducts_FullMethodName = "/hyapp.wallet.v1.WalletService/ListAdminRechargeProducts" - WalletService_CreateRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateRechargeProduct" - WalletService_UpdateRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateRechargeProduct" - WalletService_DeleteRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/DeleteRechargeProduct" - WalletService_GetDiamondExchangeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetDiamondExchangeConfig" - WalletService_ListWalletTransactions_FullMethodName = "/hyapp.wallet.v1.WalletService/ListWalletTransactions" - WalletService_ListVipPackages_FullMethodName = "/hyapp.wallet.v1.WalletService/ListVipPackages" - WalletService_GetMyVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GetMyVip" - WalletService_PurchaseVip_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseVip" - WalletService_GrantVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantVip" - WalletService_ListAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/ListAdminVipLevels" - WalletService_UpdateAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateAdminVipLevels" - WalletService_CreditTaskReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditTaskReward" - WalletService_CreditLuckyGiftReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditLuckyGiftReward" - WalletService_ApplyGameCoinChange_FullMethodName = "/hyapp.wallet.v1.WalletService/ApplyGameCoinChange" - WalletService_GetRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRedPacketConfig" - WalletService_UpdateRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateRedPacketConfig" - WalletService_CreateRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateRedPacket" - WalletService_ClaimRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/ClaimRedPacket" - WalletService_ListRedPackets_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRedPackets" - WalletService_GetRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRedPacket" - WalletService_ExpireRedPackets_FullMethodName = "/hyapp.wallet.v1.WalletService/ExpireRedPackets" - WalletService_RetryRedPacketRefund_FullMethodName = "/hyapp.wallet.v1.WalletService/RetryRedPacketRefund" + WalletService_DebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/DebitGift" + WalletService_BatchDebitGift_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchDebitGift" + WalletService_GetBalances_FullMethodName = "/hyapp.wallet.v1.WalletService/GetBalances" + WalletService_GetActiveHostSalaryPolicy_FullMethodName = "/hyapp.wallet.v1.WalletService/GetActiveHostSalaryPolicy" + WalletService_GetHostSalaryProgress_FullMethodName = "/hyapp.wallet.v1.WalletService/GetHostSalaryProgress" + WalletService_AdminCreditAsset_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditAsset" + WalletService_AdminCreditCoinSellerStock_FullMethodName = "/hyapp.wallet.v1.WalletService/AdminCreditCoinSellerStock" + WalletService_TransferCoinFromSeller_FullMethodName = "/hyapp.wallet.v1.WalletService/TransferCoinFromSeller" + WalletService_ListCoinSellerSalaryExchangeRateTiers_FullMethodName = "/hyapp.wallet.v1.WalletService/ListCoinSellerSalaryExchangeRateTiers" + WalletService_ExchangeSalaryToCoin_FullMethodName = "/hyapp.wallet.v1.WalletService/ExchangeSalaryToCoin" + WalletService_TransferSalaryToCoinSeller_FullMethodName = "/hyapp.wallet.v1.WalletService/TransferSalaryToCoinSeller" + WalletService_ListResources_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResources" + WalletService_GetResource_FullMethodName = "/hyapp.wallet.v1.WalletService/GetResource" + WalletService_CreateResource_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateResource" + WalletService_UpdateResource_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateResource" + WalletService_SetResourceStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceStatus" + WalletService_ListResourceGroups_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceGroups" + WalletService_GetResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GetResourceGroup" + WalletService_CreateResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateResourceGroup" + WalletService_UpdateResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateResourceGroup" + WalletService_SetResourceGroupStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceGroupStatus" + WalletService_ListGiftConfigs_FullMethodName = "/hyapp.wallet.v1.WalletService/ListGiftConfigs" + WalletService_ListGiftTypeConfigs_FullMethodName = "/hyapp.wallet.v1.WalletService/ListGiftTypeConfigs" + WalletService_CreateGiftConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateGiftConfig" + WalletService_UpdateGiftConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateGiftConfig" + WalletService_SetGiftConfigStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetGiftConfigStatus" + WalletService_UpsertGiftTypeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpsertGiftTypeConfig" + WalletService_GrantResource_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantResource" + WalletService_GrantResourceGroup_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantResourceGroup" + WalletService_ListUserResources_FullMethodName = "/hyapp.wallet.v1.WalletService/ListUserResources" + WalletService_EquipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/EquipUserResource" + WalletService_UnequipUserResource_FullMethodName = "/hyapp.wallet.v1.WalletService/UnequipUserResource" + WalletService_BatchGetUserEquippedResources_FullMethodName = "/hyapp.wallet.v1.WalletService/BatchGetUserEquippedResources" + WalletService_ListResourceGrants_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceGrants" + WalletService_ListResourceShopItems_FullMethodName = "/hyapp.wallet.v1.WalletService/ListResourceShopItems" + WalletService_UpsertResourceShopItems_FullMethodName = "/hyapp.wallet.v1.WalletService/UpsertResourceShopItems" + WalletService_SetResourceShopItemStatus_FullMethodName = "/hyapp.wallet.v1.WalletService/SetResourceShopItemStatus" + WalletService_PurchaseResourceShopItem_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseResourceShopItem" + WalletService_ListRechargeBills_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRechargeBills" + WalletService_GetWalletOverview_FullMethodName = "/hyapp.wallet.v1.WalletService/GetWalletOverview" + WalletService_GetWalletValueSummary_FullMethodName = "/hyapp.wallet.v1.WalletService/GetWalletValueSummary" + WalletService_GetUserGiftWall_FullMethodName = "/hyapp.wallet.v1.WalletService/GetUserGiftWall" + WalletService_ListRechargeProducts_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRechargeProducts" + WalletService_ConfirmGooglePayment_FullMethodName = "/hyapp.wallet.v1.WalletService/ConfirmGooglePayment" + WalletService_ListAdminRechargeProducts_FullMethodName = "/hyapp.wallet.v1.WalletService/ListAdminRechargeProducts" + WalletService_CreateRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateRechargeProduct" + WalletService_UpdateRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateRechargeProduct" + WalletService_DeleteRechargeProduct_FullMethodName = "/hyapp.wallet.v1.WalletService/DeleteRechargeProduct" + WalletService_GetDiamondExchangeConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetDiamondExchangeConfig" + WalletService_ListWalletTransactions_FullMethodName = "/hyapp.wallet.v1.WalletService/ListWalletTransactions" + WalletService_ListVipPackages_FullMethodName = "/hyapp.wallet.v1.WalletService/ListVipPackages" + WalletService_GetMyVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GetMyVip" + WalletService_PurchaseVip_FullMethodName = "/hyapp.wallet.v1.WalletService/PurchaseVip" + WalletService_GrantVip_FullMethodName = "/hyapp.wallet.v1.WalletService/GrantVip" + WalletService_ListAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/ListAdminVipLevels" + WalletService_UpdateAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateAdminVipLevels" + WalletService_CreditTaskReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditTaskReward" + WalletService_CreditLuckyGiftReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditLuckyGiftReward" + WalletService_ApplyGameCoinChange_FullMethodName = "/hyapp.wallet.v1.WalletService/ApplyGameCoinChange" + WalletService_GetRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRedPacketConfig" + WalletService_UpdateRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateRedPacketConfig" + WalletService_CreateRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/CreateRedPacket" + WalletService_ClaimRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/ClaimRedPacket" + WalletService_ListRedPackets_FullMethodName = "/hyapp.wallet.v1.WalletService/ListRedPackets" + WalletService_GetRedPacket_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRedPacket" + WalletService_ExpireRedPackets_FullMethodName = "/hyapp.wallet.v1.WalletService/ExpireRedPackets" + WalletService_RetryRedPacketRefund_FullMethodName = "/hyapp.wallet.v1.WalletService/RetryRedPacketRefund" ) // WalletServiceClient is the client API for WalletService service. @@ -281,6 +284,9 @@ type WalletServiceClient interface { AdminCreditAsset(ctx context.Context, in *AdminCreditAssetRequest, opts ...grpc.CallOption) (*AdminCreditAssetResponse, error) AdminCreditCoinSellerStock(ctx context.Context, in *AdminCreditCoinSellerStockRequest, opts ...grpc.CallOption) (*AdminCreditCoinSellerStockResponse, error) TransferCoinFromSeller(ctx context.Context, in *TransferCoinFromSellerRequest, opts ...grpc.CallOption) (*TransferCoinFromSellerResponse, error) + ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, in *ListCoinSellerSalaryExchangeRateTiersRequest, opts ...grpc.CallOption) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) + ExchangeSalaryToCoin(ctx context.Context, in *ExchangeSalaryToCoinRequest, opts ...grpc.CallOption) (*ExchangeSalaryToCoinResponse, error) + TransferSalaryToCoinSeller(ctx context.Context, in *TransferSalaryToCoinSellerRequest, opts ...grpc.CallOption) (*TransferSalaryToCoinSellerResponse, error) ListResources(ctx context.Context, in *ListResourcesRequest, opts ...grpc.CallOption) (*ListResourcesResponse, error) GetResource(ctx context.Context, in *GetResourceRequest, opts ...grpc.CallOption) (*GetResourceResponse, error) CreateResource(ctx context.Context, in *CreateResourceRequest, opts ...grpc.CallOption) (*ResourceResponse, error) @@ -427,6 +433,36 @@ func (c *walletServiceClient) TransferCoinFromSeller(ctx context.Context, in *Tr return out, nil } +func (c *walletServiceClient) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, in *ListCoinSellerSalaryExchangeRateTiersRequest, opts ...grpc.CallOption) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListCoinSellerSalaryExchangeRateTiersResponse) + err := c.cc.Invoke(ctx, WalletService_ListCoinSellerSalaryExchangeRateTiers_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) ExchangeSalaryToCoin(ctx context.Context, in *ExchangeSalaryToCoinRequest, opts ...grpc.CallOption) (*ExchangeSalaryToCoinResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ExchangeSalaryToCoinResponse) + err := c.cc.Invoke(ctx, WalletService_ExchangeSalaryToCoin_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *walletServiceClient) TransferSalaryToCoinSeller(ctx context.Context, in *TransferSalaryToCoinSellerRequest, opts ...grpc.CallOption) (*TransferSalaryToCoinSellerResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(TransferSalaryToCoinSellerResponse) + err := c.cc.Invoke(ctx, WalletService_TransferSalaryToCoinSeller_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) ListResources(ctx context.Context, in *ListResourcesRequest, opts ...grpc.CallOption) (*ListResourcesResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListResourcesResponse) @@ -1001,6 +1037,9 @@ type WalletServiceServer interface { AdminCreditAsset(context.Context, *AdminCreditAssetRequest) (*AdminCreditAssetResponse, error) AdminCreditCoinSellerStock(context.Context, *AdminCreditCoinSellerStockRequest) (*AdminCreditCoinSellerStockResponse, error) TransferCoinFromSeller(context.Context, *TransferCoinFromSellerRequest) (*TransferCoinFromSellerResponse, error) + ListCoinSellerSalaryExchangeRateTiers(context.Context, *ListCoinSellerSalaryExchangeRateTiersRequest) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) + ExchangeSalaryToCoin(context.Context, *ExchangeSalaryToCoinRequest) (*ExchangeSalaryToCoinResponse, error) + TransferSalaryToCoinSeller(context.Context, *TransferSalaryToCoinSellerRequest) (*TransferSalaryToCoinSellerResponse, error) ListResources(context.Context, *ListResourcesRequest) (*ListResourcesResponse, error) GetResource(context.Context, *GetResourceRequest) (*GetResourceResponse, error) CreateResource(context.Context, *CreateResourceRequest) (*ResourceResponse, error) @@ -1091,6 +1130,15 @@ func (UnimplementedWalletServiceServer) AdminCreditCoinSellerStock(context.Conte func (UnimplementedWalletServiceServer) TransferCoinFromSeller(context.Context, *TransferCoinFromSellerRequest) (*TransferCoinFromSellerResponse, error) { return nil, status.Error(codes.Unimplemented, "method TransferCoinFromSeller not implemented") } +func (UnimplementedWalletServiceServer) ListCoinSellerSalaryExchangeRateTiers(context.Context, *ListCoinSellerSalaryExchangeRateTiersRequest) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListCoinSellerSalaryExchangeRateTiers not implemented") +} +func (UnimplementedWalletServiceServer) ExchangeSalaryToCoin(context.Context, *ExchangeSalaryToCoinRequest) (*ExchangeSalaryToCoinResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ExchangeSalaryToCoin not implemented") +} +func (UnimplementedWalletServiceServer) TransferSalaryToCoinSeller(context.Context, *TransferSalaryToCoinSellerRequest) (*TransferSalaryToCoinSellerResponse, error) { + return nil, status.Error(codes.Unimplemented, "method TransferSalaryToCoinSeller not implemented") +} func (UnimplementedWalletServiceServer) ListResources(context.Context, *ListResourcesRequest) (*ListResourcesResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListResources not implemented") } @@ -1424,6 +1472,60 @@ func _WalletService_TransferCoinFromSeller_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } +func _WalletService_ListCoinSellerSalaryExchangeRateTiers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCoinSellerSalaryExchangeRateTiersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).ListCoinSellerSalaryExchangeRateTiers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_ListCoinSellerSalaryExchangeRateTiers_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).ListCoinSellerSalaryExchangeRateTiers(ctx, req.(*ListCoinSellerSalaryExchangeRateTiersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_ExchangeSalaryToCoin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExchangeSalaryToCoinRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).ExchangeSalaryToCoin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_ExchangeSalaryToCoin_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).ExchangeSalaryToCoin(ctx, req.(*ExchangeSalaryToCoinRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WalletService_TransferSalaryToCoinSeller_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(TransferSalaryToCoinSellerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).TransferSalaryToCoinSeller(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_TransferSalaryToCoinSeller_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).TransferSalaryToCoinSeller(ctx, req.(*TransferSalaryToCoinSellerRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_ListResources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListResourcesRequest) if err := dec(in); err != nil { @@ -2471,6 +2573,18 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "TransferCoinFromSeller", Handler: _WalletService_TransferCoinFromSeller_Handler, }, + { + MethodName: "ListCoinSellerSalaryExchangeRateTiers", + Handler: _WalletService_ListCoinSellerSalaryExchangeRateTiers_Handler, + }, + { + MethodName: "ExchangeSalaryToCoin", + Handler: _WalletService_ExchangeSalaryToCoin_Handler, + }, + { + MethodName: "TransferSalaryToCoinSeller", + Handler: _WalletService_TransferSalaryToCoinSeller_Handler, + }, { MethodName: "ListResources", Handler: _WalletService_ListResources_Handler, diff --git a/server/admin/internal/modules/giftdiamond/service.go b/server/admin/internal/modules/giftdiamond/service.go index d504dd94..6a21664c 100644 --- a/server/admin/internal/modules/giftdiamond/service.go +++ b/server/admin/internal/modules/giftdiamond/service.go @@ -140,17 +140,17 @@ func (s *Service) ensureSchema(ctx context.Context) error { if _, err := s.db.ExecContext(ctx, ` CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', - region_id BIGINT NOT NULL DEFAULT 0 COMMENT '送礼用户区域,0 表示全局默认', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域,0 表示全局默认', gift_type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码', status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态', - ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '主播周期钻石入账比例,百分比', + ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '房间贡献热度和主播周期钻石入账比例,百分比', created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台用户 ID', 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, region_id, gift_type_code), KEY idx_gift_diamond_ratio_region (app_code, region_id, status) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物入主播周期钻石比例配置表'`); err != nil { + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物钻石和房间贡献比例配置表'`); err != nil { return err } _, err := s.db.ExecContext(ctx, ` diff --git a/server/admin/internal/modules/hostagencypolicy/service.go b/server/admin/internal/modules/hostagencypolicy/service.go index 13cde9bc..e2ad2e13 100644 --- a/server/admin/internal/modules/hostagencypolicy/service.go +++ b/server/admin/internal/modules/hostagencypolicy/service.go @@ -27,7 +27,8 @@ const ( settlementTriggerAutomatic = "automatic" settlementTriggerManual = "manual" - // 礼物金币转主播钻石默认 1:1;月底剩余钻石转美元默认不开启,由后台显式配置。 + // 礼物金币转主播钻石由 gift_diamond_ratio_configs 统一控制;工资政策保留 1:1 快照只用于运行表字段完整。 + // 月底剩余钻石转美元默认不开启,由后台显式配置。 defaultGiftCoinToDiamondRatio = "1" defaultResidualDiamondRate = "0" @@ -304,9 +305,9 @@ func policyModelFromRequest(appCode string, actorID uint, req policyRequest) (mo if req.EffectiveFromMS < 0 || req.EffectiveToMS < 0 || (req.EffectiveToMS > 0 && req.EffectiveToMS <= req.EffectiveFromMS) { return model.HostAgencySalaryPolicy{}, errors.New("政策生效时间不正确") } - // 比例字段用 decimal 字符串入库,避免 float 在金币/钻石/美元换算中产生精度噪声。 - giftRatio := firstNonBlank(req.GiftCoinToDiamondRatio, defaultGiftCoinToDiamondRatio) - giftRatio, _, err := parseFixedDecimal(giftRatio, 6, false, "金币转钻石比例") + // 送礼入主播周期钻石的实际比例已经由“礼物钻石”配置在 wallet 扣礼物时写入周期账户; + // 这里不再接受工资政策单独覆盖,避免同一笔礼物在入账和结算阶段出现两套钻石口径。 + giftRatio, _, err := parseFixedDecimal(defaultGiftCoinToDiamondRatio, 6, false, "金币转钻石比例") if err != nil { return model.HostAgencySalaryPolicy{}, err } diff --git a/server/admin/internal/modules/hostagencypolicy/service_test.go b/server/admin/internal/modules/hostagencypolicy/service_test.go index 67c2ab74..af8b4426 100644 --- a/server/admin/internal/modules/hostagencypolicy/service_test.go +++ b/server/admin/internal/modules/hostagencypolicy/service_test.go @@ -9,7 +9,7 @@ func TestPolicyModelFromRequestNormalizesAndSortsLevels(t *testing.T) { Status: "active", SettlementMode: "half-month", SettlementTriggerMode: "manual", - GiftCoinToDiamondRatio: "1", + GiftCoinToDiamondRatio: "9", ResidualDiamondToUSDRate: "0.000001", Levels: []levelRequest{ {Level: 2, RequiredDiamonds: 700000, HostSalaryUSD: "3", HostCoinReward: 198000, AgencySalaryUSD: "0.8"}, @@ -22,6 +22,7 @@ func TestPolicyModelFromRequestNormalizesAndSortsLevels(t *testing.T) { if item.AppCode != "lalu" || item.CreatedByAdminID != 7 || item.SettlementMode != settlementModeHalfMonth || item.SettlementTriggerMode != settlementTriggerManual { t.Fatalf("policy fields mismatch: %+v", item) } + // 工资政策不能单独改送礼入主播周期钻石的比例;该比例只由礼物钻石配置页控制。 if item.GiftCoinToDiamondRatio != "1.000000" || item.ResidualDiamondToUSDRate != "0.000001000000" { t.Fatalf("ratio fields mismatch: %+v", item) } diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index 8d693f81..bd336947 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -213,6 +213,39 @@ func (h *Handler) CreditCoinSellerStock(c *gin.Context) { response.Created(c, coinSellerStockCreditFromProto(result)) } +func (h *Handler) GetCoinSellerSalaryRates(c *gin.Context) { + regionID, ok := parseInt64ID(c, "region_id") + if !ok { + return + } + items, err := h.service.GetCoinSellerSalaryRates(c.Request.Context(), regionID) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + response.OK(c, gin.H{"regionId": regionID, "tiers": items}) +} + +func (h *Handler) ReplaceCoinSellerSalaryRates(c *gin.Context) { + regionID, ok := parseInt64ID(c, "region_id") + if !ok { + return + } + var req replaceCoinSellerSalaryRatesRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "币商工资兑换比例参数不正确") + return + } + items, err := h.service.ReplaceCoinSellerSalaryRates(c.Request.Context(), adminActorID(c), regionID, req) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + writeHostOrgAuditLog(c, h.audit, "coin-seller-salary-rates", "coin_seller_salary_exchange_rate_tiers", regionID, + fmt.Sprintf("region_id=%d tiers=%d", regionID, len(items))) + response.OK(c, gin.H{"regionId": regionID, "tiers": items}) +} + func (h *Handler) CreateAgency(c *gin.Context) { var req createAgencyRequest if err := c.ShouldBindJSON(&req); err != nil { diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index a0833590..23d7227a 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -37,6 +37,19 @@ type CoinSellerListItem struct { UpdatedAtMs int64 `json:"updatedAtMs"` } +type CoinSellerSalaryRateTier struct { + RegionID int64 `json:"regionId,string"` + MinUSDMinor int64 `json:"minUsdMinor"` + MaxUSDMinor int64 `json:"maxUsdMinor"` + MinUSD string `json:"minUsd"` + MaxUSD string `json:"maxUsd"` + CoinPerUSD int64 `json:"coinPerUsd"` + Status string `json:"status"` + Enabled bool `json:"enabled"` + SortOrder int `json:"sortOrder"` + UpdatedAtMs int64 `json:"updatedAtMs"` +} + // ListBDProfiles 只读 user-service 的 BD 事实表,避免后台列表需求改动 user-service 发布物。 func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role string) ([]*userclient.BDProfile, int64, error) { if r == nil || r.db == nil { @@ -494,6 +507,124 @@ func (r *Reader) UpdateCoinSellerContact(ctx context.Context, userID int64, cont return err } +func (r *Reader) ListCoinSellerSalaryRates(ctx context.Context, regionID int64) ([]CoinSellerSalaryRateTier, error) { + if r == nil || r.walletDB == nil { + return nil, fmt.Errorf("wallet mysql is not configured") + } + if regionID <= 0 { + return nil, fmt.Errorf("region_id is required") + } + if err := r.ensureCoinSellerSalaryRateTable(ctx); err != nil { + return nil, err + } + rows, err := r.walletDB.QueryContext(ctx, ` + SELECT region_id, min_usd_minor, max_usd_minor, coin_per_usd, status, sort_order, updated_at_ms + FROM coin_seller_salary_exchange_rate_tiers + WHERE app_code = ? AND region_id = ? + ORDER BY sort_order ASC, min_usd_minor ASC, tier_id ASC + `, appctx.FromContext(ctx), regionID) + if err != nil { + return nil, err + } + defer rows.Close() + + items := make([]CoinSellerSalaryRateTier, 0) + for rows.Next() { + var item CoinSellerSalaryRateTier + if err := rows.Scan(&item.RegionID, &item.MinUSDMinor, &item.MaxUSDMinor, &item.CoinPerUSD, &item.Status, &item.SortOrder, &item.UpdatedAtMs); err != nil { + return nil, err + } + item.Enabled = item.Status == "active" + item.MinUSD = formatUSDMinor(item.MinUSDMinor) + item.MaxUSD = formatUSDMinor(item.MaxUSDMinor) + items = append(items, item) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +func (r *Reader) ReplaceCoinSellerSalaryRates(ctx context.Context, regionID int64, actorID int64, tiers []CoinSellerSalaryRateTier) ([]CoinSellerSalaryRateTier, error) { + if r == nil || r.walletDB == nil { + return nil, fmt.Errorf("wallet mysql is not configured") + } + if regionID <= 0 { + return nil, fmt.Errorf("region_id is required") + } + if err := r.ensureCoinSellerSalaryRateTable(ctx); err != nil { + return nil, err + } + tx, err := r.walletDB.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer func() { _ = tx.Rollback() }() + + appCode := appctx.FromContext(ctx) + nowMs := time.Now().UnixMilli() + if _, err := tx.ExecContext(ctx, ` + DELETE FROM coin_seller_salary_exchange_rate_tiers + WHERE app_code = ? AND region_id = ? + `, appCode, regionID); err != nil { + return nil, err + } + for index, tier := range tiers { + status := strings.ToLower(strings.TrimSpace(tier.Status)) + if status == "" { + if tier.Enabled { + status = "active" + } else { + status = "disabled" + } + } + if status != "active" && status != "disabled" { + return nil, fmt.Errorf("rate status is invalid") + } + sortOrder := tier.SortOrder + if sortOrder == 0 { + sortOrder = (index + 1) * 10 + } + _, err := tx.ExecContext(ctx, ` + INSERT INTO coin_seller_salary_exchange_rate_tiers ( + app_code, region_id, min_usd_minor, max_usd_minor, coin_per_usd, + status, sort_order, created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, appCode, regionID, tier.MinUSDMinor, tier.MaxUSDMinor, tier.CoinPerUSD, status, sortOrder, actorID, actorID, nowMs, nowMs) + if err != nil { + return nil, err + } + } + if err := tx.Commit(); err != nil { + return nil, err + } + return r.ListCoinSellerSalaryRates(ctx, regionID) +} + +func (r *Reader) ensureCoinSellerSalaryRateTable(ctx context.Context) error { + if _, err := r.walletDB.ExecContext(ctx, ` + CREATE TABLE IF NOT EXISTS coin_seller_salary_exchange_rate_tiers ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + region_id BIGINT NOT NULL COMMENT '币商所属区域 ID', + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '区间 ID', + min_usd_minor BIGINT NOT NULL COMMENT '起始美元金额,单位美分,包含', + max_usd_minor BIGINT NOT NULL COMMENT '结束美元金额,单位美分,包含', + coin_per_usd BIGINT NOT NULL COMMENT '每 1 USD 工资可兑换的币商专用金币数量', + status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '状态:active/disabled', + sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重', + created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID', + updated_by_user_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 (tier_id), + KEY idx_coin_seller_salary_rates_region (app_code, region_id, status, min_usd_minor, max_usd_minor), + KEY idx_coin_seller_salary_rates_sort (app_code, region_id, status, sort_order) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='币商工资兑换比例区间表'`); err != nil { + return err + } + return nil +} + func (r *Reader) ensureCoinSellerContactColumn(ctx context.Context) error { var count int if err := r.db.QueryRowContext(ctx, ` diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index 1220a955..89c01e88 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -55,6 +55,21 @@ type coinSellerStockCreditRequest struct { Reason string `json:"reason"` } +type replaceCoinSellerSalaryRatesRequest struct { + Tiers []coinSellerSalaryRateTierRequest `json:"tiers" binding:"required"` +} + +type coinSellerSalaryRateTierRequest struct { + MinUSD string `json:"minUsd"` + MaxUSD string `json:"maxUsd"` + MinUSDMinor int64 `json:"minUsdMinor"` + MaxUSDMinor int64 `json:"maxUsdMinor"` + CoinPerUSD int64 `json:"coinPerUsd" binding:"required"` + Enabled *bool `json:"enabled"` + Status string `json:"status"` + SortOrder int `json:"sortOrder"` +} + type createAgencyRequest struct { CommandID string `json:"commandId" binding:"required"` OwnerUserID int64 `json:"ownerUserId" binding:"required"` diff --git a/server/admin/internal/modules/hostorg/routes.go b/server/admin/internal/modules/hostorg/routes.go index db50c6aa..82d7a2fb 100644 --- a/server/admin/internal/modules/hostorg/routes.go +++ b/server/admin/internal/modules/hostorg/routes.go @@ -23,4 +23,6 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.POST("/admin/coin-sellers", middleware.RequirePermission("coin-seller:create"), h.CreateCoinSeller) protected.PATCH("/admin/coin-sellers/:user_id/status", middleware.RequirePermission("coin-seller:update"), h.SetCoinSellerStatus) protected.POST("/admin/coin-sellers/:user_id/stock-credits", middleware.RequirePermission("coin-seller:stock-credit"), h.CreditCoinSellerStock) + protected.GET("/admin/coin-seller-salary-rates/:region_id", middleware.RequirePermission("coin-seller:exchange-rate"), h.GetCoinSellerSalaryRates) + protected.PUT("/admin/coin-seller-salary-rates/:region_id", middleware.RequirePermission("coin-seller:exchange-rate"), h.ReplaceCoinSellerSalaryRates) } diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index d33104f3..e9bc87ad 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -55,6 +55,64 @@ func (s *Service) ListCoinSellers(ctx context.Context, query listQuery) ([]*Coin return s.reader.ListCoinSellers(ctx, query) } +func (s *Service) GetCoinSellerSalaryRates(ctx context.Context, regionID int64) ([]CoinSellerSalaryRateTier, error) { + return s.reader.ListCoinSellerSalaryRates(ctx, regionID) +} + +func (s *Service) ReplaceCoinSellerSalaryRates(ctx context.Context, actorID int64, regionID int64, req replaceCoinSellerSalaryRatesRequest) ([]CoinSellerSalaryRateTier, error) { + tiers := make([]CoinSellerSalaryRateTier, 0, len(req.Tiers)) + for index, item := range req.Tiers { + minUSDMinor, err := salaryRateUSDMinor(item.MinUSDMinor, item.MinUSD) + if err != nil { + return nil, fmt.Errorf("min_usd is invalid") + } + maxUSDMinor, err := salaryRateUSDMinor(item.MaxUSDMinor, item.MaxUSD) + if err != nil { + return nil, fmt.Errorf("max_usd is invalid") + } + enabled := item.Status == "active" + if item.Enabled != nil { + enabled = *item.Enabled + } + status := strings.ToLower(strings.TrimSpace(item.Status)) + if status == "" { + if enabled { + status = "active" + } else { + status = "disabled" + } + } + if status != "active" && status != "disabled" { + return nil, fmt.Errorf("status is invalid") + } + if minUSDMinor <= 0 || maxUSDMinor < minUSDMinor { + return nil, fmt.Errorf("usd range is invalid") + } + if item.CoinPerUSD <= 0 || item.CoinPerUSD%100 != 0 { + return nil, fmt.Errorf("coin_per_usd must be a positive multiple of 100") + } + sortOrder := item.SortOrder + if sortOrder == 0 { + sortOrder = (index + 1) * 10 + } + tiers = append(tiers, CoinSellerSalaryRateTier{ + RegionID: regionID, + MinUSDMinor: minUSDMinor, + MaxUSDMinor: maxUSDMinor, + MinUSD: formatUSDMinor(minUSDMinor), + MaxUSD: formatUSDMinor(maxUSDMinor), + CoinPerUSD: item.CoinPerUSD, + Status: status, + Enabled: status == "active", + SortOrder: sortOrder, + }) + } + if err := validateCoinSellerSalaryRateTiers(tiers); err != nil { + return nil, err + } + return s.reader.ReplaceCoinSellerSalaryRates(ctx, regionID, actorID, tiers) +} + func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID string, req createBDLeaderRequest) (*userclient.BDProfile, error) { targetUserID, err := s.resolveDisplayUserID(ctx, requestID, req.TargetUserID) if err != nil { @@ -326,6 +384,68 @@ func parseUSDTAmountMicro(raw string) (int64, error) { return amount, nil } +func salaryRateUSDMinor(minor int64, raw string) (int64, error) { + if minor > 0 { + return minor, nil + } + raw = strings.TrimSpace(raw) + if raw == "" { + return 0, fmt.Errorf("usd amount is required") + } + parts := strings.Split(raw, ".") + if len(parts) > 2 || parts[0] == "" { + return 0, fmt.Errorf("usd amount is invalid") + } + digits := parts[0] + fraction := "" + if len(parts) == 2 { + fraction = parts[1] + if len(fraction) > 2 { + return 0, fmt.Errorf("usd amount supports up to 2 decimals") + } + } + digits += fraction + strings.Repeat("0", 2-len(fraction)) + var amount int64 + const maxInt64 = int64(^uint64(0) >> 1) + for _, char := range digits { + if char < '0' || char > '9' { + return 0, fmt.Errorf("usd amount is invalid") + } + next := int64(char - '0') + if amount > (maxInt64-next)/10 { + return 0, fmt.Errorf("usd amount is too large") + } + amount = amount*10 + next + } + return amount, nil +} + +func validateCoinSellerSalaryRateTiers(tiers []CoinSellerSalaryRateTier) error { + active := make([]CoinSellerSalaryRateTier, 0, len(tiers)) + for _, tier := range tiers { + if tier.Status == "active" { + active = append(active, tier) + } + } + for i := 0; i < len(active); i++ { + for j := i + 1; j < len(active); j++ { + if active[i].MinUSDMinor <= active[j].MaxUSDMinor && active[j].MinUSDMinor <= active[i].MaxUSDMinor { + return fmt.Errorf("active usd ranges must not overlap") + } + } + } + return nil +} + +func formatUSDMinor(value int64) string { + sign := "" + if value < 0 { + sign = "-" + value = -value + } + return fmt.Sprintf("%s%d.%02d", sign, value/100, value%100) +} + func normalizeListQuery(query listQuery) listQuery { if query.Page < 1 { query.Page = 1 diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 0634986a..877c122b 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -84,6 +84,7 @@ var defaultPermissions = []model.Permission{ {Name: "币商创建", Code: "coin-seller:create", Kind: "button"}, {Name: "币商更新", Code: "coin-seller:update", Kind: "button"}, {Name: "币商进货", Code: "coin-seller:stock-credit", Kind: "button"}, + {Name: "币商工资兑换比例", Code: "coin-seller:exchange-rate", Kind: "button"}, {Name: "金币流水查看", Code: "coin-ledger:view", Kind: "menu"}, {Name: "金币增减查看", Code: "coin-adjustment:view", Kind: "menu"}, {Name: "金币增减创建", Code: "coin-adjustment:create", Kind: "button"}, @@ -499,7 +500,7 @@ func defaultRolePermissionCodes(code string) []string { "host:view", "host-agency-policy:view", "host-agency-policy:create", "host-agency-policy:update", "host-agency-policy:delete", "host-agency-policy:publish", "team-salary-policy:view", "team-salary-policy:create", "team-salary-policy:update", "team-salary-policy:delete", "host-salary-settlement:view", "host-salary-settlement:settle", "agency:view", "agency:create", "agency:status", "bd:view", "bd:create", "bd:update", - "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", + "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", "coin-seller:exchange-rate", "coin-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", "lucky-gift:view", "lucky-gift:update", "game:view", "game:create", "game:update", "game:status", "game:delete", @@ -587,7 +588,7 @@ func defaultRolePermissionMigrationCodes(code string) []string { "country:view", "country:create", "country:update", "country:status", "region:view", "region:create", "region:update", "region:status", "host-agency-policy:view", "host-agency-policy:create", "host-agency-policy:update", "host-agency-policy:delete", "host-agency-policy:publish", "team-salary-policy:view", "team-salary-policy:create", "team-salary-policy:update", "team-salary-policy:delete", "host-salary-settlement:view", "host-salary-settlement:settle", - "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", + "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", "coin-seller:exchange-rate", "coin-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", "lucky-gift:view", "lucky-gift:update", "game:view", "game:create", "game:update", "game:status", "game:delete", diff --git a/services/gateway-service/internal/client/user_client.go b/services/gateway-service/internal/client/user_client.go index c1d14479..3103c9e7 100644 --- a/services/gateway-service/internal/client/user_client.go +++ b/services/gateway-service/internal/client/user_client.go @@ -73,6 +73,7 @@ type UserHostClient interface { InviteBD(ctx context.Context, req *userv1.InviteBDRequest) (*userv1.InviteBDResponse, error) ListBDLeaderBDs(ctx context.Context, req *userv1.ListBDLeaderBDsRequest) (*userv1.ListBDLeaderBDsResponse, error) ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLeaderAgenciesRequest) (*userv1.ListBDLeaderAgenciesResponse, error) + ListBDAgencies(ctx context.Context, req *userv1.ListBDAgenciesRequest) (*userv1.ListBDAgenciesResponse, error) GetHostProfile(ctx context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) GetBDProfile(ctx context.Context, req *userv1.GetBDProfileRequest) (*userv1.GetBDProfileResponse, error) GetCoinSellerProfile(ctx context.Context, req *userv1.GetCoinSellerProfileRequest) (*userv1.GetCoinSellerProfileResponse, error) @@ -335,6 +336,10 @@ func (c *grpcUserHostClient) ListBDLeaderAgencies(ctx context.Context, req *user return c.client.ListBDLeaderAgencies(ctx, req) } +func (c *grpcUserHostClient) ListBDAgencies(ctx context.Context, req *userv1.ListBDAgenciesRequest) (*userv1.ListBDAgenciesResponse, error) { + return c.client.ListBDAgencies(ctx, req) +} + func (c *grpcUserHostClient) GetHostProfile(ctx context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) { return c.client.GetHostProfile(ctx, req) } diff --git a/services/gateway-service/internal/client/wallet_client.go b/services/gateway-service/internal/client/wallet_client.go index e864bc8a..059e42f6 100644 --- a/services/gateway-service/internal/client/wallet_client.go +++ b/services/gateway-service/internal/client/wallet_client.go @@ -24,6 +24,9 @@ type WalletClient interface { GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) TransferCoinFromSeller(ctx context.Context, req *walletv1.TransferCoinFromSellerRequest) (*walletv1.TransferCoinFromSellerResponse, error) + ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, req *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest) (*walletv1.ListCoinSellerSalaryExchangeRateTiersResponse, error) + ExchangeSalaryToCoin(ctx context.Context, req *walletv1.ExchangeSalaryToCoinRequest) (*walletv1.ExchangeSalaryToCoinResponse, error) + TransferSalaryToCoinSeller(ctx context.Context, req *walletv1.TransferSalaryToCoinSellerRequest) (*walletv1.TransferSalaryToCoinSellerResponse, error) ListResources(ctx context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) GetResource(ctx context.Context, req *walletv1.GetResourceRequest) (*walletv1.GetResourceResponse, error) GetResourceGroup(ctx context.Context, req *walletv1.GetResourceGroupRequest) (*walletv1.GetResourceGroupResponse, error) @@ -108,6 +111,18 @@ func (c *grpcWalletClient) TransferCoinFromSeller(ctx context.Context, req *wall return c.client.TransferCoinFromSeller(ctx, req) } +func (c *grpcWalletClient) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, req *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest) (*walletv1.ListCoinSellerSalaryExchangeRateTiersResponse, error) { + return c.client.ListCoinSellerSalaryExchangeRateTiers(ctx, req) +} + +func (c *grpcWalletClient) ExchangeSalaryToCoin(ctx context.Context, req *walletv1.ExchangeSalaryToCoinRequest) (*walletv1.ExchangeSalaryToCoinResponse, error) { + return c.client.ExchangeSalaryToCoin(ctx, req) +} + +func (c *grpcWalletClient) TransferSalaryToCoinSeller(ctx context.Context, req *walletv1.TransferSalaryToCoinSellerRequest) (*walletv1.TransferSalaryToCoinSellerResponse, error) { + return c.client.TransferSalaryToCoinSeller(ctx, req) +} + func (c *grpcWalletClient) ListResources(ctx context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) { return c.client.ListResources(ctx, req) } diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 68447200..e6efa71b 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -84,6 +84,9 @@ type UserHandlers struct { ListBDLeaderCenterAgencies http.HandlerFunc InviteBDLeaderBD http.HandlerFunc InviteBDLeaderAgency http.HandlerFunc + GetBDCenterOverview http.HandlerFunc + ListBDCenterAgencies http.HandlerFunc + InviteBDAgency http.HandlerFunc CompleteMyOnboarding http.HandlerFunc UpdateMyProfile http.HandlerFunc ChangeMyCountry http.HandlerFunc @@ -187,6 +190,10 @@ type WalletHandlers struct { ListWalletTransactions http.HandlerFunc ListCoinSellers http.HandlerFunc TransferCoinFromSeller http.HandlerFunc + GetSalaryWalletOverview http.HandlerFunc + SearchSalaryWalletSeller http.HandlerFunc + ExchangeSalaryToCoin http.HandlerFunc + TransferSalaryToSeller http.HandlerFunc GetRedPacketConfig http.HandlerFunc ListRoomRedPackets http.HandlerFunc CreateRoomRedPacket http.HandlerFunc @@ -320,6 +327,9 @@ func (r routes) registerUserRoutes() { r.profile("/bd-leader-center/agencies", http.MethodGet, h.ListBDLeaderCenterAgencies) r.profile("/bd-leader/invitations/bd", http.MethodPost, h.InviteBDLeaderBD) r.profile("/bd-leader/invitations/agency", http.MethodPost, h.InviteBDLeaderAgency) + r.profile("/bd-center/overview", http.MethodGet, h.GetBDCenterOverview) + r.profile("/bd-center/agencies", http.MethodGet, h.ListBDCenterAgencies) + r.profile("/bd/invitations/agency", http.MethodPost, h.InviteBDAgency) r.auth("/users/me/onboarding/complete", "", h.CompleteMyOnboarding) r.profile("/users/me/profile/update", "", h.UpdateMyProfile) r.profile("/users/me/country/change", "", h.ChangeMyCountry) @@ -431,6 +441,10 @@ func (r routes) registerWalletRoutes() { r.profile("/wallet/transactions", http.MethodGet, h.ListWalletTransactions) r.profile("/wallet/coin-sellers", http.MethodGet, h.ListCoinSellers) r.profile("/wallet/coin-seller/transfer", "", h.TransferCoinFromSeller) + r.profile("/salary-wallet/overview", http.MethodGet, h.GetSalaryWalletOverview) + r.profile("/salary-wallet/coin-sellers/search", http.MethodGet, h.SearchSalaryWalletSeller) + r.profile("/salary-wallet/exchange", http.MethodPost, h.ExchangeSalaryToCoin) + r.profile("/salary-wallet/transfer-to-coin-seller", http.MethodPost, h.TransferSalaryToSeller) r.profile("/red-packets/config", http.MethodGet, h.GetRedPacketConfig) r.profile("/rooms/{room_id}/red-packets", http.MethodGet, h.ListRoomRedPackets) r.profile("/rooms/{room_id}/red-packets/create", http.MethodPost, h.CreateRoomRedPacket) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index ecbcf971..7295e608 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -407,6 +407,9 @@ type fakeUserHostClient struct { lastLeaderAgencies *userv1.ListBDLeaderAgenciesRequest leaderAgenciesResp *userv1.ListBDLeaderAgenciesResponse leaderAgenciesErr error + lastBDAgencies *userv1.ListBDAgenciesRequest + bdAgenciesResp *userv1.ListBDAgenciesResponse + bdAgenciesErr error last *userv1.GetCoinSellerProfileRequest profile *userv1.CoinSellerProfile err error @@ -480,6 +483,14 @@ type fakeWalletClient struct { lastTransfer *walletv1.TransferCoinFromSellerRequest transferResp *walletv1.TransferCoinFromSellerResponse transferErr error + lastListExchangeTiers *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest + listExchangeTiersResp *walletv1.ListCoinSellerSalaryExchangeRateTiersResponse + lastExchangeSalary *walletv1.ExchangeSalaryToCoinRequest + exchangeSalaryResp *walletv1.ExchangeSalaryToCoinResponse + exchangeSalaryErr error + lastTransferSalary *walletv1.TransferSalaryToCoinSellerRequest + transferSalaryResp *walletv1.TransferSalaryToCoinSellerResponse + transferSalaryErr error lastListResources *walletv1.ListResourcesRequest listResourcesResp *walletv1.ListResourcesResponse lastGetResource *walletv1.GetResourceRequest @@ -1138,6 +1149,17 @@ func (f *fakeUserHostClient) ListBDLeaderAgencies(_ context.Context, req *userv1 return &userv1.ListBDLeaderAgenciesResponse{}, nil } +func (f *fakeUserHostClient) ListBDAgencies(_ context.Context, req *userv1.ListBDAgenciesRequest) (*userv1.ListBDAgenciesResponse, error) { + f.lastBDAgencies = req + if f.bdAgenciesErr != nil { + return nil, f.bdAgenciesErr + } + if f.bdAgenciesResp != nil { + return f.bdAgenciesResp, nil + } + return &userv1.ListBDAgenciesResponse{}, nil +} + func (f *fakeUserHostClient) GetHostProfile(_ context.Context, req *userv1.GetHostProfileRequest) (*userv1.GetHostProfileResponse, error) { f.lastHost = req if f.hostErr != nil { @@ -1449,6 +1471,39 @@ func (f *fakeWalletClient) TransferCoinFromSeller(_ context.Context, req *wallet return &walletv1.TransferCoinFromSellerResponse{}, nil } +func (f *fakeWalletClient) ListCoinSellerSalaryExchangeRateTiers(_ context.Context, req *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest) (*walletv1.ListCoinSellerSalaryExchangeRateTiersResponse, error) { + f.lastListExchangeTiers = req + if f.err != nil { + return nil, f.err + } + if f.listExchangeTiersResp != nil { + return f.listExchangeTiersResp, nil + } + return &walletv1.ListCoinSellerSalaryExchangeRateTiersResponse{}, nil +} + +func (f *fakeWalletClient) ExchangeSalaryToCoin(_ context.Context, req *walletv1.ExchangeSalaryToCoinRequest) (*walletv1.ExchangeSalaryToCoinResponse, error) { + f.lastExchangeSalary = req + if f.exchangeSalaryErr != nil { + return nil, f.exchangeSalaryErr + } + if f.exchangeSalaryResp != nil { + return f.exchangeSalaryResp, nil + } + return &walletv1.ExchangeSalaryToCoinResponse{}, nil +} + +func (f *fakeWalletClient) TransferSalaryToCoinSeller(_ context.Context, req *walletv1.TransferSalaryToCoinSellerRequest) (*walletv1.TransferSalaryToCoinSellerResponse, error) { + f.lastTransferSalary = req + if f.transferSalaryErr != nil { + return nil, f.transferSalaryErr + } + if f.transferSalaryResp != nil { + return f.transferSalaryResp, nil + } + return &walletv1.TransferSalaryToCoinSellerResponse{}, nil +} + func (f *fakeWalletClient) ListResources(_ context.Context, req *walletv1.ListResourcesRequest) (*walletv1.ListResourcesResponse, error) { f.lastListResources = req if f.err != nil { @@ -3579,6 +3634,94 @@ func TestAgencyCenterOverviewUsesOwnerAgencySalaryAndPendingApplications(t *test } } +func TestBDCenterOverviewUsesBDSalaryAndDirectAgencies(t *testing.T) { + hostClient := &fakeUserHostClient{ + bdProfile: &userv1.BDProfile{UserId: 42, Role: "bd", Status: "active", RegionId: 1001}, + bdAgenciesResp: &userv1.ListBDAgenciesResponse{Agencies: []*userv1.Agency{ + {AgencyId: 7001, OwnerUserId: 99, ParentBdUserId: 42, Name: "Yumi Star Agency", Status: "active"}, + }}, + } + walletClient := &fakeWalletClient{balancesByUserID: map[int64]*walletv1.GetBalancesResponse{ + 42: {Balances: []*walletv1.AssetBalance{{AssetType: "BD_SALARY_USD", AvailableAmount: 4862080}}}, + }} + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 42: {UserId: 42, DisplayUserId: "163008", Username: "BD_Jasmine", Avatar: "https://cdn.example/bd.png"}, + }} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetUserHostClient(hostClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/bd-center/overview", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-bd-center-overview") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastBD == nil || hostClient.lastBD.GetUserId() != 42 || hostClient.lastBDAgencies == nil || hostClient.lastBDAgencies.GetBdUserId() != 42 { + t.Fatalf("bd center requests mismatch: profile=%+v agencies=%+v", hostClient.lastBD, hostClient.lastBDAgencies) + } + if walletClient.last == nil || walletClient.last.GetUserId() != 42 || len(walletClient.last.GetAssetTypes()) != 1 || walletClient.last.GetAssetTypes()[0] != "BD_SALARY_USD" { + t.Fatalf("bd salary request mismatch: %+v", walletClient.last) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + profile := data["profile"].(map[string]any) + salary := data["salary"].(map[string]any) + overview := data["overview"].(map[string]any) + if profile["display_user_id"] != "163008" || salary["asset_type"] != "BD_SALARY_USD" || salary["display_amount"] != 48620.8 || overview["total_agency"] != float64(1) { + t.Fatalf("bd center overview response mismatch: %+v", data) + } +} + +func TestBDCenterInviteAgencyDirectlyForwardsInviteAgency(t *testing.T) { + hostClient := &fakeUserHostClient{ + bdProfile: &userv1.BDProfile{UserId: 42, Role: "bd", Status: "active", RegionId: 1001}, + inviteAgencyResp: &userv1.InviteAgencyResponse{Invitation: &userv1.RoleInvitation{ + InvitationId: 9001, + CommandId: "cmd-bd-invite-agency", + InvitationType: "agency", + Status: "accepted", + InviterUserId: 42, + TargetUserId: 99, + AgencyName: "Target Agency", + }}, + } + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 99: {UserId: 99, DisplayUserId: "163099", Username: "Target Agency"}, + }} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetUserHostClient(hostClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodPost, "/api/v1/bd/invitations/agency", bytes.NewReader([]byte(`{"command_id":"cmd-bd-invite-agency","target_user_id":"99"}`))) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastInviteAgency == nil || hostClient.lastInviteAgency.GetInviterUserId() != 42 || hostClient.lastInviteAgency.GetTargetUserId() != 99 || hostClient.lastInviteAgency.GetAgencyName() != "Target Agency" { + t.Fatalf("bd invite agency request mismatch: %+v", hostClient.lastInviteAgency) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + invitation := data["invitation"].(map[string]any) + if invitation["status"] != "accepted" || invitation["target_user_id"] != "99" { + t.Fatalf("bd invite response mismatch: %+v", data) + } +} + func TestAgencyCenterOverviewRejectsNonOwner(t *testing.T) { hostClient := &fakeUserHostClient{roleSummary: &userv1.UserRoleSummary{UserId: 42, IsManager: false, AgencyId: 7001}} handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) @@ -5260,6 +5403,63 @@ func TestListCoinTransactionsForcesCoinAndDefaultsPageSize30(t *testing.T) { } } +func TestListWalletTransactionsIncludesCounterpartyProfile(t *testing.T) { + walletClient := &fakeWalletClient{transactionsResp: &walletv1.ListWalletTransactionsResponse{ + Total: 1, + Transactions: []*walletv1.WalletTransaction{{ + EntryId: 9, + TransactionId: "wtx-seller-1", + BizType: "coin_seller_transfer", + AssetType: "COIN_SELLER_COIN", + AvailableDelta: -10_000, + AvailableAfter: 1_011, + CounterpartyUserId: 9001, + CreatedAtMs: 1_780_000_000_000, + }}, + }} + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 9001: { + UserId: 9001, + DisplayUserId: "163001", + Username: "Alice", + Avatar: "https://cdn.example/alice.png", + AppCode: "lalu", + }, + }} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, profileClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/wallet/transactions?asset_type=COIN_SELLER_COIN&page_size=20", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-wallet-ledger") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if walletClient.lastTransactions == nil || walletClient.lastTransactions.GetAssetType() != "COIN_SELLER_COIN" || walletClient.lastTransactions.GetPageSize() != 20 { + t.Fatalf("wallet transaction request mismatch: %+v", walletClient.lastTransactions) + } + if profileClient.lastBatch == nil || len(profileClient.lastBatch.GetUserIds()) != 1 || profileClient.lastBatch.GetUserIds()[0] != 9001 { + t.Fatalf("counterparty profile batch mismatch: %+v", profileClient.lastBatch) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data, ok := response.Data.(map[string]any) + items, itemsOK := data["items"].([]any) + if response.Code != httpkit.CodeOK || !ok || !itemsOK || len(items) != 1 { + t.Fatalf("wallet transaction response mismatch: %+v", response) + } + first, ok := items[0].(map[string]any) + if !ok || first["counterparty_display_user_id"] != "163001" || first["counterparty_username"] != "Alice" || first["counterparty_avatar"] != "https://cdn.example/alice.png" { + t.Fatalf("counterparty profile fields mismatch: %+v", first) + } +} + func TestListRechargeProductsUsesProfileRegionAndPlatform(t *testing.T) { walletClient := &fakeWalletClient{rechargeProductsResp: &walletv1.ListRechargeProductsResponse{ Channels: []string{"google"}, @@ -5447,6 +5647,90 @@ func TestCoinSellerTransferChecksIdentityAndPropagatesWalletCommand(t *testing.T } } +func TestCoinSellerTransferAllowsSelfTargetAndSkipsDuplicateRegionLookup(t *testing.T) { + walletClient := &fakeWalletClient{transferResp: &walletv1.TransferCoinFromSellerResponse{ + TransactionId: "wtx-coin-seller-self", + SellerBalanceAfter: 1010, + TargetBalanceAfter: 1, + Amount: 1, + }} + hostClient := &fakeUserHostClient{profile: &userv1.CoinSellerProfile{ + UserId: 42, + Status: "active", + MerchantAssetType: "COIN_SELLER_COIN", + }} + identityClient := &fakeUserIdentityClient{resolveByDisplay: map[string]int64{"163000": 42}} + profileClient := &fakeUserProfileClient{regionByUserID: map[int64]int64{42: 688}} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, identityClient, profileClient) + handler.SetWalletClient(walletClient) + handler.SetUserHostClient(hostClient) + router := handler.Routes(auth.NewVerifier("secret")) + body := []byte(`{"command_id":"cmd-seller-self","target_display_user_id":"163000","amount":1,"reason":"self recharge"}`) + request := httptest.NewRequest(http.MethodPost, "/api/v1/wallet/coin-seller/transfer", bytes.NewReader(body)) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if walletClient.lastTransfer == nil || + walletClient.lastTransfer.GetSellerUserId() != 42 || + walletClient.lastTransfer.GetTargetUserId() != 42 || + walletClient.lastTransfer.GetSellerRegionId() != 688 || + walletClient.lastTransfer.GetTargetRegionId() != 688 || + walletClient.lastTransfer.GetAmount() != 1 { + t.Fatalf("self wallet transfer request mismatch: %+v", walletClient.lastTransfer) + } + if len(profileClient.getRequests) != 1 || profileClient.getRequests[0].GetUserId() != 42 { + t.Fatalf("self transfer should only lookup seller profile once: %+v", profileClient.getRequests) + } +} + +func TestResolveDisplayUserIDIncludesProfileForH5Lookup(t *testing.T) { + identityClient := &fakeUserIdentityClient{resolveByDisplay: map[string]int64{"163000": 42}} + profileClient := &fakeUserProfileClient{usersByID: map[int64]*userv1.User{ + 42: { + UserId: 42, + DisplayUserId: "163000", + Username: "xcxcxcxc", + Avatar: "https://cdn.example/avatar.png", + RegionId: 688, + Status: userv1.UserStatus_USER_STATUS_ACTIVE, + }, + }} + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, identityClient, profileClient) + if handler.userProfileClient == nil { + t.Fatal("profile client was not attached to gateway handler") + } + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/users/by-display-user-id/163000", nil) + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if identityClient.lastResolve == nil || identityClient.lastResolve.GetDisplayUserId() != "163000" { + t.Fatalf("resolve request mismatch: %+v", identityClient.lastResolve) + } + if profileClient.lastGet == nil || profileClient.lastGet.GetUserId() != 42 { + t.Fatalf("profile lookup mismatch: %+v", profileClient.lastGet) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + profile := data["profile"].(map[string]any) + identity := data["identity"].(map[string]any) + if data["display_user_id"] != "163000" || identity["display_user_id"] != "163000" || profile["username"] != "xcxcxcxc" || profile["avatar"] != "https://cdn.example/avatar.png" { + t.Fatalf("resolve display user response mismatch: %+v", data) + } +} + func TestCoinSellerTransferRejectsCrossRegionBeforeWallet(t *testing.T) { walletClient := &fakeWalletClient{} hostClient := &fakeUserHostClient{profile: &userv1.CoinSellerProfile{ diff --git a/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go b/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go index 460dbddc..6904e2ea 100644 --- a/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/bd_leader_center_handler.go @@ -12,6 +12,7 @@ import ( const ( adminSalaryAssetType = "ADMIN_SALARY_USD" + bdSalaryAssetType = "BD_SALARY_USD" bdStatusActive = "active" ) @@ -79,6 +80,49 @@ func (h *Handler) getBDLeaderCenterOverview(writer http.ResponseWriter, request }) } +func (h *Handler) getBDCenterOverview(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + profile, ok := h.resolveActiveBD(writer, request, userID) + if !ok { + return + } + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + users, err := h.userProfiles(request, []int64{userID}) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + // BD Center 的钱包只读取 BD 自己的工资资产,避免沿用 BD Leader 后台工资资产。 + salary, err := h.salaryBalance(request, userID, bdSalaryAssetType) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + agencyResp, err := h.userHostClient.ListBDAgencies(request.Context(), &userv1.ListBDAgenciesRequest{ + Meta: httpkit.UserMeta(request, ""), + BdUserId: userID, + Status: agencyStatusActive, + PageSize: 100, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + httpkit.WriteOK(writer, request, map[string]any{ + "profile": users[userID], + "bd_profile": bdLeaderProfileFromProto(profile), + "salary": salary, + "overview": map[string]any{ + "total_agency": len(agencyResp.GetAgencies()), + }, + }) +} + func (h *Handler) listBDLeaderCenterBDs(writer http.ResponseWriter, request *http.Request) { userID := auth.UserIDFromContext(request.Context()) if _, ok := h.resolveActiveBDLeader(writer, request, userID); !ok { @@ -188,6 +232,57 @@ func (h *Handler) listBDLeaderCenterAgencies(writer http.ResponseWriter, request httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": len(items)}) } +func (h *Handler) listBDCenterAgencies(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + if _, ok := h.resolveActiveBD(writer, request, userID); !ok { + return + } + pageSize := queryPageSize(request, 20) + resp, err := h.userHostClient.ListBDAgencies(request.Context(), &userv1.ListBDAgenciesRequest{ + Meta: httpkit.UserMeta(request, ""), + BdUserId: userID, + Status: agencyStatusActive, + PageSize: int32(pageSize), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + userIDs := make([]int64, 0, len(resp.GetAgencies())+1) + userIDs = append(userIDs, userID) + for _, agency := range resp.GetAgencies() { + userIDs = append(userIDs, agency.GetOwnerUserId()) + } + users, err := h.userProfiles(request, userIDs) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + items := make([]map[string]any, 0, len(resp.GetAgencies())) + for _, agency := range resp.GetAgencies() { + // Host count is derived from active membership rows so the H5 list reflects current agency size. + membersResp, err := h.userHostClient.GetAgencyMembers(request.Context(), &userv1.GetAgencyMembersRequest{ + Meta: httpkit.UserMeta(request, ""), + AgencyId: agency.GetAgencyId(), + Status: membershipStatusActive, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + items = append(items, map[string]any{ + "agency": hostAgencyFromProto(agency), + "owner": users[agency.GetOwnerUserId()], + "parent_bd": users[userID], + "host_count": len(membersResp.GetMemberships()), + "created_at_ms": agency.GetCreatedAtMs(), + }) + } + httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": len(items)}) +} + func (h *Handler) inviteBDLeaderBD(writer http.ResponseWriter, request *http.Request) { h.inviteBDLeaderRole(writer, request, "bd") } @@ -251,6 +346,47 @@ func (h *Handler) inviteBDLeaderRole(writer http.ResponseWriter, request *http.R httpkit.WriteOK(writer, request, map[string]any{"invitation": roleInvitationData(resp.GetInvitation())}) } +func (h *Handler) inviteBDAgency(writer http.ResponseWriter, request *http.Request) { + userID := auth.UserIDFromContext(request.Context()) + if _, ok := h.resolveActiveBD(writer, request, userID); !ok { + return + } + var body map[string]any + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := stringJSONValue(body["command_id"]) + targetUserID := int64JSONValue(body["target_user_id"]) + if commandID == "" || targetUserID <= 0 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + + agencyName := stringJSONValue(body["agency_name"]) + if agencyName == "" { + users, err := h.userProfiles(request, []int64{targetUserID}) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + target := users[targetUserID] + agencyName = firstBDLeaderNonBlank(target.Username, target.DisplayUserID, int64String(targetUserID)) + } + // InviteAgency is already a direct-accept transaction in user-service, so this HTTP endpoint does not create a pending approval step. + resp, err := h.userHostClient.InviteAgency(request.Context(), &userv1.InviteAgencyRequest{ + Meta: httpkit.UserMeta(request, ""), + CommandId: commandID, + InviterUserId: userID, + TargetUserId: targetUserID, + AgencyName: agencyName, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{"invitation": roleInvitationData(resp.GetInvitation())}) +} + func (h *Handler) resolveActiveBDLeader(writer http.ResponseWriter, request *http.Request, userID int64) (*userv1.BDProfile, bool) { if h.userHostClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") @@ -272,6 +408,27 @@ func (h *Handler) resolveActiveBDLeader(writer http.ResponseWriter, request *htt return profile, true } +func (h *Handler) resolveActiveBD(writer http.ResponseWriter, request *http.Request, userID int64) (*userv1.BDProfile, bool) { + if h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return nil, false + } + resp, err := h.userHostClient.GetBDProfile(request.Context(), &userv1.GetBDProfileRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return nil, false + } + profile := resp.GetBdProfile() + if profile == nil || profile.GetStatus() != bdStatusActive || (profile.GetRole() != "bd" && profile.GetRole() != "bd_leader") { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return nil, false + } + return profile, true +} + func bdLeaderProfileFromProto(profile *userv1.BDProfile) bdLeaderProfileData { if profile == nil { return bdLeaderProfileData{} diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index a94dcdd9..b97dd841 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -68,6 +68,9 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { ListBDLeaderCenterAgencies: h.listBDLeaderCenterAgencies, InviteBDLeaderBD: h.inviteBDLeaderBD, InviteBDLeaderAgency: h.inviteBDLeaderAgency, + GetBDCenterOverview: h.getBDCenterOverview, + ListBDCenterAgencies: h.listBDCenterAgencies, + InviteBDAgency: h.inviteBDAgency, CompleteMyOnboarding: h.completeMyOnboarding, UpdateMyProfile: h.updateMyProfile, ChangeMyCountry: h.changeMyCountry, diff --git a/services/gateway-service/internal/transport/http/userapi/user_handler.go b/services/gateway-service/internal/transport/http/userapi/user_handler.go index 2c65545e..35265e4c 100644 --- a/services/gateway-service/internal/transport/http/userapi/user_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/user_handler.go @@ -25,6 +25,12 @@ type userIdentityData struct { LeaseID string `json:"lease_id,omitempty"` } +type resolveDisplayUserData struct { + userIdentityData + Identity userIdentityData `json:"identity"` + Profile userProfileData `json:"profile,omitempty"` +} + // userProfileData 是 gateway 对外返回的用户基础资料投影。 // 它不包含注册来源、三方身份或 refresh session 等服务端内部字段。 type userProfileData struct { @@ -158,7 +164,24 @@ func (h *Handler) getMyIdentity(writer http.ResponseWriter, request *http.Reques return } - httpkit.WriteOK(writer, request, identityData(resp.GetIdentity(), "")) + identity := resp.GetIdentity() + identityView := identityData(identity, "") + data := resolveDisplayUserData{ + userIdentityData: identityView, + Identity: identityView, + } + if h.userProfileClient != nil && identity.GetUserId() > 0 { + profileResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: identity.GetUserId(), + }) + if err != nil { + logx.Warn(request.Context(), "resolve_display_user_profile_failed", slog.Int64("user_id", identity.GetUserId()), slog.String("error", err.Error())) + } else { + data.Profile = profileData(profileResp.GetUser(), 0) + } + } + httpkit.WriteOK(writer, request, data) } // resolveDisplayUserID 通过当前有效展示号解析用户。 @@ -182,7 +205,25 @@ func (h *Handler) resolveDisplayUserID(writer http.ResponseWriter, request *http return } - httpkit.WriteOK(writer, request, identityData(resp.GetIdentity(), "")) + identity := resp.GetIdentity() + identityView := identityData(identity, "") + data := resolveDisplayUserData{ + userIdentityData: identityView, + Identity: identityView, + } + if h.userProfileClient != nil && identity.GetUserId() > 0 { + // H5 搜索短号后要展示头像和昵称;短号解析只负责稳定 ID,资料展示必须回 user-service 用 user_id 再补齐。 + profileResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: identity.GetUserId(), + }) + if err != nil { + logx.Warn(request.Context(), "resolve_display_user_profile_failed", slog.Int64("user_id", identity.GetUserId()), slog.String("error", err.Error())) + } else { + data.Profile = profileData(profileResp.GetUser(), 0) + } + } + httpkit.WriteOK(writer, request, data) } // completeMyOnboarding 是注册页唯一资料提交入口。 diff --git a/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go index 65c80704..a36e377f 100644 --- a/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/app_wallet_handler.go @@ -50,17 +50,20 @@ type walletFeatureFlagsData struct { } type walletTransactionData struct { - EntryID int64 `json:"entry_id"` - TransactionID string `json:"transaction_id"` - BizType string `json:"biz_type"` - AssetType string `json:"asset_type"` - AvailableDelta int64 `json:"available_delta"` - FrozenDelta int64 `json:"frozen_delta"` - AvailableAfter int64 `json:"available_after"` - FrozenAfter int64 `json:"frozen_after"` - CounterpartyUserID int64 `json:"counterparty_user_id"` - RoomID string `json:"room_id"` - CreatedAtMS int64 `json:"created_at_ms"` + EntryID int64 `json:"entry_id"` + TransactionID string `json:"transaction_id"` + BizType string `json:"biz_type"` + AssetType string `json:"asset_type"` + AvailableDelta int64 `json:"available_delta"` + FrozenDelta int64 `json:"frozen_delta"` + AvailableAfter int64 `json:"available_after"` + FrozenAfter int64 `json:"frozen_after"` + CounterpartyUserID int64 `json:"counterparty_user_id"` + CounterpartyDisplayUserID string `json:"counterparty_display_user_id,omitempty"` + CounterpartyUsername string `json:"counterparty_username,omitempty"` + CounterpartyAvatar string `json:"counterparty_avatar,omitempty"` + RoomID string `json:"room_id"` + CreatedAtMS int64 `json:"created_at_ms"` } type giftWallData struct { @@ -358,13 +361,49 @@ func (h *Handler) listWalletTransactionsByAsset(writer http.ResponseWriter, requ httpkit.WriteRPCError(writer, request, err) return } + profiles, err := h.walletTransactionCounterpartyProfiles(request, resp.GetTransactions()) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } items := make([]walletTransactionData, 0, len(resp.GetTransactions())) for _, item := range resp.GetTransactions() { - items = append(items, walletTransactionFromProto(item)) + items = append(items, walletTransactionFromProto(item, profiles)) } httpkit.WriteOK(writer, request, map[string]any{"items": items, "total": resp.GetTotal(), "page": page, "page_size": pageSize}) } +func (h *Handler) walletTransactionCounterpartyProfiles(request *http.Request, transactions []*walletv1.WalletTransaction) (map[int64]*userv1.User, error) { + if h.userProfileClient == nil { + return map[int64]*userv1.User{}, nil + } + userIDs := make([]int64, 0, len(transactions)) + seen := make(map[int64]struct{}, len(transactions)) + for _, transaction := range transactions { + userID := transaction.GetCounterpartyUserId() + if userID <= 0 { + continue + } + if _, exists := seen[userID]; exists { + continue + } + seen[userID] = struct{}{} + userIDs = append(userIDs, userID) + } + if len(userIDs) == 0 { + return map[int64]*userv1.User{}, nil + } + // 钱包流水只保存稳定 user_id;展示昵称、短号和头像必须回 user-service 批量补齐,避免 H5 把长 user_id 当短号展示。 + resp, err := h.userProfileClient.BatchGetUsers(request.Context(), &userv1.BatchGetUsersRequest{ + Meta: httpkit.UserMeta(request, ""), + UserIds: userIDs, + }) + if err != nil { + return nil, err + } + return resp.GetUsers(), nil +} + func rechargeProductFromProto(product *walletv1.RechargeProduct) rechargeProductData { if product == nil { return rechargeProductData{} @@ -438,11 +477,11 @@ func walletOverviewFromProto(resp *walletv1.GetWalletOverviewResponse) walletOve } } -func walletTransactionFromProto(item *walletv1.WalletTransaction) walletTransactionData { +func walletTransactionFromProto(item *walletv1.WalletTransaction, profiles map[int64]*userv1.User) walletTransactionData { if item == nil { return walletTransactionData{} } - return walletTransactionData{ + data := walletTransactionData{ EntryID: item.GetEntryId(), TransactionID: item.GetTransactionId(), BizType: item.GetBizType(), @@ -455,6 +494,12 @@ func walletTransactionFromProto(item *walletv1.WalletTransaction) walletTransact RoomID: item.GetRoomId(), CreatedAtMS: item.GetCreatedAtMs(), } + if profile := profiles[item.GetCounterpartyUserId()]; profile != nil { + data.CounterpartyDisplayUserID = profile.GetDisplayUserId() + data.CounterpartyUsername = profile.GetUsername() + data.CounterpartyAvatar = profile.GetAvatar() + } + return data } func giftWallFromProto(resp *walletv1.GetUserGiftWallResponse) giftWallData { diff --git a/services/gateway-service/internal/transport/http/walletapi/handler.go b/services/gateway-service/internal/transport/http/walletapi/handler.go index a83a1caa..0291b2ce 100644 --- a/services/gateway-service/internal/transport/http/walletapi/handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/handler.go @@ -52,6 +52,10 @@ func (h *Handler) WalletHandlers() httproutes.WalletHandlers { ListWalletTransactions: h.listWalletTransactions, ListCoinSellers: h.listCoinSellers, TransferCoinFromSeller: h.transferCoinFromSeller, + GetSalaryWalletOverview: h.getSalaryWalletOverview, + SearchSalaryWalletSeller: h.searchSalaryWalletSeller, + ExchangeSalaryToCoin: h.exchangeSalaryToCoin, + TransferSalaryToSeller: h.transferSalaryToCoinSeller, GetRedPacketConfig: h.getRedPacketConfig, ListRoomRedPackets: h.listRoomRedPackets, CreateRoomRedPacket: h.createRoomRedPacket, diff --git a/services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go new file mode 100644 index 00000000..289d5705 --- /dev/null +++ b/services/gateway-service/internal/transport/http/walletapi/salary_wallet_handler.go @@ -0,0 +1,501 @@ +package walletapi + +import ( + "fmt" + "net/http" + "strconv" + "strings" + + userv1 "hyapp.local/api/proto/user/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +const ( + salaryIdentityHost = "HOST" + salaryIdentityAgency = "AGENCY" + salaryIdentityBD = "BD" + salaryIdentityBDLeader = "BD_LEADER" + + salaryAssetHost = "HOST_SALARY_USD" + salaryAssetAgency = "AGENCY_SALARY_USD" + salaryAssetBD = "BD_SALARY_USD" + salaryAssetBDLeader = "ADMIN_SALARY_USD" +) + +type salaryWalletIdentityContext struct { + Identity string + SalaryAssetType string + UserID int64 + RegionID int64 +} + +type salaryWalletOverviewData struct { + Identity string `json:"identity"` + SalaryAssetType string `json:"salary_asset_type"` + RegionID int64 `json:"region_id"` + Salary salaryWalletBalanceData `json:"salary"` + ExchangeRate int64 `json:"exchange_rate"` + TransferRateTiers []salaryWalletExchangeRateTierData `json:"transfer_rate_tiers"` +} + +type salaryWalletBalanceData struct { + AssetType string `json:"asset_type"` + AvailableAmount int64 `json:"available_amount"` + FrozenAmount int64 `json:"frozen_amount"` + DisplayAmount string `json:"display_amount"` +} + +type salaryWalletExchangeRateTierData struct { + RegionID int64 `json:"region_id"` + MinUSDMinor int64 `json:"min_usd_minor"` + MaxUSDMinor int64 `json:"max_usd_minor"` + CoinPerUSD int64 `json:"coin_per_usd"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type salaryWalletAmountBody struct { + CommandID string `json:"command_id"` + CommandIDCamel string `json:"commandId"` + Identity string `json:"identity"` + AmountUSD string `json:"amount_usd"` + AmountUSDCamel string `json:"amountUsd"` + AmountUSDMinor int64 `json:"amount_usd_minor"` + AmountUSDMinorC int64 `json:"amountUsdMinor"` + Reason string `json:"reason"` +} + +type salaryWalletTransferBody struct { + CommandID string `json:"command_id"` + CommandIDCamel string `json:"commandId"` + Identity string `json:"identity"` + TargetDisplayUserID string `json:"target_display_user_id"` + TargetDisplayUserIDC string `json:"targetDisplayUserId"` + AmountUSD string `json:"amount_usd"` + AmountUSDCamel string `json:"amountUsd"` + AmountUSDMinor int64 `json:"amount_usd_minor"` + AmountUSDMinorC int64 `json:"amountUsdMinor"` + Reason string `json:"reason"` +} + +func (b salaryWalletAmountBody) commandID() string { + if value := strings.TrimSpace(b.CommandID); value != "" { + return value + } + return strings.TrimSpace(b.CommandIDCamel) +} + +func (b salaryWalletAmountBody) amountUSDMinor() (int64, error) { + if b.AmountUSDMinor > 0 { + return b.AmountUSDMinor, nil + } + if b.AmountUSDMinorC > 0 { + return b.AmountUSDMinorC, nil + } + if value := strings.TrimSpace(b.AmountUSD); value != "" { + return parseUSDMinor(value) + } + return parseUSDMinor(b.AmountUSDCamel) +} + +func (b salaryWalletTransferBody) commandID() string { + if value := strings.TrimSpace(b.CommandID); value != "" { + return value + } + return strings.TrimSpace(b.CommandIDCamel) +} + +func (b salaryWalletTransferBody) targetDisplayUserID() string { + if value := strings.TrimSpace(b.TargetDisplayUserID); value != "" { + return value + } + return strings.TrimSpace(b.TargetDisplayUserIDC) +} + +func (b salaryWalletTransferBody) amountUSDMinor() (int64, error) { + if b.AmountUSDMinor > 0 { + return b.AmountUSDMinor, nil + } + if b.AmountUSDMinorC > 0 { + return b.AmountUSDMinorC, nil + } + if value := strings.TrimSpace(b.AmountUSD); value != "" { + return parseUSDMinor(value) + } + return parseUSDMinor(b.AmountUSDCamel) +} + +func (h *Handler) getSalaryWalletOverview(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil || h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + identity, ok := h.resolveSalaryWalletIdentity(writer, request, request.URL.Query().Get("identity")) + if !ok { + return + } + + balanceResp, err := h.walletClient.GetBalances(request.Context(), &walletv1.GetBalancesRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + UserId: identity.UserID, + AssetTypes: []string{identity.SalaryAssetType}, + AppCode: appcode.FromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + ratesResp, err := h.walletClient.ListCoinSellerSalaryExchangeRateTiers(request.Context(), &walletv1.ListCoinSellerSalaryExchangeRateTiersRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + RegionId: identity.RegionID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + httpkit.WriteOK(writer, request, salaryWalletOverviewData{ + Identity: identity.Identity, + SalaryAssetType: identity.SalaryAssetType, + RegionID: identity.RegionID, + Salary: salaryBalanceFromProto(identity.SalaryAssetType, firstBalance(balanceResp.GetBalances())), + ExchangeRate: 80000, + TransferRateTiers: salaryRateTiersFromProto(ratesResp.GetTiers()), + }) +} + +func (h *Handler) searchSalaryWalletSeller(writer http.ResponseWriter, request *http.Request) { + if h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + identity, ok := h.resolveSalaryWalletIdentity(writer, request, request.URL.Query().Get("identity")) + if !ok { + return + } + displayUserID := strings.TrimSpace(request.URL.Query().Get("display_user_id")) + if displayUserID == "" { + displayUserID = strings.TrimSpace(request.URL.Query().Get("displayUserId")) + } + if displayUserID == "" { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + + seller, found, ok := h.findSameRegionSalaryCoinSeller(writer, request, identity.RegionID, displayUserID) + if !ok { + return + } + if !found { + httpkit.WriteError(writer, request, http.StatusNotFound, httpkit.CodeNotFound, "not found") + return + } + httpkit.WriteOK(writer, request, map[string]any{"seller": coinSellerFromProto(seller)}) +} + +func (h *Handler) exchangeSalaryToCoin(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil || h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + var body salaryWalletAmountBody + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := body.commandID() + amountUSDMinor, err := body.amountUSDMinor() + if err != nil || commandID == "" || amountUSDMinor <= 0 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + identity, ok := h.resolveSalaryWalletIdentity(writer, request, body.Identity) + if !ok { + return + } + reason := strings.TrimSpace(body.Reason) + if reason == "" { + reason = "salary exchange" + } + + resp, err := h.walletClient.ExchangeSalaryToCoin(request.Context(), &walletv1.ExchangeSalaryToCoinRequest{ + CommandId: commandID, + UserId: identity.UserID, + SalaryAssetType: identity.SalaryAssetType, + SalaryUsdMinor: amountUSDMinor, + Reason: reason, + AppCode: appcode.FromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{ + "transaction_id": resp.GetTransactionId(), + "salary_balance_after": resp.GetSalaryBalanceAfter(), + "coin_balance_after": resp.GetCoinBalanceAfter(), + "salary_usd_minor": resp.GetSalaryUsdMinor(), + "coin_amount": resp.GetCoinAmount(), + "coin_per_usd": resp.GetCoinPerUsd(), + }) +} + +func (h *Handler) transferSalaryToCoinSeller(writer http.ResponseWriter, request *http.Request) { + if h.walletClient == nil || h.userHostClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + var body salaryWalletTransferBody + if !httpkit.Decode(writer, request, &body) { + return + } + commandID := body.commandID() + displayUserID := body.targetDisplayUserID() + amountUSDMinor, err := body.amountUSDMinor() + if err != nil || commandID == "" || displayUserID == "" || amountUSDMinor <= 0 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return + } + identity, ok := h.resolveSalaryWalletIdentity(writer, request, body.Identity) + if !ok { + return + } + seller, found, ok := h.findSameRegionSalaryCoinSeller(writer, request, identity.RegionID, displayUserID) + if !ok { + return + } + if !found { + httpkit.WriteError(writer, request, http.StatusNotFound, httpkit.CodeNotFound, "not found") + return + } + reason := strings.TrimSpace(body.Reason) + if reason == "" { + reason = "salary transfer" + } + + resp, err := h.walletClient.TransferSalaryToCoinSeller(request.Context(), &walletv1.TransferSalaryToCoinSellerRequest{ + CommandId: commandID, + SourceUserId: identity.UserID, + SellerUserId: seller.GetUserId(), + SalaryAssetType: identity.SalaryAssetType, + SalaryUsdMinor: amountUSDMinor, + RegionId: identity.RegionID, + Reason: reason, + AppCode: appcode.FromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + httpkit.WriteOK(writer, request, map[string]any{ + "transaction_id": resp.GetTransactionId(), + "source_salary_balance_after": resp.GetSourceSalaryBalanceAfter(), + "seller_balance_after": resp.GetSellerBalanceAfter(), + "salary_usd_minor": resp.GetSalaryUsdMinor(), + "coin_amount": resp.GetCoinAmount(), + "coin_per_usd": resp.GetCoinPerUsd(), + "rate_min_usd_minor": resp.GetRateMinUsdMinor(), + "rate_max_usd_minor": resp.GetRateMaxUsdMinor(), + }) +} + +func (h *Handler) resolveSalaryWalletIdentity(writer http.ResponseWriter, request *http.Request, rawIdentity string) (salaryWalletIdentityContext, bool) { + identity := normalizeSalaryWalletIdentity(rawIdentity) + if identity == "" { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return salaryWalletIdentityContext{}, false + } + userID := auth.UserIDFromContext(request.Context()) + switch identity { + case salaryIdentityHost: + resp, err := h.userHostClient.GetHostProfile(request.Context(), &userv1.GetHostProfileRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return salaryWalletIdentityContext{}, false + } + profile := resp.GetHostProfile() + if profile == nil || profile.GetUserId() != userID || profile.GetStatus() != "active" || profile.GetRegionId() <= 0 { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + return salaryWalletIdentityContext{Identity: identity, SalaryAssetType: salaryAssetHost, UserID: userID, RegionID: profile.GetRegionId()}, true + case salaryIdentityAgency: + return h.resolveAgencySalaryIdentity(writer, request, userID) + case salaryIdentityBD, salaryIdentityBDLeader: + return h.resolveBDSalaryIdentity(writer, request, userID, identity) + default: + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return salaryWalletIdentityContext{}, false + } +} + +func (h *Handler) resolveAgencySalaryIdentity(writer http.ResponseWriter, request *http.Request, userID int64) (salaryWalletIdentityContext, bool) { + roleResp, err := h.userHostClient.GetUserRoleSummary(request.Context(), &userv1.GetUserRoleSummaryRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return salaryWalletIdentityContext{}, false + } + summary := roleResp.GetSummary() + if summary == nil || summary.GetAgencyId() <= 0 || (!summary.GetIsAgency() && !summary.GetIsManager()) { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + agencyResp, err := h.userHostClient.GetAgency(request.Context(), &userv1.GetAgencyRequest{ + Meta: httpkit.UserMeta(request, ""), + AgencyId: summary.GetAgencyId(), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return salaryWalletIdentityContext{}, false + } + agency := agencyResp.GetAgency() + if agency == nil || agency.GetOwnerUserId() != userID || agency.GetStatus() != "active" || agency.GetRegionId() <= 0 { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + return salaryWalletIdentityContext{Identity: salaryIdentityAgency, SalaryAssetType: salaryAssetAgency, UserID: userID, RegionID: agency.GetRegionId()}, true +} + +func (h *Handler) resolveBDSalaryIdentity(writer http.ResponseWriter, request *http.Request, userID int64, identity string) (salaryWalletIdentityContext, bool) { + resp, err := h.userHostClient.GetBDProfile(request.Context(), &userv1.GetBDProfileRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return salaryWalletIdentityContext{}, false + } + profile := resp.GetBdProfile() + if profile == nil || profile.GetUserId() != userID || profile.GetStatus() != "active" || profile.GetRegionId() <= 0 { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + if identity == salaryIdentityBD && profile.GetRole() != "bd" { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + if identity == salaryIdentityBDLeader && profile.GetRole() != "bd_leader" { + httpkit.WriteError(writer, request, http.StatusForbidden, httpkit.CodePermissionDenied, "permission denied") + return salaryWalletIdentityContext{}, false + } + assetType := salaryAssetBD + if identity == salaryIdentityBDLeader { + assetType = salaryAssetBDLeader + } + return salaryWalletIdentityContext{Identity: identity, SalaryAssetType: assetType, UserID: userID, RegionID: profile.GetRegionId()}, true +} + +func (h *Handler) findSameRegionSalaryCoinSeller(writer http.ResponseWriter, request *http.Request, regionID int64, displayUserID string) (*userv1.CoinSellerListItem, bool, bool) { + resp, err := h.userHostClient.ListActiveCoinSellersInMyRegion(request.Context(), &userv1.ListActiveCoinSellersInMyRegionRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: auth.UserIDFromContext(request.Context()), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return nil, false, false + } + for _, seller := range resp.GetCoinSellers() { + if seller.GetRegionId() == regionID && seller.GetMerchantAssetType() == "COIN_SELLER_COIN" && seller.GetStatus() == "active" && seller.GetDisplayUserId() == displayUserID { + return seller, true, true + } + } + return nil, false, true +} + +func normalizeSalaryWalletIdentity(value string) string { + value = strings.ToUpper(strings.TrimSpace(value)) + value = strings.ReplaceAll(value, "-", "_") + switch value { + case salaryIdentityHost, salaryIdentityAgency, salaryIdentityBD, salaryIdentityBDLeader: + return value + default: + return "" + } +} + +func firstBalance(balances []*walletv1.AssetBalance) *walletv1.AssetBalance { + if len(balances) == 0 { + return nil + } + return balances[0] +} + +func salaryBalanceFromProto(assetType string, balance *walletv1.AssetBalance) salaryWalletBalanceData { + if balance == nil { + return salaryWalletBalanceData{AssetType: assetType, DisplayAmount: "0.00"} + } + return salaryWalletBalanceData{ + AssetType: balance.GetAssetType(), + AvailableAmount: balance.GetAvailableAmount(), + FrozenAmount: balance.GetFrozenAmount(), + DisplayAmount: formatUSDMinor(balance.GetAvailableAmount()), + } +} + +func salaryRateTiersFromProto(tiers []*walletv1.CoinSellerSalaryExchangeRateTier) []salaryWalletExchangeRateTierData { + items := make([]salaryWalletExchangeRateTierData, 0, len(tiers)) + for _, tier := range tiers { + items = append(items, salaryWalletExchangeRateTierData{ + RegionID: tier.GetRegionId(), + MinUSDMinor: tier.GetMinUsdMinor(), + MaxUSDMinor: tier.GetMaxUsdMinor(), + CoinPerUSD: tier.GetCoinPerUsd(), + Status: tier.GetStatus(), + SortOrder: tier.GetSortOrder(), + UpdatedAtMS: tier.GetUpdatedAtMs(), + }) + } + return items +} + +func parseUSDMinor(value string) (int64, error) { + value = strings.TrimSpace(value) + if value == "" || strings.HasPrefix(value, "-") { + return 0, fmt.Errorf("invalid amount") + } + parts := strings.Split(value, ".") + if len(parts) > 2 || parts[0] == "" { + return 0, fmt.Errorf("invalid amount") + } + dollars, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil { + return 0, err + } + cents := int64(0) + if len(parts) == 2 { + fraction := parts[1] + if len(fraction) > 2 { + return 0, fmt.Errorf("invalid amount") + } + for len(fraction) < 2 { + fraction += "0" + } + cents, err = strconv.ParseInt(fraction, 10, 64) + if err != nil { + return 0, err + } + } + if dollars > (1<<63-1-cents)/100 { + return 0, fmt.Errorf("amount overflow") + } + return dollars*100 + cents, nil +} + +func formatUSDMinor(value int64) string { + sign := "" + if value < 0 { + sign = "-" + value = -value + } + return fmt.Sprintf("%s%d.%02d", sign, value/100, value%100) +} diff --git a/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go index c98f3965..d25db04f 100644 --- a/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go @@ -193,6 +193,14 @@ func (h *Handler) coinSellerTransferRegions(writer http.ResponseWriter, request httpkit.WriteRPCError(writer, request, err) return 0, 0, false } + sellerRegionID := sellerResp.GetUser().GetRegionId() + if sellerUserID == targetUserID { + if sellerRegionID <= 0 { + httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") + return 0, 0, false + } + return sellerRegionID, sellerRegionID, true + } targetResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ Meta: httpkit.UserMeta(request, ""), UserId: targetUserID, @@ -201,7 +209,6 @@ func (h *Handler) coinSellerTransferRegions(writer http.ResponseWriter, request httpkit.WriteRPCError(writer, request, err) return 0, 0, false } - sellerRegionID := sellerResp.GetUser().GetRegionId() targetRegionID := targetResp.GetUser().GetRegionId() if sellerRegionID <= 0 || targetRegionID <= 0 { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index f972624a..29488d2a 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -116,6 +116,13 @@ type ListBDLeaderAgenciesCommand struct { PageSize int } +// ListBDAgenciesCommand 描述 BD 查询自己直属 Agency 列表的条件。 +type ListBDAgenciesCommand struct { + BDUserID int64 + Status string + PageSize int +} + // ProcessRoleInvitationInput 是处理角色邀请的外部输入。 type ProcessRoleInvitationInput struct { CommandID string diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index 8d2c2e0a..db7cccb7 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -22,6 +22,7 @@ type Repository interface { InviteBD(ctx context.Context, command InviteBDCommand) (hostdomain.RoleInvitation, error) ListBDLeaderBDs(ctx context.Context, command ListBDLeaderBDsCommand) ([]hostdomain.BDProfile, error) ListBDLeaderAgencies(ctx context.Context, command ListBDLeaderAgenciesCommand) ([]hostdomain.Agency, error) + ListBDAgencies(ctx context.Context, command ListBDAgenciesCommand) ([]hostdomain.Agency, error) ProcessRoleInvitation(ctx context.Context, command ProcessRoleInvitationCommand) (hostdomain.ProcessRoleInvitationResult, error) CreateBDLeader(ctx context.Context, command CreateBDLeaderCommand) (hostdomain.BDProfile, error) CreateBD(ctx context.Context, command CreateBDCommand) (hostdomain.BDProfile, error) @@ -274,6 +275,21 @@ func (s *Service) ListBDLeaderAgencies(ctx context.Context, command ListBDLeader }) } +// ListBDAgencies 返回当前 BD 直接拓展的 Agency 列表。 +func (s *Service) ListBDAgencies(ctx context.Context, command ListBDAgenciesCommand) ([]hostdomain.Agency, error) { + if s.repository == nil { + return nil, xerr.New(xerr.Unavailable, "host repository is not configured") + } + if command.BDUserID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "bd_user_id is required") + } + return s.repository.ListBDAgencies(ctx, ListBDAgenciesCommand{ + BDUserID: command.BDUserID, + Status: normalizeStatus(command.Status), + PageSize: normalizePageSize(command.PageSize), + }) +} + // ProcessRoleInvitation 接受、拒绝或取消角色邀请。 func (s *Service) ProcessRoleInvitation(ctx context.Context, command ProcessRoleInvitationInput) (hostdomain.ProcessRoleInvitationResult, error) { if err := s.requireWriteDependencies(); err != nil { diff --git a/services/user-service/internal/storage/mysql/host/queries.go b/services/user-service/internal/storage/mysql/host/queries.go index ddf1234e..8fb8dda4 100644 --- a/services/user-service/internal/storage/mysql/host/queries.go +++ b/services/user-service/internal/storage/mysql/host/queries.go @@ -325,6 +325,23 @@ func (r *Repository) ListBDLeaderAgencies(ctx context.Context, command hostservi return queryAgencies(ctx, r.db, clause, args...) } +// ListBDAgencies 读取一个有效 BD 直接拓展的 Agency,不包含同负责人下其他 BD 的数据。 +func (r *Repository) ListBDAgencies(ctx context.Context, command hostservice.ListBDAgenciesCommand) ([]hostdomain.Agency, error) { + bd, err := queryBDProfile(ctx, r.db, "WHERE user_id = ?", command.BDUserID) + if err != nil { + return nil, err + } + if bd.Status != hostdomain.BDStatusActive { + return nil, xerr.New(xerr.PermissionDenied, "bd is not active") + } + status := command.Status + if status == "" { + status = hostdomain.AgencyStatusActive + } + clause, args := appScopedClause(ctx, "WHERE status = ? AND parent_bd_user_id = ? ORDER BY created_at_ms DESC, agency_id DESC LIMIT ?", status, command.BDUserID, command.PageSize) + return queryAgencies(ctx, r.db, clause, args...) +} + // ListAgencyMembers 读取 Agency 成员关系列表。 func (r *Repository) ListAgencyMembers(ctx context.Context, agencyID int64, status string) ([]hostdomain.AgencyMembership, error) { query := fmt.Sprintf(`SELECT %s FROM agency_memberships WHERE app_code = ? AND agency_id = ?`, agencyMembershipColumns) diff --git a/services/user-service/internal/transport/grpc/host.go b/services/user-service/internal/transport/grpc/host.go index 33ce2d29..9c49870b 100644 --- a/services/user-service/internal/transport/grpc/host.go +++ b/services/user-service/internal/transport/grpc/host.go @@ -181,6 +181,28 @@ func (s *Server) ListBDLeaderAgencies(ctx context.Context, req *userv1.ListBDLea return resp, nil } +// ListBDAgencies 返回当前 BD 自己拓展的 Agency 列表。 +func (s *Server) ListBDAgencies(ctx context.Context, req *userv1.ListBDAgenciesRequest) (*userv1.ListBDAgenciesResponse, error) { + if s.hostSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) + } + ctx = contextWithApp(ctx, req.GetMeta()) + agencies, err := s.hostSvc.ListBDAgencies(ctx, hostservice.ListBDAgenciesCommand{ + BDUserID: req.GetBdUserId(), + Status: req.GetStatus(), + PageSize: int(req.GetPageSize()), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + + resp := &userv1.ListBDAgenciesResponse{Agencies: make([]*userv1.Agency, 0, len(agencies))} + for _, agency := range agencies { + resp.Agencies = append(resp.Agencies, toProtoAgency(agency)) + } + return resp, nil +} + // ProcessRoleInvitation 处理 Agency 或 BD 邀请。 func (s *Server) ProcessRoleInvitation(ctx context.Context, req *userv1.ProcessRoleInvitationRequest) (*userv1.ProcessRoleInvitationResponse, error) { if s.hostSvc == nil { 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 cc7356b0..5d3b6053 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -558,6 +558,24 @@ CREATE TABLE IF NOT EXISTS coin_seller_stock_records ( KEY idx_coin_seller_stock_type_time (app_code, stock_type, created_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='金币商户库存记录表'; +CREATE TABLE IF NOT EXISTS coin_seller_salary_exchange_rate_tiers ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + region_id BIGINT NOT NULL COMMENT '币商所属区域 ID', + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '区间 ID', + min_usd_minor BIGINT NOT NULL COMMENT '起始美元金额,单位美分,包含', + max_usd_minor BIGINT NOT NULL COMMENT '结束美元金额,单位美分,包含', + coin_per_usd BIGINT NOT NULL COMMENT '每 1 USD 工资可兑换的币商专用金币数量', + status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '状态:active/disabled', + sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重', + created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID', + updated_by_user_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 (tier_id), + KEY idx_coin_seller_salary_rates_region (app_code, region_id, status, min_usd_minor, max_usd_minor), + KEY idx_coin_seller_salary_rates_sort (app_code, region_id, status, sort_order) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='币商工资兑换比例区间表'; + CREATE TABLE IF NOT EXISTS resources ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', resource_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '资源 ID', @@ -925,17 +943,17 @@ CREATE TABLE IF NOT EXISTS wallet_diamond_exchange_rules ( CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', - region_id BIGINT NOT NULL DEFAULT 0 COMMENT '送礼用户区域,0 表示全局默认', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域,0 表示全局默认', gift_type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码', status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态', - ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '主播周期钻石入账比例,百分比', + ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '房间贡献热度和主播周期钻石入账比例,百分比', created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台用户 ID', 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, region_id, gift_type_code), KEY idx_gift_diamond_ratio_region (app_code, region_id, status) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物入主播周期钻石比例配置表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物钻石和房间贡献比例配置表'; CREATE TABLE IF NOT EXISTS red_packet_configs ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index f97737bc..fce24118 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -19,6 +19,8 @@ const ( AssetBDSalaryUSD = "BD_SALARY_USD" // AssetAdminSalaryUSD 是 Admin 工资美元钱包,只接收 Admin 政策结算工资。 AssetAdminSalaryUSD = "ADMIN_SALARY_USD" + // SalaryExchangeCoinPerUSD 是工资直接兑换普通金币的固定比例,金额以 1 USD 为单位。 + SalaryExchangeCoinPerUSD int64 = 80000 // StockTypeUSDTPurchase 表示币商线下 USDT 进货后发放专用金币库存。 StockTypeUSDTPurchase = "usdt_purchase" @@ -265,6 +267,68 @@ type CoinSellerTransferReceipt struct { RechargePolicyUSDMinorUnit int64 } +// CoinSellerSalaryExchangeRateTier 是工资转给币商时按区域和美元金额匹配的金币兑换比例。 +type CoinSellerSalaryExchangeRateTier struct { + RegionID int64 + MinUSDMinor int64 + MaxUSDMinor int64 + CoinPerUSD int64 + Status string + SortOrder int + UpdatedAtMS int64 +} + +// SalaryExchangeCommand 是用户把某个身份工资美元钱包兑换为自己普通金币的账务命令。 +type SalaryExchangeCommand struct { + AppCode string + CommandID string + UserID int64 + SalaryAssetType string + SalaryUSDMinor int64 + Reason string +} + +// SalaryExchangeReceipt 返回工资扣减和普通金币入账后的双边余额。 +type SalaryExchangeReceipt struct { + TransactionID string + UserID int64 + SalaryAssetType string + SalaryBalanceAfter int64 + CoinBalanceAfter int64 + SalaryUSDMinor int64 + CoinAmount int64 + CoinPerUSD int64 + CreatedAtMS int64 +} + +// SalaryTransferToCoinSellerCommand 是用户把某个身份工资美元钱包转给同区域币商专用金币库存的账务命令。 +type SalaryTransferToCoinSellerCommand struct { + AppCode string + CommandID string + SourceUserID int64 + SellerUserID int64 + SalaryAssetType string + SalaryUSDMinor int64 + RegionID int64 + Reason string +} + +// SalaryTransferToCoinSellerReceipt 返回工资扣减和币商库存入账后的双边余额与命中的区间。 +type SalaryTransferToCoinSellerReceipt struct { + TransactionID string + SourceUserID int64 + SellerUserID int64 + SalaryAssetType string + SourceSalaryBalanceAfter int64 + SellerBalanceAfter int64 + SalaryUSDMinor int64 + CoinAmount int64 + CoinPerUSD int64 + RateMinUSDMinor int64 + RateMaxUSDMinor int64 + CreatedAtMS int64 +} + // CoinSellerStockCreditCommand 是后台给币商专用金币库存入账的最小账务命令。 type CoinSellerStockCreditCommand struct { AppCode string @@ -824,6 +888,16 @@ func ValidAssetType(assetType string) bool { } } +// ValidSalaryAssetType 只允许身份工资美元钱包进入工资兑换和转币商链路,避免普通金币或币商库存被误扣。 +func ValidSalaryAssetType(assetType string) bool { + switch strings.ToUpper(strings.TrimSpace(assetType)) { + case AssetHostSalaryUSD, AssetAgencySalaryUSD, AssetBDSalaryUSD, AssetAdminSalaryUSD: + return true + default: + return false + } +} + func NormalizeGiftChargeAssetType(assetType string) string { return AssetCoin } diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index ee5ba83d..ff1727c1 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -26,6 +26,9 @@ type Repository interface { AdminCreditAsset(ctx context.Context, command ledger.AdminCreditAssetCommand) (ledger.AssetBalance, string, error) AdminCreditCoinSellerStock(ctx context.Context, command ledger.CoinSellerStockCreditCommand) (ledger.CoinSellerStockCreditReceipt, error) TransferCoinFromSeller(ctx context.Context, command ledger.CoinSellerTransferCommand) (ledger.CoinSellerTransferReceipt, error) + ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, appCode string, regionID int64, includeDisabled bool) ([]ledger.CoinSellerSalaryExchangeRateTier, error) + ExchangeSalaryToCoin(ctx context.Context, command ledger.SalaryExchangeCommand) (ledger.SalaryExchangeReceipt, error) + TransferSalaryToCoinSeller(ctx context.Context, command ledger.SalaryTransferToCoinSellerCommand) (ledger.SalaryTransferToCoinSellerReceipt, error) CreditTaskReward(ctx context.Context, command ledger.TaskRewardCommand) (ledger.TaskRewardReceipt, error) CreditLuckyGiftReward(ctx context.Context, command ledger.LuckyGiftRewardCommand) (ledger.LuckyGiftRewardReceipt, error) ApplyGameCoinChange(ctx context.Context, command ledger.GameCoinChangeCommand) (ledger.GameCoinChangeReceipt, error) @@ -355,14 +358,11 @@ func (s *Service) AdminCreditCoinSellerStock(ctx context.Context, command ledger return s.repository.AdminCreditCoinSellerStock(ctx, command) } -// TransferCoinFromSeller 执行币商向玩家转金币;身份和区域都由 gateway/user-service 校验并传入。 +// TransferCoinFromSeller 执行币商专用金币转普通金币;身份和区域都由 gateway/user-service 校验并传入。 func (s *Service) TransferCoinFromSeller(ctx context.Context, command ledger.CoinSellerTransferCommand) (ledger.CoinSellerTransferReceipt, error) { if command.CommandID == "" || command.SellerUserID <= 0 || command.TargetUserID <= 0 || command.Amount <= 0 { return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.InvalidArgument, "coin seller transfer command is incomplete") } - if command.SellerUserID == command.TargetUserID { - return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.InvalidArgument, "seller and target must be different") - } if command.SellerRegionID <= 0 || command.TargetRegionID <= 0 { return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.InvalidArgument, "seller and target region are required") } @@ -382,6 +382,75 @@ func (s *Service) TransferCoinFromSeller(ctx context.Context, command ledger.Coi return s.repository.TransferCoinFromSeller(ctx, command) } +// ListCoinSellerSalaryExchangeRateTiers 返回指定区域的工资转币商比例区间;gateway 用它给 H5 展示预计到账金币。 +func (s *Service) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, appCode string, regionID int64, includeDisabled bool) ([]ledger.CoinSellerSalaryExchangeRateTier, error) { + if regionID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "region_id is required") + } + if s.repository == nil { + return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + appCode = appcode.Normalize(appCode) + ctx = appcode.WithContext(ctx, appCode) + return s.repository.ListCoinSellerSalaryExchangeRateTiers(ctx, appCode, regionID, includeDisabled) +} + +// ExchangeSalaryToCoin 校验工资兑换命令;身份归属由 gateway 校验,wallet 只接受明确的工资资产和正向美分金额。 +func (s *Service) ExchangeSalaryToCoin(ctx context.Context, command ledger.SalaryExchangeCommand) (ledger.SalaryExchangeReceipt, error) { + if command.CommandID == "" || command.UserID <= 0 || command.SalaryUSDMinor <= 0 { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.InvalidArgument, "salary exchange command is incomplete") + } + command.SalaryAssetType = strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)) + if !ledger.ValidSalaryAssetType(command.SalaryAssetType) { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.InvalidArgument, "salary_asset_type is invalid") + } + command.Reason = strings.TrimSpace(command.Reason) + if command.Reason == "" { + command.Reason = "salary exchange" + } + if len(command.CommandID) > 128 || len(command.Reason) > 512 { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.InvalidArgument, "salary exchange text fields are too long") + } + if s.repository == nil { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + + return s.repository.ExchangeSalaryToCoin(ctx, command) +} + +// TransferSalaryToCoinSeller 校验工资转币商命令;比例区间命中和双边入账由 repository 在同一事务内完成。 +func (s *Service) TransferSalaryToCoinSeller(ctx context.Context, command ledger.SalaryTransferToCoinSellerCommand) (ledger.SalaryTransferToCoinSellerReceipt, error) { + if command.CommandID == "" || command.SourceUserID <= 0 || command.SellerUserID <= 0 || command.SalaryUSDMinor <= 0 { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "salary transfer command is incomplete") + } + if command.SourceUserID == command.SellerUserID { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "source and seller must be different") + } + if command.RegionID <= 0 { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "region_id is required") + } + command.SalaryAssetType = strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)) + if !ledger.ValidSalaryAssetType(command.SalaryAssetType) { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "salary_asset_type is invalid") + } + command.Reason = strings.TrimSpace(command.Reason) + if command.Reason == "" { + command.Reason = "salary transfer" + } + if len(command.CommandID) > 128 || len(command.Reason) > 512 { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "salary transfer text fields are too long") + } + if s.repository == nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + ctx = appcode.WithContext(ctx, command.AppCode) + + return s.repository.TransferSalaryToCoinSeller(ctx, command) +} + // CreditTaskReward 发放任务奖励金币;任务完成判断属于 activity-service,这里只负责账本幂等入账。 func (s *Service) CreditTaskReward(ctx context.Context, command ledger.TaskRewardCommand) (ledger.TaskRewardReceipt, error) { if command.CommandID == "" || command.TargetUserID <= 0 || command.Amount <= 0 || command.TaskID == "" || command.CycleKey == "" { diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index f0003116..58dd535d 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -263,6 +263,84 @@ func TestDebitGiftCreditsHostPeriodDiamondsBySenderRegionAndGiftType(t *testing. } } +func TestDebitGiftAppliesRoomRegionGiftDiamondRatioToHeatValueByGiftType(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetGiftDiamondRatio(8801, resourcedomain.GiftTypeNormal, "30.00") + repository.SetGiftDiamondRatio(8801, resourcedomain.GiftTypeLucky, "40.00") + repository.SetGiftDiamondRatio(8801, resourcedomain.GiftTypeSuperLucky, "50.00") + + cases := []struct { + giftID string + giftType string + command string + senderID int64 + wantHeat int64 + }{ + {giftID: "normal-room-ratio-gift", giftType: resourcedomain.GiftTypeNormal, command: "cmd-normal-room-ratio", senderID: 13001, wantHeat: 30}, + {giftID: "lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeLucky, command: "cmd-lucky-room-ratio", senderID: 13002, wantHeat: 40}, + {giftID: "super-lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, command: "cmd-super-lucky-room-ratio", senderID: 13003, wantHeat: 50}, + } + + for _, tc := range cases { + repository.SetBalance(tc.senderID, 100) + repository.SetGiftPrice(tc.giftID, "v1", 100, 100, 100) + repository.SetGiftType(tc.giftID, tc.giftType) + receipt, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ + CommandID: tc.command, + RoomID: "room-ratio", + SenderUserID: tc.senderID, + SenderRegionID: 1001, + RegionID: 8801, + TargetUserID: 14001, + GiftID: tc.giftID, + GiftCount: 1, + PriceVersion: "v1", + }) + if err != nil { + t.Fatalf("DebitGift %s failed: %v", tc.giftType, err) + } + if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != 100 { + t.Fatalf("%s room contribution ratio mismatch: %+v want heat %d", tc.giftType, receipt, tc.wantHeat) + } + } +} + +func TestBatchDebitGiftAppliesRoomRegionGiftDiamondRatioToEachTargetHeatValue(t *testing.T) { + repository := mysqltest.NewRepository(t) + repository.SetBalance(15001, 1000) + repository.SetGiftPrice("batch-room-ratio-gift", "v1", 100, 100, 100) + repository.SetGiftType("batch-room-ratio-gift", resourcedomain.GiftTypeLucky) + repository.SetGiftDiamondRatio(9901, resourcedomain.GiftTypeLucky, "25.00") + svc := walletservice.New(repository) + + receipt, err := svc.BatchDebitGift(context.Background(), ledger.BatchDebitGiftCommand{ + CommandID: "cmd-batch-room-ratio", + RoomID: "room-ratio", + SenderUserID: 15001, + SenderRegionID: 1001, + RegionID: 9901, + GiftID: "batch-room-ratio-gift", + GiftCount: 1, + PriceVersion: "v1", + Targets: []ledger.DebitGiftTargetCommand{ + {CommandID: "cmd-batch-room-ratio:target:15002", TargetUserID: 15002}, + {CommandID: "cmd-batch-room-ratio:target:15003", TargetUserID: 15003}, + }, + }) + if err != nil { + t.Fatalf("BatchDebitGift failed: %v", err) + } + if receipt.Aggregate.HeatValue != 50 || len(receipt.Targets) != 2 { + t.Fatalf("batch aggregate room contribution ratio mismatch: %+v", receipt) + } + for _, target := range receipt.Targets { + if target.Receipt.HeatValue != 25 || target.Receipt.GiftPointAdded != 100 { + t.Fatalf("target room contribution ratio mismatch: %+v", target) + } + } +} + // TestDebitGiftRejectsHostPeriodWithoutRegion 锁定工资政策必须有主播区域才能入账。 func TestDebitGiftRejectsHostPeriodWithoutRegion(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -1553,6 +1631,111 @@ func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { } } +// TestTransferCoinFromSellerAllowsSelfTransfer 验证币商可以把自己的专用库存转入自己的普通金币账户。 +func TestTransferCoinFromSellerAllowsSelfTransfer(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetRechargePolicy(1001, "recharge-v1", 30000, 100) + _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ + CommandID: "cmd-credit-self-seller", + TargetUserID: 30003, + AssetType: ledger.AssetCoinSellerCoin, + Amount: 100000, + OperatorUserID: 90001, + Reason: "seed seller balance", + EvidenceRef: "ticket-self-seller", + }) + if err != nil { + t.Fatalf("seed seller asset failed: %v", err) + } + + command := ledger.CoinSellerTransferCommand{ + CommandID: "cmd-seller-self-transfer", + SellerUserID: 30003, + TargetUserID: 30003, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 30000, + Reason: "self recharge", + } + first, err := svc.TransferCoinFromSeller(context.Background(), command) + if err != nil { + t.Fatalf("TransferCoinFromSeller self transfer failed: %v", err) + } + second, err := svc.TransferCoinFromSeller(context.Background(), command) + if err != nil { + t.Fatalf("TransferCoinFromSeller self transfer retry failed: %v", err) + } + if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SellerBalanceAfter != 70000 || first.TargetBalanceAfter != 30000 || first.RechargeUSDMinor != 100 { + t.Fatalf("self transfer receipt mismatch: first=%+v second=%+v", first, second) + } + + balances, err := svc.GetBalances(context.Background(), 30003, []string{ledger.AssetCoinSellerCoin, ledger.AssetCoin}) + if err != nil { + t.Fatalf("GetBalances failed: %v", err) + } + if balanceAmount(balances, ledger.AssetCoinSellerCoin) != 70000 || balanceAmount(balances, ledger.AssetCoin) != 30000 { + t.Fatalf("self transfer balances mismatch: %+v", balances) + } + if got := repository.CountRows("wallet_transactions", "command_id = ?", command.CommandID); got != 1 { + t.Fatalf("idempotent self transfer should write one transaction, got %d", got) + } + if got := repository.CountRows("wallet_entries", "transaction_id = ?", first.TransactionID); got != 2 { + t.Fatalf("self transfer should write two entries for two asset accounts, got %d", got) + } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ?", first.TransactionID); got != 1 { + t.Fatalf("self transfer should write one recharge record, got %d", got) + } + if got := repository.CountRows("wallet_outbox", "transaction_id = ?", first.TransactionID); got != 4 { + t.Fatalf("self transfer should write two balance events, one transfer event and one recharge event, got %d", got) + } +} + +// TestTransferCoinFromSellerAllowsSubCentRechargeAmount 验证小额金币也必须到账,美元统计按最小货币单位向下取整。 +func TestTransferCoinFromSellerAllowsSubCentRechargeAmount(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetRechargePolicy(1001, "recharge-v1", 1000, 100) + _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ + CommandID: "cmd-credit-small-seller", + TargetUserID: 30004, + AssetType: ledger.AssetCoinSellerCoin, + Amount: 11, + OperatorUserID: 90001, + Reason: "seed small seller balance", + EvidenceRef: "ticket-small-seller", + }) + if err != nil { + t.Fatalf("seed seller asset failed: %v", err) + } + + receipt, err := svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ + CommandID: "cmd-seller-small-transfer", + SellerUserID: 30004, + TargetUserID: 30004, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 1, + Reason: "self recharge", + }) + if err != nil { + t.Fatalf("TransferCoinFromSeller small amount failed: %v", err) + } + if receipt.SellerBalanceAfter != 10 || receipt.TargetBalanceAfter != 1 || receipt.RechargeUSDMinor != 0 { + t.Fatalf("small transfer receipt mismatch: %+v", receipt) + } + balances, err := svc.GetBalances(context.Background(), 30004, []string{ledger.AssetCoinSellerCoin, ledger.AssetCoin}) + if err != nil { + t.Fatalf("GetBalances failed: %v", err) + } + if balanceAmount(balances, ledger.AssetCoinSellerCoin) != 10 || balanceAmount(balances, ledger.AssetCoin) != 1 { + t.Fatalf("small transfer balances mismatch: %+v", balances) + } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ? AND coin_amount = ? AND usd_minor_amount = ?", receipt.TransactionID, int64(1), int64(0)); got != 1 { + t.Fatalf("small transfer should write recharge record with zero USD minor, got %d", got) + } +} + // TestTransferCoinFromSellerInsufficientBalance 验证币商余额不足时不生成转账交易。 func TestTransferCoinFromSellerInsufficientBalance(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -1612,6 +1795,138 @@ func TestTransferCoinFromSellerRequiresRechargePolicy(t *testing.T) { } } +// TestExchangeSalaryToCoinMovesSalaryIntoPlayerCoin 验证工资兑换按固定 1 USD = 80000 COIN 扣工资并加普通金币,重复 command 只返回同一笔事实。 +func TestExchangeSalaryToCoinMovesSalaryIntoPlayerCoin(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetAssetBalance(34001, ledger.AssetAdminSalaryUSD, 2500) + + command := ledger.SalaryExchangeCommand{ + AppCode: appcode.Default, + CommandID: "cmd-salary-exchange", + UserID: 34001, + SalaryAssetType: ledger.AssetAdminSalaryUSD, + SalaryUSDMinor: 1000, + Reason: "salary exchange", + } + first, err := svc.ExchangeSalaryToCoin(context.Background(), command) + if err != nil { + t.Fatalf("ExchangeSalaryToCoin failed: %v", err) + } + second, err := svc.ExchangeSalaryToCoin(context.Background(), command) + if err != nil { + t.Fatalf("ExchangeSalaryToCoin retry failed: %v", err) + } + if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SalaryBalanceAfter != 1500 || first.CoinBalanceAfter != 800000 || first.CoinAmount != 800000 || first.CoinPerUSD != ledger.SalaryExchangeCoinPerUSD { + t.Fatalf("salary exchange receipt mismatch: first=%+v second=%+v", first, second) + } + + assertBalance(t, svc, 34001, ledger.AssetAdminSalaryUSD, 1500) + assertBalance(t, svc, 34001, ledger.AssetCoin, 800000) + if got := repository.CountRows("wallet_transactions", "command_id = ?", command.CommandID); got != 1 { + t.Fatalf("idempotent salary exchange should write one transaction, got %d", got) + } + if got := repository.CountRows("wallet_entries", "transaction_id = ?", first.TransactionID); got != 2 { + t.Fatalf("salary exchange should write two entries, got %d", got) + } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ?", first.TransactionID); got != 0 { + t.Fatalf("salary exchange must not write player recharge record, got %d", got) + } +} + +// TestExchangeSalaryToCoinRejectsCommandPayloadConflict 验证同 command_id 只能代表同一笔工资兑换请求。 +func TestExchangeSalaryToCoinRejectsCommandPayloadConflict(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetAssetBalance(34002, ledger.AssetHostSalaryUSD, 3000) + + command := ledger.SalaryExchangeCommand{ + AppCode: appcode.Default, + CommandID: "cmd-salary-exchange-conflict", + UserID: 34002, + SalaryAssetType: ledger.AssetHostSalaryUSD, + SalaryUSDMinor: 500, + Reason: "salary exchange", + } + if _, err := svc.ExchangeSalaryToCoin(context.Background(), command); err != nil { + t.Fatalf("ExchangeSalaryToCoin initial command failed: %v", err) + } + command.SalaryUSDMinor = 600 + if _, err := svc.ExchangeSalaryToCoin(context.Background(), command); !xerr.IsCode(err, xerr.IdempotencyConflict) { + t.Fatalf("expected IDEMPOTENCY_CONFLICT for changed salary exchange payload, got %v", err) + } + assertBalance(t, svc, 34002, ledger.AssetHostSalaryUSD, 2500) + assertBalance(t, svc, 34002, ledger.AssetCoin, 400000) +} + +// TestTransferSalaryToCoinSellerUsesRegionRateTier 验证工资转币商按命中的区域区间扣工资并加币商专用金币,不写玩家充值事实。 +func TestTransferSalaryToCoinSellerUsesRegionRateTier(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetAssetBalance(35001, ledger.AssetBDSalaryUSD, 10000) + repository.SetCoinSellerSalaryExchangeRateTier(appcode.Default, 7001, 1100, 5000, 92000) + + command := ledger.SalaryTransferToCoinSellerCommand{ + AppCode: appcode.Default, + CommandID: "cmd-salary-transfer-seller", + SourceUserID: 35001, + SellerUserID: 35002, + SalaryAssetType: ledger.AssetBDSalaryUSD, + SalaryUSDMinor: 4000, + RegionID: 7001, + Reason: "salary transfer", + } + first, err := svc.TransferSalaryToCoinSeller(context.Background(), command) + if err != nil { + t.Fatalf("TransferSalaryToCoinSeller failed: %v", err) + } + second, err := svc.TransferSalaryToCoinSeller(context.Background(), command) + if err != nil { + t.Fatalf("TransferSalaryToCoinSeller retry failed: %v", err) + } + if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SourceSalaryBalanceAfter != 6000 || first.SellerBalanceAfter != 3680000 || first.CoinAmount != 3680000 || first.CoinPerUSD != 92000 || first.RateMinUSDMinor != 1100 || first.RateMaxUSDMinor != 5000 { + t.Fatalf("salary transfer receipt mismatch: first=%+v second=%+v", first, second) + } + + assertBalance(t, svc, 35001, ledger.AssetBDSalaryUSD, 6000) + assertBalance(t, svc, 35002, ledger.AssetCoinSellerCoin, 3680000) + if got := repository.CountRows("wallet_transactions", "command_id = ?", command.CommandID); got != 1 { + t.Fatalf("idempotent salary transfer should write one transaction, got %d", got) + } + if got := repository.CountRows("wallet_entries", "transaction_id = ?", first.TransactionID); got != 2 { + t.Fatalf("salary transfer should write two entries, got %d", got) + } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ?", first.TransactionID); got != 0 { + t.Fatalf("salary transfer must not write player recharge record, got %d", got) + } +} + +// TestTransferSalaryToCoinSellerRequiresConfiguredRate 验证当前区域没有可命中的工资转币商比例时不会产生半成品账务。 +func TestTransferSalaryToCoinSellerRequiresConfiguredRate(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + repository.SetAssetBalance(35003, ledger.AssetAgencySalaryUSD, 10000) + + _, err := svc.TransferSalaryToCoinSeller(context.Background(), ledger.SalaryTransferToCoinSellerCommand{ + AppCode: appcode.Default, + CommandID: "cmd-salary-transfer-no-rate", + SourceUserID: 35003, + SellerUserID: 35004, + SalaryAssetType: ledger.AssetAgencySalaryUSD, + SalaryUSDMinor: 4000, + RegionID: 8001, + Reason: "salary transfer", + }) + if !xerr.IsCode(err, xerr.NotFound) { + t.Fatalf("expected NOT_FOUND when salary transfer rate is missing, got %v", err) + } + assertBalance(t, svc, 35003, ledger.AssetAgencySalaryUSD, 10000) + assertBalance(t, svc, 35004, ledger.AssetCoinSellerCoin, 0) + if got := repository.CountRows("wallet_transactions", "command_id = ?", "cmd-salary-transfer-no-rate"); got != 0 { + t.Fatalf("missing salary transfer rate must not write transaction, got %d", got) + } +} + // TestAdminCreditCoinSellerStockPurchaseCreditsDedicatedBalance 验证 USDT 进货只增加币商专用库存并写专用进货记录。 func TestAdminCreditCoinSellerStockPurchaseCreditsDedicatedBalance(t *testing.T) { repository := mysqltest.NewRepository(t) @@ -1941,6 +2256,40 @@ func TestGiftConfigSyncsConfiguredResourcePrice(t *testing.T) { if gift.ChargeAssetType != ledger.AssetCoin || gift.CoinPrice != 77 || gift.GiftPointAmount != 77 { t.Fatalf("gift price should be overridden by resource price: %+v", gift) } + updatedResource, err := svc.UpdateResource(ctx, resourcedomain.ResourceCommand{ + ResourceID: paidResource.ResourceID, + ResourceCode: paidResource.ResourceCode, + ResourceType: resourcedomain.TypeGift, + Name: paidResource.Name, + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategyIncreaseQuantity, + PriceType: resourcedomain.PriceTypeCoin, + CoinPrice: 88, + UsageScopes: []string{"gift"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("update priced gift resource failed: %v", err) + } + if updatedResource.CoinPrice != 88 || updatedResource.GiftPointAmount != 88 { + t.Fatalf("updated resource price mismatch: %+v", updatedResource) + } + repository.SetBalance(54001, 100) + updatedReceipt, err := svc.DebitGift(ctx, ledger.DebitGiftCommand{ + CommandID: "cmd-price-sync-after-resource-update", + RoomID: "room-price-sync", + SenderUserID: 54001, + TargetUserID: 54002, + GiftID: "price-sync", + GiftCount: 1, + }) + if err != nil { + t.Fatalf("debit gift after resource price update failed: %v", err) + } + if updatedReceipt.CoinSpent != 88 || updatedReceipt.GiftPointAdded != 88 { + t.Fatalf("gift price should follow updated resource price: %+v", updatedReceipt) + } freeResource, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ ResourceCode: "gift_free_sync", diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 6e0ba633..a1810858 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -29,6 +29,8 @@ const ( bizTypeCoinSellerTransfer = "coin_seller_transfer" bizTypeCoinSellerStockPurchase = "coin_seller_stock_purchase" bizTypeCoinSellerCoinCompensation = "coin_seller_coin_compensation" + bizTypeSalaryExchangeToCoin = "salary_exchange_to_coin" + bizTypeSalaryTransferToCoinSeller = "salary_transfer_to_coin_seller" bizTypeGooglePlayRecharge = "google_play_recharge" bizTypeGameDebit = "game_debit" bizTypeGameCredit = "game_credit" @@ -95,6 +97,10 @@ func Open(ctx context.Context, dsn string) (*Repository, error) { _ = db.Close() return nil, err } + if err := ensureCoinSellerSalaryExchangeRateSchema(ctx, db); err != nil { + _ = db.Close() + return nil, err + } return &Repository{db: db}, nil } @@ -103,17 +109,17 @@ func ensureGiftDiamondRatioSchema(ctx context.Context, db *sql.DB) error { if _, err := db.ExecContext(ctx, ` CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', - region_id BIGINT NOT NULL DEFAULT 0 COMMENT '送礼用户区域,0 表示全局默认', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域,0 表示全局默认', gift_type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码', status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态', - ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '主播周期钻石入账比例,百分比', + ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '房间贡献热度和主播周期钻石入账比例,百分比', created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台用户 ID', 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, region_id, gift_type_code), KEY idx_gift_diamond_ratio_region (app_code, region_id, status) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物入主播周期钻石比例配置表'`); err != nil { + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物钻石和房间贡献比例配置表'`); err != nil { return err } _, err := db.ExecContext(ctx, ` @@ -127,6 +133,28 @@ func ensureGiftDiamondRatioSchema(ctx context.Context, db *sql.DB) error { return err } +func ensureCoinSellerSalaryExchangeRateSchema(ctx context.Context, db *sql.DB) error { + _, err := db.ExecContext(ctx, ` + CREATE TABLE IF NOT EXISTS coin_seller_salary_exchange_rate_tiers ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + region_id BIGINT NOT NULL COMMENT '币商所属区域 ID', + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '区间 ID', + min_usd_minor BIGINT NOT NULL COMMENT '起始美元金额,单位美分,包含', + max_usd_minor BIGINT NOT NULL COMMENT '结束美元金额,单位美分,包含', + coin_per_usd BIGINT NOT NULL COMMENT '每 1 USD 工资可兑换的币商专用金币数量', + status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '状态:active/disabled', + sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重', + created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID', + updated_by_user_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 (tier_id), + KEY idx_coin_seller_salary_rates_region (app_code, region_id, status, min_usd_minor, max_usd_minor), + KEY idx_coin_seller_salary_rates_sort (app_code, region_id, status, sort_order) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='币商工资兑换比例区间表'`) + return err +} + // Close 释放 MySQL 连接池。 func (r *Repository) Close() error { if r == nil || r.db == nil { @@ -194,7 +222,16 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if err != nil { return ledger.Receipt{}, err } - heatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) + baseHeatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) + if err != nil { + return ledger.Receipt{}, err + } + roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.RegionID, giftConfig.GiftTypeCode) + if err != nil { + return ledger.Receipt{}, err + } + // 房间贡献由房间 visible_region_id 命中后台礼物钻石比例;room-service 只消费结算后的 heat_value,不再自己查钱包配置。 + heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) if err != nil { return ledger.Receipt{}, err } @@ -231,37 +268,40 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm transactionID := transactionID(command.AppCode, command.CommandID) metadata := giftMetadata{ - AppCode: command.AppCode, - GiftID: command.GiftID, - GiftName: giftConfig.Name, - ResourceID: giftConfig.ResourceID, - ResourceSnapshot: mustJSON(giftConfig.Resource), - GiftTypeCode: giftConfig.GiftTypeCode, - PresentationJSON: giftConfig.PresentationJSON, - SortOrder: giftConfig.SortOrder, - GiftCount: command.GiftCount, - PriceVersion: price.PriceVersion, - ChargeAssetType: price.ChargeAssetType, - ChargeAmount: chargeAmount, - CoinSpent: chargeAmount, - GiftPointAdded: giftPointAdded, - HeatValue: heatValue, - BalanceAfter: sender.AvailableAmount - chargeAmount, - BillingReceipt: billingReceiptID(command.AppCode, command.CommandID), - SenderUserID: command.SenderUserID, - SenderRegionID: command.SenderRegionID, - TargetUserID: command.TargetUserID, - TargetIsHost: command.TargetIsHost, - TargetHostRegionID: command.TargetHostRegionID, - TargetAgencyOwnerUserID: command.TargetAgencyOwnerUserID, - HostPeriodDiamondAdded: hostPeriodDiamondAdded, - GiftDiamondRatioPercent: giftDiamondRatioPercent, - GiftDiamondRatioRegionID: giftDiamondRatioRegionID, - HostPeriodCycleKey: hostPeriodCycleKey, - RoomID: command.RoomID, - CoinPrice: price.CoinPrice, - GiftPointAmount: price.GiftPointAmount, - HeatUnitValue: price.HeatValue, + AppCode: command.AppCode, + GiftID: command.GiftID, + GiftName: giftConfig.Name, + ResourceID: giftConfig.ResourceID, + ResourceSnapshot: mustJSON(giftConfig.Resource), + GiftTypeCode: giftConfig.GiftTypeCode, + PresentationJSON: giftConfig.PresentationJSON, + SortOrder: giftConfig.SortOrder, + GiftCount: command.GiftCount, + PriceVersion: price.PriceVersion, + ChargeAssetType: price.ChargeAssetType, + ChargeAmount: chargeAmount, + CoinSpent: chargeAmount, + GiftPointAdded: giftPointAdded, + HeatValue: heatValue, + BalanceAfter: sender.AvailableAmount - chargeAmount, + BillingReceipt: billingReceiptID(command.AppCode, command.CommandID), + SenderUserID: command.SenderUserID, + SenderRegionID: command.SenderRegionID, + TargetUserID: command.TargetUserID, + TargetIsHost: command.TargetIsHost, + TargetHostRegionID: command.TargetHostRegionID, + TargetAgencyOwnerUserID: command.TargetAgencyOwnerUserID, + HostPeriodDiamondAdded: hostPeriodDiamondAdded, + GiftDiamondRatioPercent: giftDiamondRatioPercent, + GiftDiamondRatioRegionID: giftDiamondRatioRegionID, + HostPeriodCycleKey: hostPeriodCycleKey, + RoomID: command.RoomID, + RoomRegionID: command.RegionID, + RoomContributionRatioPercent: roomContributionRatio.Percent, + RoomContributionRatioRegionID: roomContributionRatioRegionID, + CoinPrice: price.CoinPrice, + GiftPointAmount: price.GiftPointAmount, + HeatUnitValue: price.HeatValue, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeGiftDebit, requestHash, fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { return ledger.Receipt{}, err @@ -370,7 +410,16 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb if err != nil { return ledger.BatchGiftReceipt{}, err } - heatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) + baseHeatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) + if err != nil { + return ledger.BatchGiftReceipt{}, err + } + roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.RegionID, giftConfig.GiftTypeCode) + if err != nil { + return ledger.BatchGiftReceipt{}, err + } + // 批量多目标仍然是每个目标各送一份同款礼物;每份房间贡献先按房间区域比例折算,再由聚合回执累加。 + heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) if err != nil { return ledger.BatchGiftReceipt{}, err } @@ -467,37 +516,40 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb transactionID := transactionID(command.AppCode, target.CommandID) senderAfter := sender.AvailableAmount - chargeAmount metadata := giftMetadata{ - AppCode: command.AppCode, - GiftID: command.GiftID, - GiftName: giftConfig.Name, - ResourceID: giftConfig.ResourceID, - ResourceSnapshot: mustJSON(giftConfig.Resource), - GiftTypeCode: giftConfig.GiftTypeCode, - PresentationJSON: giftConfig.PresentationJSON, - SortOrder: giftConfig.SortOrder, - GiftCount: command.GiftCount, - PriceVersion: price.PriceVersion, - ChargeAssetType: price.ChargeAssetType, - ChargeAmount: chargeAmount, - CoinSpent: chargeAmount, - GiftPointAdded: giftPointAdded, - HeatValue: heatValue, - BalanceAfter: senderAfter, - BillingReceipt: billingReceiptID(command.AppCode, target.CommandID), - SenderUserID: command.SenderUserID, - SenderRegionID: command.SenderRegionID, - TargetUserID: target.TargetUserID, - TargetIsHost: target.TargetIsHost, - TargetHostRegionID: target.TargetHostRegionID, - TargetAgencyOwnerUserID: target.TargetAgencyOwnerUserID, - HostPeriodDiamondAdded: hostPeriodDiamondAdded, - GiftDiamondRatioPercent: giftDiamondRatioPercent, - GiftDiamondRatioRegionID: giftDiamondRatioRegionID, - HostPeriodCycleKey: hostPeriodCycleKey, - RoomID: command.RoomID, - CoinPrice: price.CoinPrice, - GiftPointAmount: price.GiftPointAmount, - HeatUnitValue: price.HeatValue, + AppCode: command.AppCode, + GiftID: command.GiftID, + GiftName: giftConfig.Name, + ResourceID: giftConfig.ResourceID, + ResourceSnapshot: mustJSON(giftConfig.Resource), + GiftTypeCode: giftConfig.GiftTypeCode, + PresentationJSON: giftConfig.PresentationJSON, + SortOrder: giftConfig.SortOrder, + GiftCount: command.GiftCount, + PriceVersion: price.PriceVersion, + ChargeAssetType: price.ChargeAssetType, + ChargeAmount: chargeAmount, + CoinSpent: chargeAmount, + GiftPointAdded: giftPointAdded, + HeatValue: heatValue, + BalanceAfter: senderAfter, + BillingReceipt: billingReceiptID(command.AppCode, target.CommandID), + SenderUserID: command.SenderUserID, + SenderRegionID: command.SenderRegionID, + TargetUserID: target.TargetUserID, + TargetIsHost: target.TargetIsHost, + TargetHostRegionID: target.TargetHostRegionID, + TargetAgencyOwnerUserID: target.TargetAgencyOwnerUserID, + HostPeriodDiamondAdded: hostPeriodDiamondAdded, + GiftDiamondRatioPercent: giftDiamondRatioPercent, + GiftDiamondRatioRegionID: giftDiamondRatioRegionID, + HostPeriodCycleKey: hostPeriodCycleKey, + RoomID: command.RoomID, + RoomRegionID: command.RegionID, + RoomContributionRatioPercent: roomContributionRatio.Percent, + RoomContributionRatioRegionID: roomContributionRatioRegionID, + CoinPrice: price.CoinPrice, + GiftPointAmount: price.GiftPointAmount, + HeatUnitValue: price.HeatValue, } if err := r.insertTransaction(ctx, tx, transactionID, target.CommandID, bizTypeGiftDebit, debitRequestHash(debitGiftCommandFromBatchTarget(command, target)), fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { return ledger.BatchGiftReceipt{}, err @@ -1249,6 +1301,259 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. return receiptFromCoinSellerTransferMetadata(transactionID, metadata), nil } +// ListCoinSellerSalaryExchangeRateTiers 返回指定区域工资转币商的兑换区间;默认只返回 active 区间。 +func (r *Repository) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, appCode string, regionID int64, includeDisabled bool) ([]ledger.CoinSellerSalaryExchangeRateTier, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, appCode) + statusClause := "AND status = 'active'" + if includeDisabled { + statusClause = "" + } + query := fmt.Sprintf(` + SELECT region_id, min_usd_minor, max_usd_minor, coin_per_usd, status, sort_order, updated_at_ms + FROM coin_seller_salary_exchange_rate_tiers + WHERE app_code = ? AND region_id = ? %s + ORDER BY sort_order ASC, min_usd_minor ASC, tier_id ASC`, statusClause) + rows, err := r.db.QueryContext(ctx, query, appcode.FromContext(ctx), regionID) + if err != nil { + return nil, err + } + defer rows.Close() + + tiers := make([]ledger.CoinSellerSalaryExchangeRateTier, 0) + for rows.Next() { + var tier ledger.CoinSellerSalaryExchangeRateTier + if err := rows.Scan(&tier.RegionID, &tier.MinUSDMinor, &tier.MaxUSDMinor, &tier.CoinPerUSD, &tier.Status, &tier.SortOrder, &tier.UpdatedAtMS); err != nil { + return nil, err + } + tiers = append(tiers, tier) + } + if err := rows.Err(); err != nil { + return nil, err + } + return tiers, nil +} + +// ExchangeSalaryToCoin 在同一事务里扣工资美元钱包、给当前用户普通 COIN 入账,保证两边余额和幂等一起落库。 +func (r *Repository) ExchangeSalaryToCoin(ctx context.Context, command ledger.SalaryExchangeCommand) (ledger.SalaryExchangeReceipt, error) { + if r == nil || r.db == nil { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + requestHash := salaryExchangeRequestHash(command) + if txRow, exists, err := r.lookupTransactionWithConflictCode(ctx, tx, command.CommandID, requestHash, bizTypeSalaryExchangeToCoin, xerr.IdempotencyConflict); err != nil || exists { + if err != nil || !exists { + return ledger.SalaryExchangeReceipt{}, err + } + return r.receiptForSalaryExchangeTransaction(ctx, tx, txRow.TransactionID) + } + + nowMs := time.Now().UnixMilli() + coinAmount, err := calculateSalaryCoinAmount(command.SalaryUSDMinor, ledger.SalaryExchangeCoinPerUSD) + if err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + salaryAccount, err := r.lockAccount(ctx, tx, command.UserID, command.SalaryAssetType, false, nowMs) + if err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if salaryAccount.AvailableAmount < command.SalaryUSDMinor { + return ledger.SalaryExchangeReceipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") + } + coinAccount, err := r.lockAccount(ctx, tx, command.UserID, ledger.AssetCoin, true, nowMs) + if err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + + transactionID := transactionID(command.AppCode, command.CommandID) + salaryAfter := salaryAccount.AvailableAmount - command.SalaryUSDMinor + coinAfter, err := checkedAdd(coinAccount.AvailableAmount, coinAmount) + if err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + metadata := salaryExchangeMetadata{ + AppCode: command.AppCode, + UserID: command.UserID, + SalaryAssetType: command.SalaryAssetType, + CoinAssetType: ledger.AssetCoin, + SalaryUSDMinor: command.SalaryUSDMinor, + CoinPerUSD: ledger.SalaryExchangeCoinPerUSD, + CoinAmount: coinAmount, + SalaryBalanceAfter: salaryAfter, + CoinBalanceAfter: coinAfter, + Reason: command.Reason, + CreatedAtMS: nowMs, + } + if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeSalaryExchangeToCoin, requestHash, fmt.Sprintf("salary_exchange:%d", command.UserID), metadata, nowMs); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := r.applyAccountDelta(ctx, tx, salaryAccount, -command.SalaryUSDMinor, 0, nowMs); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, + UserID: command.UserID, + AssetType: command.SalaryAssetType, + AvailableDelta: -command.SalaryUSDMinor, + FrozenDelta: 0, + AvailableAfter: salaryAfter, + FrozenAfter: salaryAccount.FrozenAmount, + CreatedAtMS: nowMs, + }); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := r.applyAccountDelta(ctx, tx, coinAccount, coinAmount, 0, nowMs); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, + UserID: command.UserID, + AssetType: ledger.AssetCoin, + AvailableDelta: coinAmount, + FrozenDelta: 0, + AvailableAfter: coinAfter, + FrozenAfter: coinAccount.FrozenAmount, + CreatedAtMS: nowMs, + }); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + balanceChangedEvent(transactionID, command.CommandID, command.UserID, command.SalaryAssetType, -command.SalaryUSDMinor, 0, salaryAfter, salaryAccount.FrozenAmount, salaryAccount.Version+1, metadata, nowMs), + balanceChangedEvent(transactionID, command.CommandID, command.UserID, ledger.AssetCoin, coinAmount, 0, coinAfter, coinAccount.FrozenAmount, coinAccount.Version+1, metadata, nowMs), + }); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + if err := tx.Commit(); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + + return receiptFromSalaryExchangeMetadata(transactionID, metadata), nil +} + +// TransferSalaryToCoinSeller 在同一事务里扣来源工资钱包、按当前区域配置给币商专用金币库存入账。 +func (r *Repository) TransferSalaryToCoinSeller(ctx context.Context, command ledger.SalaryTransferToCoinSellerCommand) (ledger.SalaryTransferToCoinSellerReceipt, error) { + if r == nil || r.db == nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + requestHash := salaryTransferToCoinSellerRequestHash(command) + if txRow, exists, err := r.lookupTransactionWithConflictCode(ctx, tx, command.CommandID, requestHash, bizTypeSalaryTransferToCoinSeller, xerr.IdempotencyConflict); err != nil || exists { + if err != nil || !exists { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + return r.receiptForSalaryTransferToCoinSellerTransaction(ctx, tx, txRow.TransactionID) + } + + nowMs := time.Now().UnixMilli() + rate, err := r.resolveCoinSellerSalaryExchangeRateTier(ctx, tx, command.RegionID, command.SalaryUSDMinor) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + coinAmount, err := calculateSalaryCoinAmount(command.SalaryUSDMinor, rate.CoinPerUSD) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + source, err := r.lockAccount(ctx, tx, command.SourceUserID, command.SalaryAssetType, false, nowMs) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if source.AvailableAmount < command.SalaryUSDMinor { + return ledger.SalaryTransferToCoinSellerReceipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") + } + seller, err := r.lockAccount(ctx, tx, command.SellerUserID, ledger.AssetCoinSellerCoin, true, nowMs) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + + transactionID := transactionID(command.AppCode, command.CommandID) + sourceAfter := source.AvailableAmount - command.SalaryUSDMinor + sellerAfter, err := checkedAdd(seller.AvailableAmount, coinAmount) + if err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + metadata := salaryTransferToCoinSellerMetadata{ + AppCode: command.AppCode, + SourceUserID: command.SourceUserID, + SellerUserID: command.SellerUserID, + RegionID: command.RegionID, + SalaryAssetType: command.SalaryAssetType, + SellerAssetType: ledger.AssetCoinSellerCoin, + SalaryUSDMinor: command.SalaryUSDMinor, + CoinPerUSD: rate.CoinPerUSD, + CoinAmount: coinAmount, + RateMinUSDMinor: rate.MinUSDMinor, + RateMaxUSDMinor: rate.MaxUSDMinor, + SourceSalaryBalanceAfter: sourceAfter, + SellerBalanceAfter: sellerAfter, + Reason: command.Reason, + CreatedAtMS: nowMs, + } + if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeSalaryTransferToCoinSeller, requestHash, fmt.Sprintf("salary_coin_seller:%d:%d", command.SourceUserID, command.SellerUserID), metadata, nowMs); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := r.applyAccountDelta(ctx, tx, source, -command.SalaryUSDMinor, 0, nowMs); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, + UserID: command.SourceUserID, + AssetType: command.SalaryAssetType, + AvailableDelta: -command.SalaryUSDMinor, + FrozenDelta: 0, + AvailableAfter: sourceAfter, + FrozenAfter: source.FrozenAmount, + CounterpartyUserID: command.SellerUserID, + CreatedAtMS: nowMs, + }); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := r.applyAccountDelta(ctx, tx, seller, coinAmount, 0, nowMs); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, + UserID: command.SellerUserID, + AssetType: ledger.AssetCoinSellerCoin, + AvailableDelta: coinAmount, + FrozenDelta: 0, + AvailableAfter: sellerAfter, + FrozenAfter: seller.FrozenAmount, + CounterpartyUserID: command.SourceUserID, + CreatedAtMS: nowMs, + }); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + balanceChangedEvent(transactionID, command.CommandID, command.SourceUserID, command.SalaryAssetType, -command.SalaryUSDMinor, 0, sourceAfter, source.FrozenAmount, source.Version+1, metadata, nowMs), + balanceChangedEvent(transactionID, command.CommandID, command.SellerUserID, ledger.AssetCoinSellerCoin, coinAmount, 0, sellerAfter, seller.FrozenAmount, seller.Version+1, metadata, nowMs), + }); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + if err := tx.Commit(); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + + return receiptFromSalaryTransferToCoinSellerMetadata(transactionID, metadata), nil +} + type transactionRow struct { TransactionID string MetadataJSON string @@ -1437,13 +1742,13 @@ type giftDiamondRatioSnapshot struct { PPM int64 } -func (r *Repository) resolveGiftDiamondRatio(ctx context.Context, tx *sql.Tx, appCode string, senderRegionID int64, giftTypeCode string) (giftDiamondRatioSnapshot, int64, error) { +func (r *Repository) resolveGiftDiamondRatio(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, giftTypeCode string) (giftDiamondRatioSnapshot, int64, error) { giftTypeCode = strings.TrimSpace(giftTypeCode) if giftTypeCode == "" { giftTypeCode = "normal" } - regions := []int64{senderRegionID} - if senderRegionID != 0 { + regions := []int64{regionID} + if regionID != 0 { regions = append(regions, 0) } for _, regionID := range regions { @@ -1527,13 +1832,49 @@ func calculateRechargeUSDMinor(coinAmount int64, policy rechargePolicy) (int64, if err != nil { return 0, err } - if numerator%policy.CoinAmount != 0 { - // 充值金额按最小货币单位入账;不能精确换算时拒绝,避免财务口径出现隐式四舍五入。 - return 0, xerr.New(xerr.InvalidArgument, "coin amount does not match recharge policy") - } + // 金币必须完整到账;充值 USD 统计只能落到最小货币单位,不能表示的尾差向下取整。 return numerator / policy.CoinAmount, nil } +func (r *Repository) resolveCoinSellerSalaryExchangeRateTier(ctx context.Context, tx *sql.Tx, regionID int64, salaryUSDMinor int64) (ledger.CoinSellerSalaryExchangeRateTier, error) { + row := tx.QueryRowContext(ctx, + `SELECT region_id, min_usd_minor, max_usd_minor, coin_per_usd, status, sort_order, updated_at_ms + FROM coin_seller_salary_exchange_rate_tiers + WHERE app_code = ? AND region_id = ? AND status = 'active' + AND min_usd_minor <= ? AND max_usd_minor >= ? + ORDER BY sort_order ASC, min_usd_minor ASC, tier_id ASC + LIMIT 1 + FOR UPDATE`, + appcode.FromContext(ctx), + regionID, + salaryUSDMinor, + salaryUSDMinor, + ) + var tier ledger.CoinSellerSalaryExchangeRateTier + if err := row.Scan(&tier.RegionID, &tier.MinUSDMinor, &tier.MaxUSDMinor, &tier.CoinPerUSD, &tier.Status, &tier.SortOrder, &tier.UpdatedAtMS); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return ledger.CoinSellerSalaryExchangeRateTier{}, xerr.New(xerr.NotFound, "exchange rate not configured") + } + return ledger.CoinSellerSalaryExchangeRateTier{}, err + } + if tier.MinUSDMinor <= 0 || tier.MaxUSDMinor < tier.MinUSDMinor || tier.CoinPerUSD <= 0 || tier.CoinPerUSD%100 != 0 { + // 工资以美分入账,coin_per_usd 必须能被 100 整除,避免转账金币出现隐式四舍五入。 + return ledger.CoinSellerSalaryExchangeRateTier{}, xerr.New(xerr.Internal, "coin seller salary exchange rate is invalid") + } + return tier, nil +} + +func calculateSalaryCoinAmount(salaryUSDMinor int64, coinPerUSD int64) (int64, error) { + numerator, err := checkedMul(salaryUSDMinor, coinPerUSD) + if err != nil { + return 0, err + } + if numerator%100 != 0 { + return 0, xerr.New(xerr.InvalidArgument, "salary amount does not match exchange rate") + } + return numerator / 100, nil +} + func (r *Repository) insertTransaction(ctx context.Context, tx *sql.Tx, transactionID string, commandID string, bizType string, requestHash string, externalRef string, metadata any, nowMs int64) error { metadataJSON, err := json.Marshal(metadata) if err != nil { @@ -2194,39 +2535,42 @@ func (r *Repository) balanceAfterTransaction(ctx context.Context, tx *sql.Tx, tr } type giftMetadata struct { - AppCode string `json:"app_code"` - GiftID string `json:"gift_id"` - GiftName string `json:"gift_name"` - ResourceID int64 `json:"resource_id"` - ResourceSnapshot string `json:"resource_snapshot_json"` - GiftTypeCode string `json:"gift_type_code"` - PresentationJSON string `json:"presentation_json"` - SortOrder int32 `json:"sort_order"` - GiftCount int32 `json:"gift_count"` - PriceVersion string `json:"price_version"` - CoinPrice int64 `json:"coin_price"` - GiftPointAmount int64 `json:"gift_point_amount"` - HeatUnitValue int64 `json:"heat_unit_value"` - ChargeAssetType string `json:"charge_asset_type"` - ChargeAmount int64 `json:"charge_amount"` - CoinSpent int64 `json:"coin_spent"` - GiftPointAdded int64 `json:"gift_point_added"` - HeatValue int64 `json:"heat_value"` - BalanceAfter int64 `json:"balance_after"` - BillingReceipt string `json:"billing_receipt_id"` - SenderUserID int64 `json:"sender_user_id"` - SenderRegionID int64 `json:"sender_region_id"` - TargetUserID int64 `json:"target_user_id"` - TargetIsHost bool `json:"target_is_host"` - TargetHostRegionID int64 `json:"target_host_region_id"` - TargetAgencyOwnerUserID int64 `json:"target_agency_owner_user_id"` - HostPeriodDiamondAdded int64 `json:"host_period_diamond_added"` - GiftDiamondRatioPercent string `json:"gift_diamond_ratio_percent"` - GiftDiamondRatioRegionID int64 `json:"gift_diamond_ratio_region_id"` - HostPeriodDiamondAfter int64 `json:"host_period_diamond_after"` - HostPeriodDiamondVersion int64 `json:"host_period_diamond_version"` - HostPeriodCycleKey string `json:"host_period_cycle_key"` - RoomID string `json:"room_id"` + AppCode string `json:"app_code"` + GiftID string `json:"gift_id"` + GiftName string `json:"gift_name"` + ResourceID int64 `json:"resource_id"` + ResourceSnapshot string `json:"resource_snapshot_json"` + GiftTypeCode string `json:"gift_type_code"` + PresentationJSON string `json:"presentation_json"` + SortOrder int32 `json:"sort_order"` + GiftCount int32 `json:"gift_count"` + PriceVersion string `json:"price_version"` + CoinPrice int64 `json:"coin_price"` + GiftPointAmount int64 `json:"gift_point_amount"` + HeatUnitValue int64 `json:"heat_unit_value"` + ChargeAssetType string `json:"charge_asset_type"` + ChargeAmount int64 `json:"charge_amount"` + CoinSpent int64 `json:"coin_spent"` + GiftPointAdded int64 `json:"gift_point_added"` + HeatValue int64 `json:"heat_value"` + BalanceAfter int64 `json:"balance_after"` + BillingReceipt string `json:"billing_receipt_id"` + SenderUserID int64 `json:"sender_user_id"` + SenderRegionID int64 `json:"sender_region_id"` + TargetUserID int64 `json:"target_user_id"` + TargetIsHost bool `json:"target_is_host"` + TargetHostRegionID int64 `json:"target_host_region_id"` + TargetAgencyOwnerUserID int64 `json:"target_agency_owner_user_id"` + HostPeriodDiamondAdded int64 `json:"host_period_diamond_added"` + GiftDiamondRatioPercent string `json:"gift_diamond_ratio_percent"` + GiftDiamondRatioRegionID int64 `json:"gift_diamond_ratio_region_id"` + HostPeriodDiamondAfter int64 `json:"host_period_diamond_after"` + HostPeriodDiamondVersion int64 `json:"host_period_diamond_version"` + HostPeriodCycleKey string `json:"host_period_cycle_key"` + RoomID string `json:"room_id"` + RoomRegionID int64 `json:"room_region_id"` + RoomContributionRatioPercent string `json:"room_contribution_ratio_percent"` + RoomContributionRatioRegionID int64 `json:"room_contribution_ratio_region_id"` } type adminCreditMetadata struct { @@ -2304,6 +2648,38 @@ type coinSellerTransferMetadata struct { RechargePolicyUSDMinorAmount int64 `json:"recharge_policy_usd_minor_amount"` } +type salaryExchangeMetadata struct { + AppCode string `json:"app_code"` + UserID int64 `json:"user_id"` + SalaryAssetType string `json:"salary_asset_type"` + CoinAssetType string `json:"coin_asset_type"` + SalaryUSDMinor int64 `json:"salary_usd_minor"` + CoinPerUSD int64 `json:"coin_per_usd"` + CoinAmount int64 `json:"coin_amount"` + SalaryBalanceAfter int64 `json:"salary_balance_after"` + CoinBalanceAfter int64 `json:"coin_balance_after"` + Reason string `json:"reason"` + CreatedAtMS int64 `json:"created_at_ms"` +} + +type salaryTransferToCoinSellerMetadata struct { + AppCode string `json:"app_code"` + SourceUserID int64 `json:"source_user_id"` + SellerUserID int64 `json:"seller_user_id"` + RegionID int64 `json:"region_id"` + SalaryAssetType string `json:"salary_asset_type"` + SellerAssetType string `json:"seller_asset_type"` + SalaryUSDMinor int64 `json:"salary_usd_minor"` + CoinPerUSD int64 `json:"coin_per_usd"` + CoinAmount int64 `json:"coin_amount"` + RateMinUSDMinor int64 `json:"rate_min_usd_minor"` + RateMaxUSDMinor int64 `json:"rate_max_usd_minor"` + SourceSalaryBalanceAfter int64 `json:"source_salary_balance_after"` + SellerBalanceAfter int64 `json:"seller_balance_after"` + Reason string `json:"reason"` + CreatedAtMS int64 `json:"created_at_ms"` +} + type coinSellerStockMetadata struct { AppCode string `json:"app_code"` SellerUserID int64 `json:"seller_user_id"` @@ -2507,6 +2883,73 @@ func receiptFromCoinSellerTransferMetadata(transactionID string, metadata coinSe } } +func (r *Repository) receiptForSalaryExchangeTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.SalaryExchangeReceipt, error) { + var metadataJSON string + if err := tx.QueryRowContext(ctx, + `SELECT COALESCE(CAST(metadata_json AS CHAR), '{}') + FROM wallet_transactions + WHERE app_code = ? AND transaction_id = ?`, + appcode.FromContext(ctx), + transactionID, + ).Scan(&metadataJSON); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + var metadata salaryExchangeMetadata + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return ledger.SalaryExchangeReceipt{}, err + } + return receiptFromSalaryExchangeMetadata(transactionID, metadata), nil +} + +func receiptFromSalaryExchangeMetadata(transactionID string, metadata salaryExchangeMetadata) ledger.SalaryExchangeReceipt { + return ledger.SalaryExchangeReceipt{ + TransactionID: transactionID, + UserID: metadata.UserID, + SalaryAssetType: metadata.SalaryAssetType, + SalaryBalanceAfter: metadata.SalaryBalanceAfter, + CoinBalanceAfter: metadata.CoinBalanceAfter, + SalaryUSDMinor: metadata.SalaryUSDMinor, + CoinAmount: metadata.CoinAmount, + CoinPerUSD: metadata.CoinPerUSD, + CreatedAtMS: metadata.CreatedAtMS, + } +} + +func (r *Repository) receiptForSalaryTransferToCoinSellerTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.SalaryTransferToCoinSellerReceipt, error) { + var metadataJSON string + if err := tx.QueryRowContext(ctx, + `SELECT COALESCE(CAST(metadata_json AS CHAR), '{}') + FROM wallet_transactions + WHERE app_code = ? AND transaction_id = ?`, + appcode.FromContext(ctx), + transactionID, + ).Scan(&metadataJSON); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + var metadata salaryTransferToCoinSellerMetadata + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return ledger.SalaryTransferToCoinSellerReceipt{}, err + } + return receiptFromSalaryTransferToCoinSellerMetadata(transactionID, metadata), nil +} + +func receiptFromSalaryTransferToCoinSellerMetadata(transactionID string, metadata salaryTransferToCoinSellerMetadata) ledger.SalaryTransferToCoinSellerReceipt { + return ledger.SalaryTransferToCoinSellerReceipt{ + TransactionID: transactionID, + SourceUserID: metadata.SourceUserID, + SellerUserID: metadata.SellerUserID, + SalaryAssetType: metadata.SalaryAssetType, + SourceSalaryBalanceAfter: metadata.SourceSalaryBalanceAfter, + SellerBalanceAfter: metadata.SellerBalanceAfter, + SalaryUSDMinor: metadata.SalaryUSDMinor, + CoinAmount: metadata.CoinAmount, + CoinPerUSD: metadata.CoinPerUSD, + RateMinUSDMinor: metadata.RateMinUSDMinor, + RateMaxUSDMinor: metadata.RateMaxUSDMinor, + CreatedAtMS: metadata.CreatedAtMS, + } +} + func balanceChangedEvent(transactionID string, commandID string, userID int64, assetType string, availableDelta int64, frozenDelta int64, availableAfter int64, frozenAfter int64, balanceVersion int64, payload any, nowMs int64) walletOutboxEvent { return walletOutboxEvent{ EventID: eventID(transactionID, "WalletBalanceChanged", userID, assetType), @@ -2940,6 +3383,28 @@ func coinSellerTransferRequestHash(command ledger.CoinSellerTransferCommand) str )) } +func salaryExchangeRequestHash(command ledger.SalaryExchangeCommand) string { + return stableHash(fmt.Sprintf("salary_exchange|%s|%d|%s|%d|%s", + appcode.Normalize(command.AppCode), + command.UserID, + strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)), + command.SalaryUSDMinor, + strings.TrimSpace(command.Reason), + )) +} + +func salaryTransferToCoinSellerRequestHash(command ledger.SalaryTransferToCoinSellerCommand) string { + return stableHash(fmt.Sprintf("salary_transfer_coin_seller|%s|%d|%d|%s|%d|%d|%s", + appcode.Normalize(command.AppCode), + command.SourceUserID, + command.SellerUserID, + strings.ToUpper(strings.TrimSpace(command.SalaryAssetType)), + command.SalaryUSDMinor, + command.RegionID, + strings.TrimSpace(command.Reason), + )) +} + func coinSellerStockBizType(stockType string) string { switch stockType { case ledger.StockTypeUSDTPurchase: diff --git a/services/wallet-service/internal/storage/mysql/resource_repository.go b/services/wallet-service/internal/storage/mysql/resource_repository.go index 149b2754..213181a7 100644 --- a/services/wallet-service/internal/storage/mysql/resource_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_repository.go @@ -237,9 +237,15 @@ func (r *Repository) UpdateResource(ctx context.Context, command resourcedomain. if err != nil { return resourcedomain.Resource{}, err } - if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + events := []walletOutboxEvent{ resourceOutboxEvent("ResourceChanged", fmt.Sprintf("resource:%d:update:%d", command.ResourceID, nowMs), 0, command.ResourceID, resource, nowMs), - }); err != nil { + } + giftEvents, err := r.syncGiftPricesForResourceTx(ctx, tx, resource, nowMs) + if err != nil { + return resourcedomain.Resource{}, err + } + events = append(events, giftEvents...) + if err := r.insertWalletOutbox(ctx, tx, events); err != nil { return resourcedomain.Resource{}, err } if err := tx.Commit(); err != nil { @@ -248,6 +254,77 @@ func (r *Repository) UpdateResource(ctx context.Context, command resourcedomain. return resource, nil } +func (r *Repository) syncGiftPricesForResourceTx(ctx context.Context, tx *sql.Tx, resource resourcedomain.Resource, nowMs int64) ([]walletOutboxEvent, error) { + // 礼物资源的价格是后台编辑入口,实际送礼扣费读取 wallet_gift_prices。 + // 因此资源价格变更后,必须在同一个事务内把已绑定礼物的 active 价格同步过去, + // 同时发 GiftConfigChanged outbox,让依赖礼物配置快照的下游可以刷新缓存。 + if resource.ResourceType != resourcedomain.TypeGift { + return nil, nil + } + priceType := resourcedomain.NormalizePriceType(resource.PriceType) + if priceType != resourcedomain.PriceTypeCoin && priceType != resourcedomain.PriceTypeFree { + return nil, nil + } + rows, err := tx.QueryContext(ctx, ` + SELECT gift_id + FROM gift_configs + WHERE app_code = ? AND resource_id = ? + ORDER BY gift_id`, + appcode.FromContext(ctx), resource.ResourceID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + giftIDs := make([]string, 0) + for rows.Next() { + var giftID string + if err := rows.Scan(&giftID); err != nil { + return nil, err + } + giftIDs = append(giftIDs, giftID) + } + if err := rows.Err(); err != nil { + return nil, err + } + if len(giftIDs) == 0 { + return nil, nil + } + + coinPrice := int64(0) + giftPointAmount := int64(0) + if priceType == resourcedomain.PriceTypeCoin { + coinPrice = resource.CoinPrice + giftPointAmount = resource.GiftPointAmount + } + if _, err := tx.ExecContext(ctx, ` + UPDATE wallet_gift_prices gp + JOIN gift_configs gc ON gc.app_code = gp.app_code AND gc.gift_id = gp.gift_id + SET gp.charge_asset_type = ?, gp.coin_price = ?, gp.gift_point_amount = ?, gp.updated_at_ms = ? + WHERE gc.app_code = ? AND gc.resource_id = ? AND gp.status = 'active'`, + ledger.AssetCoin, coinPrice, giftPointAmount, nowMs, appcode.FromContext(ctx), resource.ResourceID, + ); err != nil { + return nil, err + } + events := make([]walletOutboxEvent, 0, len(giftIDs)) + for _, giftID := range giftIDs { + events = append(events, resourceOutboxEvent( + "GiftConfigChanged", + fmt.Sprintf("gift:%s:resource_price:%d", giftID, nowMs), + 0, + resource.ResourceID, + map[string]any{ + "gift_id": giftID, + "resource_id": resource.ResourceID, + "coin_price": coinPrice, + "gift_point_amount": giftPointAmount, + }, + nowMs, + )) + } + return events, nil +} + func (r *Repository) SetResourceStatus(ctx context.Context, command resourcedomain.StatusCommand) (resourcedomain.Resource, error) { if r == nil || r.db == nil { return resourcedomain.Resource{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") diff --git a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go index 5310e7be..ab36ea93 100644 --- a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go @@ -331,6 +331,26 @@ func (r *Repository) SetAssetBalance(userID int64, assetType string, balance int } } +// SetCoinSellerSalaryExchangeRateTier seeds an active salary transfer tier for coin seller transfer tests. +func (r *Repository) SetCoinSellerSalaryExchangeRateTier(appCode string, regionID int64, minUSDMinor int64, maxUSDMinor int64, coinPerUSD int64) { + r.t.Helper() + + nowMs := time.Now().UnixMilli() + _, err := r.schema.DB.ExecContext(context.Background(), ` + INSERT INTO coin_seller_salary_exchange_rate_tiers ( + app_code, region_id, min_usd_minor, max_usd_minor, coin_per_usd, + status, sort_order, created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, 'active', 10, 0, 0, ?, ?) + ON DUPLICATE KEY UPDATE + coin_per_usd = VALUES(coin_per_usd), + status = VALUES(status), + updated_at_ms = VALUES(updated_at_ms) + `, appCode, regionID, minUSDMinor, maxUSDMinor, coinPerUSD, nowMs, nowMs) + if err != nil { + r.t.Fatalf("seed coin seller salary exchange rate tier failed: %v", err) + } +} + // SetGiftPrice overrides or inserts a gift settlement price for server-side billing tests. func (r *Repository) SetGiftPrice(giftID string, priceVersion string, coinPrice int64, giftPointAmount int64, heatValue int64) { r.t.Helper() @@ -410,7 +430,7 @@ func (r *Repository) SetGiftType(giftID string, giftTypeCode string) { } } -// SetGiftDiamondRatio configures the host-period diamond ratio for a sender region and gift type. +// SetGiftDiamondRatio configures the gift diamond ratio for a room region and gift type. func (r *Repository) SetGiftDiamondRatio(regionID int64, giftTypeCode string, ratioPercent string) { r.t.Helper() nowMs := time.Now().UnixMilli() diff --git a/services/wallet-service/internal/transport/grpc/server.go b/services/wallet-service/internal/transport/grpc/server.go index ba597bec..90286512 100644 --- a/services/wallet-service/internal/transport/grpc/server.go +++ b/services/wallet-service/internal/transport/grpc/server.go @@ -862,3 +862,77 @@ func (s *Server) TransferCoinFromSeller(ctx context.Context, req *walletv1.Trans RechargePolicyUsdMinorAmount: receipt.RechargePolicyUSDMinorUnit, }, nil } + +// ListCoinSellerSalaryExchangeRateTiers 返回工资转币商使用的区域比例区间,调用方用它做预计到账展示。 +func (s *Server) ListCoinSellerSalaryExchangeRateTiers(ctx context.Context, req *walletv1.ListCoinSellerSalaryExchangeRateTiersRequest) (*walletv1.ListCoinSellerSalaryExchangeRateTiersResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + tiers, err := s.svc.ListCoinSellerSalaryExchangeRateTiers(ctx, req.GetAppCode(), req.GetRegionId(), req.GetIncludeDisabled()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + response := &walletv1.ListCoinSellerSalaryExchangeRateTiersResponse{Tiers: make([]*walletv1.CoinSellerSalaryExchangeRateTier, 0, len(tiers))} + for _, tier := range tiers { + response.Tiers = append(response.Tiers, &walletv1.CoinSellerSalaryExchangeRateTier{ + RegionId: tier.RegionID, + MinUsdMinor: tier.MinUSDMinor, + MaxUsdMinor: tier.MaxUSDMinor, + CoinPerUsd: tier.CoinPerUSD, + Status: tier.Status, + SortOrder: int32(tier.SortOrder), + UpdatedAtMs: tier.UpdatedAtMS, + }) + } + return response, nil +} + +// ExchangeSalaryToCoin 处理用户工资兑换普通金币,身份资产已经由 gateway 校验并注入。 +func (s *Server) ExchangeSalaryToCoin(ctx context.Context, req *walletv1.ExchangeSalaryToCoinRequest) (*walletv1.ExchangeSalaryToCoinResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + receipt, err := s.svc.ExchangeSalaryToCoin(ctx, ledger.SalaryExchangeCommand{ + AppCode: req.GetAppCode(), + CommandID: req.GetCommandId(), + UserID: req.GetUserId(), + SalaryAssetType: req.GetSalaryAssetType(), + SalaryUSDMinor: req.GetSalaryUsdMinor(), + Reason: req.GetReason(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.ExchangeSalaryToCoinResponse{ + TransactionId: receipt.TransactionID, + SalaryBalanceAfter: receipt.SalaryBalanceAfter, + CoinBalanceAfter: receipt.CoinBalanceAfter, + SalaryUsdMinor: receipt.SalaryUSDMinor, + CoinAmount: receipt.CoinAmount, + CoinPerUsd: receipt.CoinPerUSD, + }, nil +} + +// TransferSalaryToCoinSeller 处理用户工资转同区域币商专用金币库存。 +func (s *Server) TransferSalaryToCoinSeller(ctx context.Context, req *walletv1.TransferSalaryToCoinSellerRequest) (*walletv1.TransferSalaryToCoinSellerResponse, error) { + ctx = appcode.WithContext(ctx, req.GetAppCode()) + receipt, err := s.svc.TransferSalaryToCoinSeller(ctx, ledger.SalaryTransferToCoinSellerCommand{ + AppCode: req.GetAppCode(), + CommandID: req.GetCommandId(), + SourceUserID: req.GetSourceUserId(), + SellerUserID: req.GetSellerUserId(), + SalaryAssetType: req.GetSalaryAssetType(), + SalaryUSDMinor: req.GetSalaryUsdMinor(), + RegionID: req.GetRegionId(), + Reason: req.GetReason(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &walletv1.TransferSalaryToCoinSellerResponse{ + TransactionId: receipt.TransactionID, + SourceSalaryBalanceAfter: receipt.SourceSalaryBalanceAfter, + SellerBalanceAfter: receipt.SellerBalanceAfter, + SalaryUsdMinor: receipt.SalaryUSDMinor, + CoinAmount: receipt.CoinAmount, + CoinPerUsd: receipt.CoinPerUSD, + RateMinUsdMinor: receipt.RateMinUSDMinor, + RateMaxUsdMinor: receipt.RateMaxUSDMinor, + }, nil +} From 90ea9d706d89475bbe6657b5a41608c77631c1aa Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 4 Jun 2026 23:06:51 +0800 Subject: [PATCH 12/28] Record coin seller transfers without recharge policy --- .../internal/transport/http/response_test.go | 14 ++++---- .../internal/service/wallet/service_test.go | 34 +++++++++---------- .../internal/storage/mysql/repository.go | 22 +++++------- .../internal/testutil/mysqltest/mysqltest.go | 2 +- 4 files changed, 33 insertions(+), 39 deletions(-) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 7295e608..efe68243 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -5590,12 +5590,12 @@ func TestCoinSellerTransferChecksIdentityAndPropagatesWalletCommand(t *testing.T SellerBalanceAfter: 80000, TargetBalanceAfter: 80000, Amount: 80000, - RechargeUsdMinor: 100, - RechargeCurrencyCode: "USD", - RechargePolicyId: 7, - RechargePolicyVersion: "recharge-v1", - RechargePolicyCoinAmount: 80000, - RechargePolicyUsdMinorAmount: 100, + RechargeUsdMinor: 0, + RechargeCurrencyCode: "", + RechargePolicyId: 0, + RechargePolicyVersion: "", + RechargePolicyCoinAmount: 0, + RechargePolicyUsdMinorAmount: 0, }} hostClient := &fakeUserHostClient{profile: &userv1.CoinSellerProfile{ UserId: 42, @@ -5642,7 +5642,7 @@ func TestCoinSellerTransferChecksIdentityAndPropagatesWalletCommand(t *testing.T t.Fatalf("decode response failed: %v", err) } data, ok := response.Data.(map[string]any) - if response.Code != httpkit.CodeOK || !ok || data["transaction_id"] != "wtx-coin-seller" || data["seller_balance_after"] != float64(80000) || data["recharge_usd_minor"] != float64(100) { + if response.Code != httpkit.CodeOK || !ok || data["transaction_id"] != "wtx-coin-seller" || data["seller_balance_after"] != float64(80000) || data["recharge_usd_minor"] != float64(0) || data["recharge_policy_id"] != float64(0) { t.Fatalf("coin seller transfer response mismatch: %+v", response) } } diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 58dd535d..f312ba9a 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -1568,7 +1568,6 @@ func TestCreditLuckyGiftRewardIsIdempotent(t *testing.T) { func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) - repository.SetRechargePolicy(1001, "recharge-v1", 80000, 100) _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ CommandID: "cmd-credit-seller", TargetUserID: 30001, @@ -1599,7 +1598,7 @@ func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { if err != nil { t.Fatalf("TransferCoinFromSeller retry failed: %v", err) } - if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SellerBalanceAfter != 80000 || first.TargetBalanceAfter != 80000 || first.RechargeUSDMinor != 100 { + if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SellerBalanceAfter != 80000 || first.TargetBalanceAfter != 80000 || first.RechargeUSDMinor != 0 { t.Fatalf("transfer receipt mismatch: first=%+v second=%+v", first, second) } @@ -1635,7 +1634,6 @@ func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { func TestTransferCoinFromSellerAllowsSelfTransfer(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) - repository.SetRechargePolicy(1001, "recharge-v1", 30000, 100) _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ CommandID: "cmd-credit-self-seller", TargetUserID: 30003, @@ -1666,7 +1664,7 @@ func TestTransferCoinFromSellerAllowsSelfTransfer(t *testing.T) { if err != nil { t.Fatalf("TransferCoinFromSeller self transfer retry failed: %v", err) } - if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SellerBalanceAfter != 70000 || first.TargetBalanceAfter != 30000 || first.RechargeUSDMinor != 100 { + if first.TransactionID == "" || first.TransactionID != second.TransactionID || first.SellerBalanceAfter != 70000 || first.TargetBalanceAfter != 30000 || first.RechargeUSDMinor != 0 { t.Fatalf("self transfer receipt mismatch: first=%+v second=%+v", first, second) } @@ -1691,11 +1689,10 @@ func TestTransferCoinFromSellerAllowsSelfTransfer(t *testing.T) { } } -// TestTransferCoinFromSellerAllowsSubCentRechargeAmount 验证小额金币也必须到账,美元统计按最小货币单位向下取整。 -func TestTransferCoinFromSellerAllowsSubCentRechargeAmount(t *testing.T) { +// TestTransferCoinFromSellerRecordsCoinsWithoutUSDConversion 验证币商转账只按金币记录充值事实,不再走 USD 换算。 +func TestTransferCoinFromSellerRecordsCoinsWithoutUSDConversion(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) - repository.SetRechargePolicy(1001, "recharge-v1", 1000, 100) _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ CommandID: "cmd-credit-small-seller", TargetUserID: 30004, @@ -1731,7 +1728,7 @@ func TestTransferCoinFromSellerAllowsSubCentRechargeAmount(t *testing.T) { if balanceAmount(balances, ledger.AssetCoinSellerCoin) != 10 || balanceAmount(balances, ledger.AssetCoin) != 1 { t.Fatalf("small transfer balances mismatch: %+v", balances) } - if got := repository.CountRows("wallet_recharge_records", "transaction_id = ? AND coin_amount = ? AND usd_minor_amount = ?", receipt.TransactionID, int64(1), int64(0)); got != 1 { + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ? AND coin_amount = ? AND usd_minor_amount = ? AND policy_id = ? AND policy_version = ? AND exchange_coin_amount = ? AND exchange_usd_minor_amount = ?", receipt.TransactionID, int64(1), int64(0), int64(0), "", int64(1), int64(0)); got != 1 { t.Fatalf("small transfer should write recharge record with zero USD minor, got %d", got) } } @@ -1758,8 +1755,8 @@ func TestTransferCoinFromSellerInsufficientBalance(t *testing.T) { } } -// TestTransferCoinFromSellerRequiresRechargePolicy 验证缺少区域充值政策时不会产生半成品充值事实。 -func TestTransferCoinFromSellerRequiresRechargePolicy(t *testing.T) { +// TestTransferCoinFromSellerDoesNotRequireRechargePolicy 验证币商转账不依赖外部充值定价策略。 +func TestTransferCoinFromSellerDoesNotRequireRechargePolicy(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) _, _, err := svc.AdminCreditAsset(context.Background(), ledger.AdminCreditAssetCommand{ @@ -1775,7 +1772,7 @@ func TestTransferCoinFromSellerRequiresRechargePolicy(t *testing.T) { t.Fatalf("seed seller asset failed: %v", err) } - _, err = svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ + receipt, err := svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ CommandID: "cmd-seller-no-policy", SellerUserID: 32001, TargetUserID: 32002, @@ -1784,14 +1781,17 @@ func TestTransferCoinFromSellerRequiresRechargePolicy(t *testing.T) { Amount: 80000, Reason: "player recharge", }) - if !xerr.IsCode(err, xerr.NotFound) { - t.Fatalf("expected NOT_FOUND when recharge policy is missing, got %v", err) + if err != nil { + t.Fatalf("TransferCoinFromSeller without recharge policy failed: %v", err) } - if got := repository.CountRows("wallet_transactions", "command_id = ?", "cmd-seller-no-policy"); got != 0 { - t.Fatalf("missing recharge policy must not write transaction, got %d", got) + if receipt.RechargeUSDMinor != 0 || receipt.RechargePolicyID != 0 || receipt.RechargePolicyVersion != "" { + t.Fatalf("policy-free transfer receipt mismatch: %+v", receipt) } - if got := repository.CountRows("wallet_recharge_records", "transaction_id LIKE ?", "wtx_%"); got != 0 { - t.Fatalf("missing recharge policy must not write recharge record, got %d", got) + if got := repository.CountRows("wallet_transactions", "command_id = ?", "cmd-seller-no-policy"); got != 1 { + t.Fatalf("policy-free seller transfer should write transaction, got %d", got) + } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ? AND coin_amount = ? AND usd_minor_amount = ? AND policy_id = ?", receipt.TransactionID, int64(80000), int64(0), int64(0)); got != 1 { + t.Fatalf("policy-free seller transfer should write coin-only recharge record, got %d", got) } } diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index a1810858..6e87b2c8 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -1214,14 +1214,8 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. } transactionID := transactionID(command.AppCode, command.CommandID) - policy, err := r.resolveRechargePolicy(ctx, tx, command.TargetRegionID, nowMs) - if err != nil { - return ledger.CoinSellerTransferReceipt{}, err - } - rechargeUSDMinor, err := calculateRechargeUSDMinor(command.Amount, policy) - if err != nil { - return ledger.CoinSellerTransferReceipt{}, err - } + // 币商转账的事实口径只记录金币数量;USD 价格策略属于外部充值定价,不参与币商库存转普通金币。 + rechargeUSDMinor := int64(0) rechargeSequence, err := r.reserveUserRechargeSequence(ctx, tx, command.AppCode, command.TargetUserID, transactionID, command.Amount, rechargeUSDMinor, nowMs) if err != nil { return ledger.CoinSellerTransferReceipt{}, err @@ -1242,11 +1236,11 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. TargetBalanceAfter: targetAfter, RechargeSequence: rechargeSequence, RechargeUSDMinor: rechargeUSDMinor, - RechargeCurrencyCode: policy.CurrencyCode, - RechargePolicyID: policy.PolicyID, - RechargePolicyVersion: policy.PolicyVersion, - RechargePolicyCoinAmount: policy.CoinAmount, - RechargePolicyUSDMinorAmount: policy.USDMinorAmount, + RechargeCurrencyCode: "", + RechargePolicyID: 0, + RechargePolicyVersion: "", + RechargePolicyCoinAmount: 0, + RechargePolicyUSDMinorAmount: 0, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeCoinSellerTransfer, requestHash, fmt.Sprintf("coin_seller:%d:%d", command.SellerUserID, command.TargetUserID), metadata, nowMs); err != nil { return ledger.CoinSellerTransferReceipt{}, err @@ -1917,7 +1911,7 @@ func (r *Repository) insertRechargeRecord(ctx context.Context, tx *sql.Tx, trans metadata.RechargeCurrencyCode, metadata.Amount, metadata.RechargeUSDMinor, - metadata.RechargePolicyCoinAmount, + metadata.Amount, metadata.RechargePolicyUSDMinorAmount, nowMs, ) diff --git a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go index ab36ea93..a5ece288 100644 --- a/services/wallet-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/wallet-service/internal/testutil/mysqltest/mysqltest.go @@ -449,7 +449,7 @@ func (r *Repository) SetGiftDiamondRatio(regionID int64, giftTypeCode string, ra } } -// SetRechargePolicy 配置区域充值汇率,用于币商转账充值口径测试。 +// SetRechargePolicy 配置区域充值定价,用于外部充值类事实测试。 func (r *Repository) SetRechargePolicy(regionID int64, policyVersion string, coinAmount int64, usdMinorAmount int64) { r.t.Helper() From 7a59d3571cf08dcf62690ceb2a2c9b50a36baf6f Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 12:09:37 +0800 Subject: [PATCH 13/28] Update gift ratios and production service changes --- .../037_gift_diamond_global_defaults.sql | 18 ++ server/admin/cmd/server/main.go | 2 +- .../admin/configs/config.tencent.example.yaml | 2 +- .../internal/integration/userclient/client.go | 1 + .../internal/modules/giftdiamond/service.go | 17 +- .../admin/internal/modules/hostorg/reader.go | 44 +++- .../admin/internal/modules/hostorg/request.go | 4 +- .../admin/internal/modules/hostorg/service.go | 26 ++- .../internal/modules/luckygift/handler.go | 2 +- server/admin/internal/modules/payment/dto.go | 96 +++++++-- .../admin/internal/modules/payment/handler.go | 66 +++++- .../mysql/initdb/001_activity_service.sql | 105 ++++------ .../internal/service/luckygift/config.go | 192 ------------------ .../internal/service/luckygift/config_test.go | 60 ------ .../storage/mysql/lucky_gift_repository.go | 62 ------ .../internal/storage/mysql/repository.go | 70 ++++--- .../internal/room/service/gift.go | 11 +- .../room/service/gift_leaderboard_test.go | 81 ++++++++ .../internal/room/service/pipeline.go | 2 +- .../room/service/room_gift_leaderboard.go | 9 +- .../internal/room/service/service.go | 6 +- .../statistics-service/internal/app/app.go | 32 ++- .../internal/app/local_flow_test.go | 2 +- .../internal/service/host/commands.go | 8 +- .../internal/service/host/service.go | 18 +- .../internal/service/host/service_test.go | 42 ++++ .../internal/storage/mysql/host/admin.go | 46 +++-- .../mysql/initdb/001_wallet_service.sql | 4 +- .../internal/service/wallet/service_test.go | 38 ++-- .../mysql/google_payment_repository.go | 17 +- .../internal/storage/mysql/repository.go | 34 +++- 31 files changed, 598 insertions(+), 519 deletions(-) create mode 100644 scripts/mysql/037_gift_diamond_global_defaults.sql create mode 100644 services/room-service/internal/room/service/gift_leaderboard_test.go diff --git a/scripts/mysql/037_gift_diamond_global_defaults.sql b/scripts/mysql/037_gift_diamond_global_defaults.sql new file mode 100644 index 00000000..4219de83 --- /dev/null +++ b/scripts/mysql/037_gift_diamond_global_defaults.sql @@ -0,0 +1,18 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +USE hyapp_wallet; + +SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +INSERT INTO gift_diamond_ratio_configs ( + app_code, region_id, gift_type_code, status, ratio_percent, + created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms +) VALUES + ('lalu', 0, 'normal', 'active', 100.00, 0, 0, @now_ms, @now_ms), + ('lalu', 0, 'lucky', 'active', 10.00, 0, 0, @now_ms, @now_ms), + ('lalu', 0, 'super_lucky', 'active', 1.00, 0, 0, @now_ms, @now_ms) +ON DUPLICATE KEY UPDATE + status = VALUES(status), + ratio_percent = VALUES(ratio_percent), + updated_by_admin_id = VALUES(updated_by_admin_id), + updated_at_ms = VALUES(updated_at_ms); diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index 1d1f6aec..c7912c59 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -239,7 +239,7 @@ func main() { LevelConfig: levelconfigmodule.New(activityclient.NewGRPC(activityConn), walletclient.NewGRPC(walletConn), auditHandler), LuckyGift: luckygiftmodule.New(activityclient.NewGRPC(activityConn), cfg.ActivityService.RequestTimeout, auditHandler), Menu: menumodule.New(store, auditHandler), - Payment: paymentmodule.New(walletclient.NewGRPC(walletConn), auditHandler), + Payment: paymentmodule.New(walletclient.NewGRPC(walletConn), userDB, auditHandler), RBAC: rbacmodule.New(store, auditHandler), RedPacket: redpacketmodule.New(walletclient.NewGRPC(walletConn), auditHandler), Report: reportmodule.New(userDB, roomClient), diff --git a/server/admin/configs/config.tencent.example.yaml b/server/admin/configs/config.tencent.example.yaml index 78edae8a..3276871b 100644 --- a/server/admin/configs/config.tencent.example.yaml +++ b/server/admin/configs/config.tencent.example.yaml @@ -36,7 +36,7 @@ bootstrap: password: "REPLACE_WITH_TEMP_BOOTSTRAP_PASSWORD" user_service: addr: "10.2.1.16:13005" - request_timeout: "3s" + request_timeout: "10s" wallet_service: addr: "10.2.1.15:13004" request_timeout: "3s" diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 7a295a76..42c8d105 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -400,6 +400,7 @@ type HostProfile struct { Avatar string `json:"avatar"` RegionName string `json:"regionName"` CurrentAgencyName string `json:"currentAgencyName"` + Diamond int64 `json:"diamond"` } type CoinSellerProfile struct { diff --git a/server/admin/internal/modules/giftdiamond/service.go b/server/admin/internal/modules/giftdiamond/service.go index 6a21664c..a68000cf 100644 --- a/server/admin/internal/modules/giftdiamond/service.go +++ b/server/admin/internal/modules/giftdiamond/service.go @@ -91,7 +91,7 @@ func (s *Service) resolveRatio(ctx context.Context, appCode string, regionID int return item, err } } - return ratioDTO{GiftTypeCode: giftType, RatioPercent: "100.00", RegionID: regionID, EffectiveRegionID: 0, Status: statusActive}, nil + return ratioDTO{GiftTypeCode: giftType, RatioPercent: defaultRatioPercent(giftType), RegionID: regionID, EffectiveRegionID: 0, Status: statusActive}, nil } func (s *Service) getRatio(ctx context.Context, appCode string, regionID int64, giftType string) (ratioDTO, bool, error) { @@ -133,6 +133,17 @@ func formatPercentString(raw string) string { return fmt.Sprintf("%.2f", value) } +func defaultRatioPercent(giftType string) string { + switch strings.TrimSpace(giftType) { + case "lucky": + return "10.00" + case "super_lucky": + return "1.00" + default: + return "100.00" + } +} + func (s *Service) ensureSchema(ctx context.Context) error { if s == nil || s.db == nil { return errors.New("wallet db is not configured") @@ -159,8 +170,8 @@ func (s *Service) ensureSchema(ctx context.Context) error { created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms ) VALUES (?, 0, 'normal', 'active', 100.00, 0, 0, 0, 0), - (?, 0, 'lucky', 'active', 100.00, 0, 0, 0, 0), - (?, 0, 'super_lucky', 'active', 100.00, 0, 0, 0, 0)`, + (?, 0, 'lucky', 'active', 10.00, 0, 0, 0, 0), + (?, 0, 'super_lucky', 'active', 1.00, 0, 0, 0, 0)`, "lalu", "lalu", "lalu") return err } diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index 23d7227a..46cccc47 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -382,6 +382,7 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user defer rows.Close() items := make([]*userclient.HostProfile, 0, query.PageSize) + userIDs := make([]int64, 0, query.PageSize) for rows.Next() { item := &userclient.HostProfile{} if err := rows.Scan( @@ -403,8 +404,19 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user return nil, 0, err } items = append(items, item) + userIDs = append(userIDs, item.UserID) } - return items, total, rows.Err() + if err := rows.Err(); err != nil { + return nil, 0, err + } + diamonds, err := r.hostPeriodDiamonds(ctx, appCode, userIDs) + if err != nil { + return nil, 0, err + } + for _, item := range items { + item.Diamond = diamonds[item.UserID] + } + return items, total, nil } // ListCoinSellers 聚合 user-service 身份事实和 wallet-service 币商余额,只做后台展示读模型。 @@ -676,6 +688,36 @@ func (r *Reader) coinSellerBalances(ctx context.Context, appCode string, userIDs return result, rows.Err() } +func (r *Reader) hostPeriodDiamonds(ctx context.Context, appCode string, userIDs []int64) (map[int64]int64, error) { + result := make(map[int64]int64, len(userIDs)) + if r == nil || r.walletDB == nil || len(userIDs) == 0 { + return result, nil + } + placeholders := strings.TrimRight(strings.Repeat("?,", len(userIDs)), ",") + args := []any{appCode, time.Now().UTC().Format("2006-01")} + for _, userID := range userIDs { + args = append(args, userID) + } + rows, err := r.walletDB.QueryContext(ctx, fmt.Sprintf(` + SELECT user_id, total_diamonds + FROM host_period_diamond_accounts + WHERE app_code = ? AND cycle_key = ? AND user_id IN (%s) + `, placeholders), args...) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var userID int64 + var amount int64 + if err := rows.Scan(&userID, &amount); err != nil { + return nil, err + } + result[userID] = amount + } + return result, rows.Err() +} + func sqlPlaceholders(count int) string { if count <= 0 { return "" diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index 89c01e88..aa6b2ad9 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -21,7 +21,7 @@ type createBDLeaderRequest struct { type createBDRequest struct { CommandID string `json:"commandId" binding:"required"` TargetUserID int64 `json:"targetUserId" binding:"required"` - ParentLeaderUserID int64 `json:"parentLeaderUserId" binding:"required"` + ParentLeaderUserID int64 `json:"parentLeaderUserId"` Reason string `json:"reason"` } @@ -73,7 +73,7 @@ type coinSellerSalaryRateTierRequest struct { type createAgencyRequest struct { CommandID string `json:"commandId" binding:"required"` OwnerUserID int64 `json:"ownerUserId" binding:"required"` - ParentBDUserID int64 `json:"parentBdUserId" binding:"required"` + ParentBDUserID int64 `json:"parentBdUserId"` Name string `json:"name" binding:"required"` JoinEnabled *bool `json:"joinEnabled" binding:"required"` MaxHosts int32 `json:"maxHosts"` diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index e9bc87ad..adeea825 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -135,9 +135,16 @@ func (s *Service) CreateBD(ctx context.Context, actorID int64, requestID string, if err != nil { return nil, err } - parentLeaderUserID, err := s.resolveDisplayUserID(ctx, requestID, req.ParentLeaderUserID) - if err != nil { - return nil, err + parentLeaderUserID := int64(0) + if req.ParentLeaderUserID < 0 { + return nil, fmt.Errorf("parent_leader_user_id must not be negative") + } + if req.ParentLeaderUserID > 0 { + // 父级 Leader 是可选关系;传入短 ID 时才解析成内部 user_id,未传时保留 0 表示独立 BD。 + parentLeaderUserID, err = s.resolveDisplayUserID(ctx, requestID, req.ParentLeaderUserID) + if err != nil { + return nil, err + } } return s.userClient.CreateBD(ctx, userclient.CreateBDRequest{ RequestID: requestID, @@ -281,9 +288,16 @@ func (s *Service) CreateAgency(ctx context.Context, actorID int64, requestID str if err != nil { return nil, err } - parentBDUserID, err := s.resolveDisplayUserID(ctx, requestID, req.ParentBDUserID) - if err != nil { - return nil, err + parentBDUserID := int64(0) + if req.ParentBDUserID < 0 { + return nil, fmt.Errorf("parent_bd_user_id must not be negative") + } + if req.ParentBDUserID > 0 { + // 父级 BD 是可选关系;传入短 ID 时才解析成内部 user_id,未传时保留 0 表示独立 Agency。 + parentBDUserID, err = s.resolveDisplayUserID(ctx, requestID, req.ParentBDUserID) + if err != nil { + return nil, err + } } joinEnabled := false if req.JoinEnabled != nil { diff --git a/server/admin/internal/modules/luckygift/handler.go b/server/admin/internal/modules/luckygift/handler.go index c23ba0ea..32c53011 100644 --- a/server/admin/internal/modules/luckygift/handler.go +++ b/server/admin/internal/modules/luckygift/handler.go @@ -147,7 +147,7 @@ func (h *Handler) UpsertLuckyGiftConfig(c *gin.Context) { return } item := configFromProto(resp.GetConfig()) - shared.OperationLogWithResourceID(c, h.audit, "upsert-lucky-gift-config", "lucky_gift_rules", item.PoolID, "success", "") + shared.OperationLogWithResourceID(c, h.audit, "upsert-lucky-gift-config", "lucky_gift_rule_versions", item.PoolID, "success", "") response.OK(c, item) } diff --git a/server/admin/internal/modules/payment/dto.go b/server/admin/internal/modules/payment/dto.go index d6fd1387..feb29e78 100644 --- a/server/admin/internal/modules/payment/dto.go +++ b/server/admin/internal/modules/payment/dto.go @@ -9,24 +9,33 @@ import ( ) type rechargeBillDTO struct { - AppCode string `json:"appCode"` - TransactionID string `json:"transactionId"` - CommandID string `json:"commandId"` - RechargeType string `json:"rechargeType"` - Status string `json:"status"` - ExternalRef string `json:"externalRef"` - UserID int64 `json:"userId"` - SellerUserID int64 `json:"sellerUserId"` - SellerRegionID int64 `json:"sellerRegionId"` - TargetRegionID int64 `json:"targetRegionId"` - PolicyID int64 `json:"policyId"` - PolicyVersion string `json:"policyVersion"` - CurrencyCode string `json:"currencyCode"` - CoinAmount int64 `json:"coinAmount"` - USDMinorAmount int64 `json:"usdMinorAmount"` - ExchangeCoinAmount int64 `json:"exchangeCoinAmount"` - ExchangeUSDMinorAmount int64 `json:"exchangeUsdMinorAmount"` - CreatedAtMS int64 `json:"createdAtMs"` + AppCode string `json:"appCode"` + TransactionID string `json:"transactionId"` + CommandID string `json:"commandId"` + RechargeType string `json:"rechargeType"` + Status string `json:"status"` + ExternalRef string `json:"externalRef"` + UserID int64 `json:"userId"` + SellerUserID int64 `json:"sellerUserId"` + SellerRegionID int64 `json:"sellerRegionId"` + TargetRegionID int64 `json:"targetRegionId"` + PolicyID int64 `json:"policyId"` + PolicyVersion string `json:"policyVersion"` + CurrencyCode string `json:"currencyCode"` + CoinAmount int64 `json:"coinAmount"` + USDMinorAmount int64 `json:"usdMinorAmount"` + ExchangeCoinAmount int64 `json:"exchangeCoinAmount"` + ExchangeUSDMinorAmount int64 `json:"exchangeUsdMinorAmount"` + CreatedAtMS int64 `json:"createdAtMs"` + User rechargeBillUserDTO `json:"user"` + Seller rechargeBillUserDTO `json:"seller"` +} + +type rechargeBillUserDTO struct { + UserID string `json:"userId"` + DisplayUserID string `json:"displayUserId"` + Username string `json:"username"` + Avatar string `json:"avatar"` } type rechargeProductDTO struct { @@ -81,6 +90,57 @@ func rechargeBillFromProto(item *walletv1.RechargeBill) rechargeBillDTO { } } +// collectRechargeBillUserIDs 把付款用户和币商用户放进同一个去重列表;后续只查一次 users 表即可覆盖两列展示。 +func collectRechargeBillUserIDs(items []rechargeBillDTO) []int64 { + seen := make(map[int64]struct{}, len(items)*2) + userIDs := make([]int64, 0, len(items)*2) + for _, item := range items { + for _, userID := range []int64{item.UserID, item.SellerUserID} { + if userID <= 0 { + continue + } + if _, ok := seen[userID]; ok { + continue + } + seen[userID] = struct{}{} + userIDs = append(userIDs, userID) + } + } + return userIDs +} + +// rechargeBillUserOrFallback 保证用户资料缺失时仍返回长 ID,列表和导出不会因为历史用户资料缺失而显示空白。 +func rechargeBillUserOrFallback(profile rechargeBillUserDTO, userID int64) rechargeBillUserDTO { + if userID <= 0 { + return rechargeBillUserDTO{} + } + if profile.UserID != "" { + return profile + } + return rechargeBillUserDTO{UserID: strconv.FormatInt(userID, 10)} +} + +// int64Args 将用户 ID 列表转换为 database/sql 可展开的参数切片,避免为 IN 条件拼接原始数值。 +func int64Args(values []int64) []any { + args := make([]any, 0, len(values)) + for _, value := range values { + args = append(args, value) + } + return args +} + +// placeholders 只生成固定数量的问号占位符;实际用户 ID 仍通过参数绑定传入,避免 SQL 注入。 +func placeholders(count int) string { + if count <= 0 { + return "" + } + items := make([]string, count) + for index := range items { + items[index] = "?" + } + return strings.Join(items, ",") +} + func rechargeProductFromProto(item *walletv1.RechargeProduct) rechargeProductDTO { if item == nil { return rechargeProductDTO{} diff --git a/server/admin/internal/modules/payment/handler.go b/server/admin/internal/modules/payment/handler.go index d7ce37e4..f09bbf92 100644 --- a/server/admin/internal/modules/payment/handler.go +++ b/server/admin/internal/modules/payment/handler.go @@ -1,6 +1,8 @@ package payment import ( + "context" + "database/sql" "errors" "math" "strconv" @@ -22,18 +24,21 @@ const usdtMicroUnit int64 = 1_000_000 type Handler struct { wallet walletclient.Client + userDB *sql.DB audit shared.OperationLogger } -func New(wallet walletclient.Client, audit shared.OperationLogger) *Handler { - return &Handler{wallet: wallet, audit: audit} +// New 组装支付后台 handler;wallet 负责账单和商品事实,userDB 只补后台列表需要的用户展示资料。 +func New(wallet walletclient.Client, userDB *sql.DB, audit shared.OperationLogger) *Handler { + return &Handler{wallet: wallet, userDB: userDB, audit: audit} } func (h *Handler) ListRechargeBills(c *gin.Context) { options := shared.ListOptions(c) + appCode := appctx.FromContext(c.Request.Context()) resp, err := h.wallet.ListRechargeBills(c.Request.Context(), &walletv1.ListRechargeBillsRequest{ RequestId: middleware.CurrentRequestID(c), - AppCode: appctx.FromContext(c.Request.Context()), + AppCode: appCode, UserId: queryInt64(c, "user_id", "userId"), SellerUserId: queryInt64(c, "seller_user_id", "sellerUserId"), RegionId: queryInt64(c, "region_id", "regionId"), @@ -54,9 +59,64 @@ func (h *Handler) ListRechargeBills(c *gin.Context) { for _, item := range resp.GetBills() { items = append(items, rechargeBillFromProto(item)) } + // 账单事实仍由 wallet-service 返回;这里只按本页出现的付款用户和币商用户批量补展示资料,避免列表渲染时逐行查用户。 + if err := h.fillRechargeBillUsers(c.Request.Context(), appCode, items); err != nil { + response.ServerError(c, "获取账单用户资料失败") + return + } response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) } +// fillRechargeBillUsers 将用户资料写回当前页账单 DTO;缺失资料会在 DTO 层保留长 ID,避免影响账单事实展示。 +func (h *Handler) fillRechargeBillUsers(ctx context.Context, appCode string, items []rechargeBillDTO) error { + userIDs := collectRechargeBillUserIDs(items) + if len(userIDs) == 0 { + return nil + } + profiles, err := h.loadRechargeBillUsers(ctx, appCode, userIDs) + if err != nil { + return err + } + for index := range items { + items[index].User = rechargeBillUserOrFallback(profiles[items[index].UserID], items[index].UserID) + items[index].Seller = rechargeBillUserOrFallback(profiles[items[index].SellerUserID], items[index].SellerUserID) + } + return nil +} + +// loadRechargeBillUsers 按 app_code 和用户 ID 批量读取展示资料,返回 map 便于用户列和币商列复用同一次查询结果。 +func (h *Handler) loadRechargeBillUsers(ctx context.Context, appCode string, userIDs []int64) (map[int64]rechargeBillUserDTO, error) { + if h == nil || h.userDB == nil { + return nil, errors.New("user mysql is not configured") + } + // 本查询只读取 users 表里的展示字段,按照 app_code 和 user_id 精确命中;区域和账单筛选仍以 wallet-service 返回为准。 + 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(userIDs))+`)`, + append([]any{appCode}, int64Args(userIDs)...)..., + ) + if err != nil { + return nil, err + } + defer rows.Close() + + profiles := make(map[int64]rechargeBillUserDTO, len(userIDs)) + for rows.Next() { + var profile rechargeBillUserDTO + var userID int64 + if err := rows.Scan(&userID, &profile.DisplayUserID, &profile.Username, &profile.Avatar); err != nil { + return nil, err + } + profile.UserID = strconv.FormatInt(userID, 10) + profiles[userID] = profile + } + if err := rows.Err(); err != nil { + return nil, err + } + return profiles, nil +} + func (h *Handler) ListRechargeProducts(c *gin.Context) { options := shared.ListOptions(c) resp, err := h.wallet.ListAdminRechargeProducts(c.Request.Context(), &walletv1.ListAdminRechargeProductsRequest{ 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 defd27fc..8192c27f 100644 --- a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql +++ b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql @@ -50,49 +50,6 @@ CREATE TABLE IF NOT EXISTS activity_outbox ( KEY idx_activity_outbox_retention (app_code, status, updated_at_ms, outbox_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='活动事件 outbox 表'; -CREATE TABLE IF NOT EXISTS lucky_gift_rules ( - app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', - gift_id VARCHAR(96) NOT NULL COMMENT '奖池 ID;当前列名沿用旧内部作用域名', - enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用', - rule_version BIGINT NOT NULL COMMENT '规则版本', - gift_price BIGINT NOT NULL COMMENT '单次抽奖消耗金币', - target_rtp_ppm INT NOT NULL COMMENT '基础 RTP 目标,ppm', - pool_rate_ppm INT NOT NULL COMMENT '基础奖池入池比例,ppm', - global_window_draws BIGINT NOT NULL COMMENT '全站 RTP 窗口抽数', - gift_window_draws BIGINT NOT NULL COMMENT '礼物 RTP 子窗口抽数', - novice_draw_limit BIGINT NOT NULL COMMENT '新手池截止抽数', - intermediate_draw_limit BIGINT NOT NULL COMMENT '中级池截止抽数', - high_multiplier BIGINT NOT NULL COMMENT '高倍判定倍率', - high_water_pool_multiple BIGINT NOT NULL COMMENT '高倍开启所需奖池水位倍数', - platform_pool_weight_ppm INT NOT NULL COMMENT '平台池基础返奖责任权重', - room_pool_weight_ppm INT NOT NULL COMMENT '房间池基础返奖责任权重', - gift_pool_weight_ppm INT NOT NULL COMMENT '礼物池基础返奖责任权重', - initial_platform_pool BIGINT NOT NULL COMMENT '平台池初始水位', - initial_gift_pool BIGINT NOT NULL COMMENT '礼物池初始水位', - initial_room_pool BIGINT NOT NULL COMMENT '房间池初始水位', - platform_reserve BIGINT NOT NULL COMMENT '平台池安全水位', - gift_reserve BIGINT NOT NULL COMMENT '礼物池安全水位', - room_reserve BIGINT NOT NULL COMMENT '房间池安全水位', - max_single_payout BIGINT NOT NULL COMMENT '单次最大奖励', - user_hourly_payout_cap BIGINT NOT NULL COMMENT '用户小时奖励上限', - user_daily_payout_cap BIGINT NOT NULL COMMENT '用户日奖励上限', - device_daily_payout_cap BIGINT NOT NULL COMMENT '设备日奖励上限', - room_hourly_payout_cap BIGINT NOT NULL COMMENT '房间小时奖励上限', - anchor_daily_payout_cap BIGINT NOT NULL COMMENT '主播关联日奖励上限', - room_atmosphere_rate_ppm INT NOT NULL COMMENT '房间气氛池入池比例', - room_atmosphere_initial BIGINT NOT NULL COMMENT '房间气氛池初始预算', - room_atmosphere_reserve BIGINT NOT NULL COMMENT '房间气氛池安全水位', - activity_budget BIGINT NOT NULL COMMENT '活动补贴预算', - activity_daily_limit BIGINT NOT NULL COMMENT '活动补贴日上限', - large_tier_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否开启高倍奖档', - tiers_json JSON NOT NULL COMMENT '倍率生成奖档快照;权重由 RTP 窗口运行时生成', - updated_by_admin_id 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, gift_id), - KEY idx_lucky_gift_rules_enabled (app_code, enabled, updated_at_ms) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物规则表'; - CREATE TABLE IF NOT EXISTS lucky_gift_rule_versions ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', @@ -996,29 +953,43 @@ CREATE TABLE IF NOT EXISTS message_fanout_jobs ( KEY idx_message_fanout_status (app_code, status, next_run_at_ms, updated_at_ms) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='消息分发任务表'; --- 本地开发必须开箱即可验证幸运礼物链路;INSERT IGNORE 只补缺省奖池,不覆盖后台已发布规则。 +-- 本地开发必须开箱即可验证幸运礼物 v2 链路;INSERT IGNORE 只补缺省奖池,不覆盖后台已发布版本。 SET @lucky_seed_now_ms := 1779259000000; -SET @lucky_seed_tiers := JSON_ARRAY( - JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'novice', 'tier_id', 'novice_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'intermediate', 'tier_id', 'intermediate_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_none', 'reward_coins', 0, 'multiplier_ppm', 0, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_1x', 'reward_coins', 100, 'multiplier_ppm', 1000000, 'weight', 0, 'high_water_only', false, 'enabled', true), - JSON_OBJECT('pool', 'advanced', 'tier_id', 'advanced_2x', 'reward_coins', 200, 'multiplier_ppm', 2000000, 'weight', 0, 'high_water_only', false, 'enabled', true) -); -INSERT IGNORE INTO lucky_gift_rules ( - app_code, gift_id, enabled, rule_version, gift_price, target_rtp_ppm, pool_rate_ppm, - global_window_draws, gift_window_draws, novice_draw_limit, intermediate_draw_limit, - high_multiplier, high_water_pool_multiple, platform_pool_weight_ppm, room_pool_weight_ppm, - gift_pool_weight_ppm, initial_platform_pool, initial_gift_pool, initial_room_pool, - platform_reserve, gift_reserve, room_reserve, max_single_payout, user_hourly_payout_cap, - user_daily_payout_cap, device_daily_payout_cap, room_hourly_payout_cap, anchor_daily_payout_cap, - room_atmosphere_rate_ppm, room_atmosphere_initial, room_atmosphere_reserve, - activity_budget, activity_daily_limit, large_tier_enabled, tiers_json, - updated_by_admin_id, created_at_ms, updated_at_ms +INSERT IGNORE INTO lucky_gift_rule_versions ( + app_code, pool_id, rule_version, enabled, target_rtp_ppm, pool_rate_ppm, + settlement_window_wager, control_band_ppm, gift_price_reference, + novice_max_equivalent_draws, normal_max_equivalent_draws, + max_single_payout, user_hourly_payout_cap, user_daily_payout_cap, device_daily_payout_cap, + room_hourly_payout_cap, anchor_daily_payout_cap, effective_from_ms, created_by_admin_id, created_at_ms ) VALUES - ('lalu', 'lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, @lucky_seed_tiers, 0, @lucky_seed_now_ms, @lucky_seed_now_ms), - ('lalu', 'super_lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, @lucky_seed_tiers, 0, @lucky_seed_now_ms, @lucky_seed_now_ms); + ('lalu', 'lucky', 1, true, 950000, 960000, 1000000, 10000, 100, 2000, 20000, 50000, 34200, 615600, 1026000, 684000, 12312000, @lucky_seed_now_ms, 0, @lucky_seed_now_ms), + ('lalu', 'super_lucky', 1, true, 950000, 960000, 1000000, 10000, 100, 2000, 20000, 50000, 34200, 615600, 1026000, 684000, 12312000, @lucky_seed_now_ms, 0, @lucky_seed_now_ms); + +INSERT IGNORE INTO lucky_gift_stage_tiers ( + app_code, pool_id, rule_version, stage, tier_id, multiplier_ppm, base_weight_ppm, + reward_source, high_water_only, broadcast_level, enabled +) VALUES + ('lalu', 'lucky', 1, 'novice', 'novice_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_none', 0, 270000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_1x', 1000000, 600000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_2x', 2000000, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_5x', 5000000, 30000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_none', 0, 270000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_1x', 1000000, 600000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_2x', 2000000, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_5x', 5000000, 30000, 'base_rtp', false, 'none', true); diff --git a/services/activity-service/internal/service/luckygift/config.go b/services/activity-service/internal/service/luckygift/config.go index e321c5ed..0955616a 100644 --- a/services/activity-service/internal/service/luckygift/config.go +++ b/services/activity-service/internal/service/luckygift/config.go @@ -2,7 +2,6 @@ package luckygift import ( "fmt" - "sort" "strings" "hyapp/pkg/xerr" @@ -14,51 +13,6 @@ const ( highTierMultiplierPPM int64 = 10_000_000 ) -// DefaultConfig 给后台指定奖池提供规则草稿;真正生效必须由后台显式 enabled。 -func DefaultConfig(appCode, poolID string) domain.Config { - const giftPrice int64 = 10_000 - poolID = normalizePoolID(poolID) - return domain.Config{ - AppCode: appCode, - GiftID: poolID, - PoolID: poolID, - Enabled: false, - GiftPrice: giftPrice, - TargetRTPPPM: 950_000, - PoolRatePPM: 950_000, - ControlBandPPM: 10_000, - GlobalWindowDraws: 100_000, - GiftWindowDraws: 100_000, - NoviceMaxEquivalentDraws: 2_000, - NormalMaxEquivalentDraws: 20_000, - HighMultiplier: 100, - HighWaterPoolMultiple: 2, - PlatformPoolWeightPPM: 200_000, - RoomPoolWeightPPM: 300_000, - GiftPoolWeightPPM: 500_000, - InitialPlatformPool: 9_500_000, - InitialGiftPool: 23_750_000, - InitialRoomPool: 5_000_000, - PlatformReserve: 1_000_000, - GiftReserve: 1_000_000, - RoomReserve: 100_000, - MaxSinglePayout: giftPrice * 500, - UserHourlyPayoutCap: 3_420_000, - UserDailyPayoutCap: 61_560_000, - DeviceDailyPayoutCap: 102_600_000, - RoomHourlyPayoutCap: 68_400_000, - AnchorDailyPayoutCap: 1_231_200_000, - RoomAtmosphereRatePPM: 10_000, - RoomAtmosphereInitial: 100_000, - RoomAtmosphereReserve: 10_000, - ActivityBudget: 0, - ActivityDailyLimit: 0, - LargeTierEnabled: true, - MultiplierPPMs: defaultMultiplierPPMs(), - Tiers: defaultTiers(giftPrice), - } -} - // DefaultRuleConfig 返回 v2 配置草稿。草稿默认 disabled,只有后台发布后才写入不可变版本表。 func DefaultRuleConfig(appCode, poolID string) domain.RuleConfig { poolID = normalizePoolID(poolID) @@ -286,152 +240,6 @@ func validBroadcastLevel(level string) bool { level == domain.BroadcastGlobal } -// validateConfig 只校验会破坏线上抽奖不变量的字段;展示类默认值留给后台表单处理。 -func validateConfig(config domain.Config) error { - if normalizePoolID(config.PoolID) == "" { - return xerr.New(xerr.InvalidArgument, "lucky gift pool id is required") - } - // 当前 DB 历史列名仍叫 gift_id,但业务语义已经是 pool_id;这里强制二者一致,避免后台提交真实礼物 ID 后把窗口和奖池切散。 - config.GiftID = normalizePoolID(config.PoolID) - if config.GiftPrice <= 0 || config.TargetRTPPPM <= 0 || config.TargetRTPPPM > ppmScale { - return xerr.New(xerr.InvalidArgument, "gift price or target RTP is invalid") - } - // 入池比例低于目标 RTP 时,即使长期抽数足够也无法靠奖池支付基础返奖,必须在发布前拒绝。 - if config.PoolRatePPM < config.TargetRTPPPM || config.PoolRatePPM > ppmScale { - return xerr.New(xerr.InvalidArgument, "pool rate must be between target RTP and 100%") - } - if config.GlobalWindowDraws <= 0 || config.GiftWindowDraws <= 0 { - return xerr.New(xerr.InvalidArgument, "RTP window draws must be positive") - } - if config.NoviceMaxEquivalentDraws < 0 || config.NormalMaxEquivalentDraws < config.NoviceMaxEquivalentDraws { - return xerr.New(xerr.InvalidArgument, "experience pool equivalent draw limits are invalid") - } - if config.HighMultiplier <= 0 || config.HighWaterPoolMultiple <= 0 { - return xerr.New(xerr.InvalidArgument, "high multiplier config is invalid") - } - if config.PlatformPoolWeightPPM < 0 || config.RoomPoolWeightPPM < 0 || config.GiftPoolWeightPPM < 0 || - config.PlatformPoolWeightPPM+config.RoomPoolWeightPPM+config.GiftPoolWeightPPM != ppmScale { - return xerr.New(xerr.InvalidArgument, "pool weights must sum to 1000000") - } - if config.MaxSinglePayout <= 0 || config.UserHourlyPayoutCap <= 0 || config.UserDailyPayoutCap <= 0 || - config.DeviceDailyPayoutCap <= 0 || config.RoomHourlyPayoutCap <= 0 || config.AnchorDailyPayoutCap <= 0 { - return xerr.New(xerr.InvalidArgument, "risk payout caps must be positive") - } - // tiers 是倍率列表归一化后的运行时候选集合;即使后台只提交 multiplier_ppms,发布前也必须先生成 tiers。 - if len(config.Tiers) == 0 { - return xerr.New(xerr.InvalidArgument, "reward tiers are required") - } - maxMultiplierPPM := int64(0) - for _, tier := range config.Tiers { - if tier.Pool == "" || tier.TierID == "" || tier.Weight < 0 || tier.RewardCoins < 0 || tier.MultiplierPPM < 0 { - return xerr.New(xerr.InvalidArgument, fmt.Sprintf("invalid reward tier: %s", tier.TierID)) - } - if tier.Enabled && tier.MultiplierPPM > maxMultiplierPPM { - maxMultiplierPPM = tier.MultiplierPPM - } - } - // 最大倍率低于目标 RTP 时,窗口最后几抽可能没有足够高的基础候选追平目标,只能提前拒绝这类配置。 - if maxMultiplierPPM < config.TargetRTPPPM { - return xerr.New(xerr.InvalidArgument, "max lucky gift multiplier must not be lower than target RTP") - } - return nil -} - -// normalizeTiers 把后台“可中倍率”转换成三档体验池候选;后台传入的权重不会成为线上概率。 -func normalizeTiers(tiers []domain.Tier, multipliers []int64, giftPrice, highMultiplier int64) ([]domain.Tier, []int64) { - multiplierPPMs := normalizeMultiplierPPMs(multipliers, tiers, giftPrice) - return buildMultiplierTiers(giftPrice, highMultiplier, multiplierPPMs), multiplierPPMs -} - -func normalizeMultiplierPPMs(input []int64, tiers []domain.Tier, giftPrice int64) []int64 { - // 新后台直接提交 multiplier_ppms;旧调用方如果仍提交 tiers,则从 reward_coins 反推倍率以减少迁移断点。 - values := append([]int64(nil), input...) - if len(values) == 0 { - for _, tier := range tiers { - if tier.MultiplierPPM > 0 || tier.RewardCoins == 0 { - values = append(values, tier.MultiplierPPM) - continue - } - if giftPrice > 0 && tier.RewardCoins > 0 { - values = append(values, tier.RewardCoins*ppmScale/giftPrice) - } - } - } - // 没有任何输入时使用保守默认倍率,保证默认草稿可被后台查看和复制,但仍默认 disabled。 - if len(values) == 0 { - values = defaultMultiplierPPMs() - } - seen := map[int64]bool{} - out := make([]int64, 0, len(values)) - for _, value := range values { - // 负倍率没有业务含义;重复倍率会造成同一返奖点被重复计权,因此在入口处去重。 - if value < 0 || seen[value] { - continue - } - seen[value] = true - out = append(out, value) - } - // 全部被过滤时回退默认列表,避免构造出空 tiers 后在更深层事务里失败。 - if len(out) == 0 { - out = defaultMultiplierPPMs() - } - sort.Slice(out, func(i, j int) bool { return out[i] < out[j] }) - return out -} - -func buildMultiplierTiers(cost, highMultiplier int64, multipliers []int64) []domain.Tier { - out := make([]domain.Tier, 0, len(multipliers)*3) - for _, pool := range []string{domain.PoolNovice, domain.PoolIntermediate, domain.PoolAdvanced} { - for _, multiplierPPM := range multipliers { - out = append(out, domain.Tier{ - Pool: pool, - TierID: pool + "_" + multiplierTierID(multiplierPPM), - RewardCoins: cost * multiplierPPM / ppmScale, - MultiplierPPM: multiplierPPM, - // 旧 multiplier_ppms 入口没有显式概率;运行侧会退化为等权随机,正式 v2 发布应使用阶段奖档概率。 - Weight: 0, - HighWaterOnly: highMultiplier > 0 && multiplierPPM >= highMultiplier*ppmScale, - Enabled: true, - }) - } - } - return out -} - -func defaultMultiplierPPMs() []int64 { - return []int64{ - 0, - 200_000, - 500_000, - 1_000_000, - 2_000_000, - 5_000_000, - 10_000_000, - 20_000_000, - 50_000_000, - 100_000_000, - 500_000_000, - } -} - -func defaultTiers(cost int64) []domain.Tier { - return buildMultiplierTiers(cost, 100, defaultMultiplierPPMs()) -} - -func multiplierTierID(multiplierPPM int64) string { - if multiplierPPM == 0 { - return "none" - } - whole := multiplierPPM / ppmScale - fraction := multiplierPPM % ppmScale - if fraction == 0 { - return fmt.Sprintf("%dx", whole) - } - // 小数倍率用下划线表达,避免 tier_id 出现点号后和后台路径/筛选语法冲突。 - text := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%d_%06dx", whole, fraction), "0"), "_") - return text -} - func normalizePoolID(poolID string) string { poolID = strings.TrimSpace(poolID) if poolID == "" { diff --git a/services/activity-service/internal/service/luckygift/config_test.go b/services/activity-service/internal/service/luckygift/config_test.go index e5397065..5328d272 100644 --- a/services/activity-service/internal/service/luckygift/config_test.go +++ b/services/activity-service/internal/service/luckygift/config_test.go @@ -4,66 +4,6 @@ import ( "testing" ) -func TestDefaultConfigPassesValidation(t *testing.T) { - config := DefaultConfig("hyapp", "pool_95") - config.Enabled = true - - if err := validateConfig(config); err != nil { - t.Fatalf("default lucky gift config should be publishable: %v", err) - } -} - -func TestValidateConfigAcceptsIndependentPoolScope(t *testing.T) { - config := DefaultConfig("hyapp", "pool_98") - config.Enabled = true - - if err := validateConfig(config); err != nil { - t.Fatalf("expected pool scoped lucky gift config to pass: %v", err) - } -} - -func TestNormalizeTiersBuildsMultiplierDrivenTiers(t *testing.T) { - tiers, multipliers := normalizeTiers(nil, []int64{0, 500_000, 2_000_000}, 500, 100) - - if len(multipliers) != 3 || multipliers[1] != 500_000 || multipliers[2] != 2_000_000 { - t.Fatalf("expected normalized multiplier list, got %#v", multipliers) - } - if len(tiers) != 9 { - t.Fatalf("expected three pools times three multipliers, got %d", len(tiers)) - } - for _, tier := range tiers { - if !tier.Enabled || tier.Weight != 0 { - t.Fatalf("tier should be enabled with runtime-generated weight: %#v", tier) - } - if tier.MultiplierPPM == 500_000 && tier.RewardCoins != 250 { - t.Fatalf("expected 0.5x reward to follow reference cost, got %#v", tier) - } - } -} - -func TestNormalizeTiersDoesNotForceZeroMultiplier(t *testing.T) { - tiers, multipliers := normalizeTiers(nil, []int64{1_000_000, 2_000_000}, 500, 100) - - if len(multipliers) != 2 || multipliers[0] != 1_000_000 || multipliers[1] != 2_000_000 { - t.Fatalf("expected positive-only multiplier list to stay positive-only, got %#v", multipliers) - } - for _, tier := range tiers { - if tier.MultiplierPPM == 0 || tier.RewardCoins == 0 { - t.Fatalf("positive-only test config must not generate none tier: %#v", tier) - } - } -} - -func TestValidateConfigRejectsMultiplierListBelowTargetRTP(t *testing.T) { - config := DefaultConfig("hyapp", "pool_low") - config.MultiplierPPMs = []int64{0, 500_000} - config.Tiers, config.MultiplierPPMs = normalizeTiers(nil, config.MultiplierPPMs, config.GiftPrice, config.HighMultiplier) - - if err := validateConfig(config); err == nil { - t.Fatalf("expected max multiplier below RTP to be rejected") - } -} - func TestDefaultRuleConfigPassesValidation(t *testing.T) { config := DefaultRuleConfig("hyapp", "pool_v2") config.Enabled = true diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go index 12962498..fc10e550 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go @@ -1956,72 +1956,10 @@ func luckyDrawWhereClause(appCode string, query domain.DrawQuery) (string, []any return strings.Join(where, " AND "), args } -type luckyQueryer interface { - QueryRowContext(context.Context, string, ...any) *sql.Row -} - type luckyScanner interface { Scan(...any) error } -func (r *Repository) getLuckyGiftConfig(ctx context.Context, q luckyQueryer, appCode string, giftID string, forUpdate bool) (domain.Config, bool, error) { - if giftID == "" { - return domain.Config{}, false, nil - } - lockSQL := "" - if forUpdate { - lockSQL = " FOR UPDATE" - } - row := q.QueryRowContext(ctx, ` - SELECT app_code, gift_id, enabled, rule_version, gift_price, target_rtp_ppm, pool_rate_ppm, - global_window_draws, gift_window_draws, novice_draw_limit, intermediate_draw_limit, - high_multiplier, high_water_pool_multiple, platform_pool_weight_ppm, room_pool_weight_ppm, - gift_pool_weight_ppm, initial_platform_pool, initial_gift_pool, initial_room_pool, - platform_reserve, gift_reserve, room_reserve, max_single_payout, user_hourly_payout_cap, - user_daily_payout_cap, device_daily_payout_cap, room_hourly_payout_cap, anchor_daily_payout_cap, - room_atmosphere_rate_ppm, room_atmosphere_initial, room_atmosphere_reserve, - activity_budget, activity_daily_limit, large_tier_enabled, - COALESCE(CAST(tiers_json AS CHAR), '[]'), updated_by_admin_id, created_at_ms, updated_at_ms - FROM lucky_gift_rules - WHERE app_code = ? AND gift_id = ?`+lockSQL, - appCode, giftID, - ) - config, err := scanLuckyConfig(row) - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return domain.Config{}, false, nil - } - return domain.Config{}, false, err - } - return config, true, nil -} - -func scanLuckyConfig(scanner luckyScanner) (domain.Config, error) { - var config domain.Config - var tiersJSON string - var noviceDrawLimit int64 - var intermediateDrawLimit int64 - if err := scanner.Scan(&config.AppCode, &config.GiftID, &config.Enabled, &config.RuleVersion, &config.GiftPrice, &config.TargetRTPPPM, &config.PoolRatePPM, - &config.GlobalWindowDraws, &config.GiftWindowDraws, &noviceDrawLimit, &intermediateDrawLimit, - &config.HighMultiplier, &config.HighWaterPoolMultiple, &config.PlatformPoolWeightPPM, &config.RoomPoolWeightPPM, - &config.GiftPoolWeightPPM, &config.InitialPlatformPool, &config.InitialGiftPool, &config.InitialRoomPool, - &config.PlatformReserve, &config.GiftReserve, &config.RoomReserve, &config.MaxSinglePayout, &config.UserHourlyPayoutCap, - &config.UserDailyPayoutCap, &config.DeviceDailyPayoutCap, &config.RoomHourlyPayoutCap, &config.AnchorDailyPayoutCap, - &config.RoomAtmosphereRatePPM, &config.RoomAtmosphereInitial, &config.RoomAtmosphereReserve, - &config.ActivityBudget, &config.ActivityDailyLimit, &config.LargeTierEnabled, - &tiersJSON, &config.UpdatedByAdminID, &config.CreatedAtMS, &config.UpdatedAtMS); err != nil { - return domain.Config{}, err - } - if err := json.Unmarshal([]byte(tiersJSON), &config.Tiers); err != nil { - return domain.Config{}, err - } - config.PoolID = config.GiftID - config.NoviceMaxEquivalentDraws = noviceDrawLimit - config.NormalMaxEquivalentDraws = intermediateDrawLimit - config.MultiplierPPMs = luckyMultiplierPPMsFromTiers(config.Tiers, config.GiftPrice) - return config, nil -} - func luckyRuntimeConfigFromRuleConfig(ruleConfig domain.RuleConfig) (domain.Config, error) { poolID := luckyPoolID(ruleConfig.PoolID) referencePrice := ruleConfig.GiftPriceReference diff --git a/services/activity-service/internal/storage/mysql/repository.go b/services/activity-service/internal/storage/mysql/repository.go index 2d9c43a2..2bebaebc 100644 --- a/services/activity-service/internal/storage/mysql/repository.go +++ b/services/activity-service/internal/storage/mysql/repository.go @@ -414,35 +414,51 @@ func (r *Repository) ensureLuckyGiftRuleVersionRiskCapColumns(ctx context.Contex } func (r *Repository) ensureDefaultLuckyGiftRules(ctx context.Context) error { - // 本地和 Docker 开发库通常保留 MySQL volume;这里补齐缺省 lucky/super_lucky 契约,但不覆盖后台已发布规则。 + // 本地和 Docker 开发库通常保留 MySQL volume;这里补齐 v2 lucky/super_lucky 契约,但不覆盖后台已发布版本。 const seedNowMS int64 = 1779259000000 - const seedTiersJSON = `[ - {"pool":"novice","tier_id":"novice_none","reward_coins":0,"multiplier_ppm":0,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"novice","tier_id":"novice_1x","reward_coins":100,"multiplier_ppm":1000000,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"novice","tier_id":"novice_2x","reward_coins":200,"multiplier_ppm":2000000,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"intermediate","tier_id":"intermediate_none","reward_coins":0,"multiplier_ppm":0,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"intermediate","tier_id":"intermediate_1x","reward_coins":100,"multiplier_ppm":1000000,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"intermediate","tier_id":"intermediate_2x","reward_coins":200,"multiplier_ppm":2000000,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"advanced","tier_id":"advanced_none","reward_coins":0,"multiplier_ppm":0,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"advanced","tier_id":"advanced_1x","reward_coins":100,"multiplier_ppm":1000000,"weight":0,"high_water_only":false,"enabled":true}, - {"pool":"advanced","tier_id":"advanced_2x","reward_coins":200,"multiplier_ppm":2000000,"weight":0,"high_water_only":false,"enabled":true} - ]` - _, err := r.db.ExecContext(ctx, ` - INSERT IGNORE INTO lucky_gift_rules ( - app_code, gift_id, enabled, rule_version, gift_price, target_rtp_ppm, pool_rate_ppm, - global_window_draws, gift_window_draws, novice_draw_limit, intermediate_draw_limit, - high_multiplier, high_water_pool_multiple, platform_pool_weight_ppm, room_pool_weight_ppm, - gift_pool_weight_ppm, initial_platform_pool, initial_gift_pool, initial_room_pool, - platform_reserve, gift_reserve, room_reserve, max_single_payout, user_hourly_payout_cap, - user_daily_payout_cap, device_daily_payout_cap, room_hourly_payout_cap, anchor_daily_payout_cap, - room_atmosphere_rate_ppm, room_atmosphere_initial, room_atmosphere_reserve, - activity_budget, activity_daily_limit, large_tier_enabled, tiers_json, - updated_by_admin_id, created_at_ms, updated_at_ms + if _, err := r.db.ExecContext(ctx, ` + INSERT IGNORE INTO lucky_gift_rule_versions ( + app_code, pool_id, rule_version, enabled, target_rtp_ppm, pool_rate_ppm, + settlement_window_wager, control_band_ppm, gift_price_reference, + novice_max_equivalent_draws, normal_max_equivalent_draws, + max_single_payout, user_hourly_payout_cap, user_daily_payout_cap, device_daily_payout_cap, + room_hourly_payout_cap, anchor_daily_payout_cap, effective_from_ms, created_by_admin_id, created_at_ms ) VALUES - ('lalu', 'lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, ?, 0, ?, ?), - ('lalu', 'super_lucky', true, 1, 100, 950000, 950000, 100000, 100000, 2000, 20000, 100, 2, 200000, 300000, 500000, 9500000, 23750000, 5000000, 1000000, 1000000, 100000, 50000, 3420000, 61560000, 102600000, 68400000, 1231200000, 10000, 100000, 10000, 0, 0, true, ?, 0, ?, ?)`, - seedTiersJSON, seedNowMS, seedNowMS, seedTiersJSON, seedNowMS, seedNowMS, - ) + ('lalu', 'lucky', 1, true, 950000, 960000, 1000000, 10000, 100, 2000, 20000, 50000, 34200, 615600, 1026000, 684000, 12312000, ?, 0, ?), + ('lalu', 'super_lucky', 1, true, 950000, 960000, 1000000, 10000, 100, 2000, 20000, 50000, 34200, 615600, 1026000, 684000, 12312000, ?, 0, ?)`, + seedNowMS, seedNowMS, seedNowMS, seedNowMS, + ); err != nil { + return err + } + _, err := r.db.ExecContext(ctx, ` + INSERT IGNORE INTO lucky_gift_stage_tiers ( + app_code, pool_id, rule_version, stage, tier_id, multiplier_ppm, base_weight_ppm, + reward_source, high_water_only, broadcast_level, enabled + ) VALUES + ('lalu', 'lucky', 1, 'novice', 'novice_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'novice', 'novice_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'normal', 'normal_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_none', 0, 270000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_1x', 1000000, 600000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_2x', 2000000, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'lucky', 1, 'advanced', 'advanced_5x', 5000000, 30000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'novice', 'novice_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_none', 0, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_0_5x', 500000, 200000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_1x', 1000000, 550000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'normal', 'normal_2x', 2000000, 150000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_none', 0, 270000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_1x', 1000000, 600000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_2x', 2000000, 100000, 'base_rtp', false, 'none', true), + ('lalu', 'super_lucky', 1, 'advanced', 'advanced_5x', 5000000, 30000, 'base_rtp', false, 'none', true)`) return err } diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index 8530a439..51551591 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -231,7 +231,7 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r roomGiftLeaderboard: &RoomGiftLeaderboardIncrement{ AppCode: appcode.FromContext(ctx), RoomID: current.RoomID, - CoinSpent: roomGiftLeaderboardCoinSpent(billing), + CoinSpent: roomGiftLeaderboardValue(billing), OccurredAtMS: now.UnixMilli(), }, roomUserGiftStats: []RoomUserGiftStatIncrement{ @@ -387,14 +387,15 @@ func (s *Service) executeLuckyGiftDraws(ctx context.Context, meta *roomv1.Reques return results, nil } -func roomGiftLeaderboardCoinSpent(billing *walletv1.DebitGiftResponse) int64 { +func roomGiftLeaderboardValue(billing *walletv1.DebitGiftResponse) int64 { if billing == nil { return 0 } - if billing.GetCoinSpent() > 0 { - return billing.GetCoinSpent() + // 房间贡献榜跟房间热度、房间内贡献人保持同一口径,使用 wallet 已按全局默认比例折算后的 heat_value。 + if billing.GetHeatValue() > 0 { + return billing.GetHeatValue() } - return billing.GetChargeAmount() + return 0 } func (s *Service) shouldDrawLuckyGift(poolID string, giftTypeCode string) bool { diff --git a/services/room-service/internal/room/service/gift_leaderboard_test.go b/services/room-service/internal/room/service/gift_leaderboard_test.go new file mode 100644 index 00000000..c038b67a --- /dev/null +++ b/services/room-service/internal/room/service/gift_leaderboard_test.go @@ -0,0 +1,81 @@ +package service_test + +import ( + "context" + "testing" + "time" + + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/services/room-service/internal/integration" + roomservice "hyapp/services/room-service/internal/room/service" + "hyapp/services/room-service/internal/router" + "hyapp/services/room-service/internal/testutil/mysqltest" +) + +type recordingRoomGiftLeaderboard struct { + increments []roomservice.RoomGiftLeaderboardIncrement +} + +func (s *recordingRoomGiftLeaderboard) IncrementRoomGift(_ context.Context, input roomservice.RoomGiftLeaderboardIncrement) error { + s.increments = append(s.increments, input) + return nil +} + +func (s *recordingRoomGiftLeaderboard) ListRoomGiftLeaderboard(context.Context, roomservice.RoomGiftLeaderboardQuery) (roomservice.RoomGiftLeaderboardPage, error) { + return roomservice.RoomGiftLeaderboardPage{}, nil +} + +func TestSendGiftWritesRoomGiftLeaderboardWithHeatValue(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ + BillingReceiptId: "receipt-gift-leaderboard", + CoinSpent: 100, + ChargeAmount: 100, + GiftPointAdded: 100, + HeatValue: 10, + GiftTypeCode: "lucky", + }}} + leaderboard := &recordingRoomGiftLeaderboard{} + now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 5, 12, 0, 0, 0, time.UTC)} + svc := roomservice.New(roomservice.Config{ + NodeID: "node-gift-leaderboard-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + Clock: now, + RoomGiftLeaderboard: leaderboard, + }, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + roomID := "room-gift-leaderboard" + senderID := int64(18001) + targetID := int64(18002) + createTreasureRoom(t, ctx, svc, roomID, senderID, 9001) + joinTreasureRoom(t, ctx, svc, roomID, targetID) + + if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ + Meta: &roomv1.RequestMeta{ + RequestId: "req-gift-leaderboard", + CommandId: "cmd-gift-leaderboard", + ActorUserId: senderID, + RoomId: roomID, + AppCode: appcode.Default, + SentAtMs: now.Now().UnixMilli(), + }, + TargetType: "user", + TargetUserId: targetID, + GiftId: "gift-leaderboard", + GiftCount: 1, + }); err != nil { + t.Fatalf("send gift failed: %v", err) + } + + if len(leaderboard.increments) != 1 { + t.Fatalf("expected one leaderboard increment, got %+v", leaderboard.increments) + } + if leaderboard.increments[0].CoinSpent != 10 { + t.Fatalf("leaderboard must use heat value after global ratio, got %+v", leaderboard.increments[0]) + } +} diff --git a/services/room-service/internal/room/service/pipeline.go b/services/room-service/internal/room/service/pipeline.go index 1ddf6b45..f2b882bc 100644 --- a/services/room-service/internal/room/service/pipeline.go +++ b/services/room-service/internal/room/service/pipeline.go @@ -159,7 +159,7 @@ func (s *Service) mutateRoom(ctx context.Context, cmd command.Command, replayabl s.projectRoomListBestEffort(ctx, result.snapshot) // 当前房间恢复读模型同样最终一致;权威校验仍以 Room Cell 快照为准。 s.projectRoomPresenceBestEffort(ctx, result.snapshot) - // 跨房间金币榜是 Redis 轻量读模型,不能影响已提交的房间状态和账务事实。 + // 跨房间贡献榜是 Redis 轻量读模型,不能影响已提交的房间状态和账务事实。 s.recordRoomGiftLeaderboardBestEffort(ctx, result.roomGiftLeaderboard) projectionMS = elapsedMS(projectionStartedAt) } diff --git a/services/room-service/internal/room/service/room_gift_leaderboard.go b/services/room-service/internal/room/service/room_gift_leaderboard.go index cb638f42..81de3d84 100644 --- a/services/room-service/internal/room/service/room_gift_leaderboard.go +++ b/services/room-service/internal/room/service/room_gift_leaderboard.go @@ -24,15 +24,16 @@ const ( maxRoomGiftLeaderboardPageSize = 100 ) -// RoomGiftLeaderboardStore 是房间金币榜的轻量读模型边界;生产实现使用 Redis zset。 +// RoomGiftLeaderboardStore 是跨房间贡献榜的轻量读模型边界;生产实现使用 Redis zset。 type RoomGiftLeaderboardStore interface { IncrementRoomGift(ctx context.Context, input RoomGiftLeaderboardIncrement) error ListRoomGiftLeaderboard(ctx context.Context, query RoomGiftLeaderboardQuery) (RoomGiftLeaderboardPage, error) } type RoomGiftLeaderboardIncrement struct { - AppCode string - RoomID string + AppCode string + RoomID string + // CoinSpent 沿用 proto 字段名,运行值实际是 wallet 折算后的房间贡献值。 CoinSpent int64 OccurredAtMS int64 } @@ -60,7 +61,7 @@ type RoomGiftLeaderboardEntry struct { CoinSpent int64 } -// RedisRoomGiftLeaderboardStore 只在 zset 中保存 room_id -> 周期金币消耗分。 +// RedisRoomGiftLeaderboardStore 只在 zset 中保存 room_id -> 周期房间贡献分。 type RedisRoomGiftLeaderboardStore struct { client *redis.Client } diff --git a/services/room-service/internal/room/service/service.go b/services/room-service/internal/room/service/service.go index 30ddab97..19436743 100644 --- a/services/room-service/internal/room/service/service.go +++ b/services/room-service/internal/room/service/service.go @@ -34,7 +34,7 @@ type Config struct { RTCUserRemover integration.RTCUserRemover // RoomTreasureOpenScheduler 把倒计时开箱唤醒交给外部延迟消息,避免只靠已加载 Cell 扫描。 RoomTreasureOpenScheduler integration.RoomTreasureOpenScheduler - // RoomGiftLeaderboard 是跨房间金币榜读模型,SendGift 提交后 best-effort 写入。 + // RoomGiftLeaderboard 是跨房间贡献榜读模型,SendGift 提交后 best-effort 写入。 RoomGiftLeaderboard RoomGiftLeaderboardStore // LuckyGiftSendLocker 串行化同一用户的幸运礼物扣费、抽奖和同步返奖链路。 LuckyGiftSendLocker LuckyGiftSendLocker @@ -74,7 +74,7 @@ type Service struct { outboxPublisher integration.OutboxPublisher // roomTreasureOpenScheduler 在 countdown outbox 投递成功后安排 open_at_ms 唤醒。 roomTreasureOpenScheduler integration.RoomTreasureOpenScheduler - // roomGiftLeaderboard 只保存房间维度金币消耗 zset,不承载 Room Cell 核心状态。 + // roomGiftLeaderboard 只保存房间维度贡献值 zset,不承载 Room Cell 核心状态。 roomGiftLeaderboard RoomGiftLeaderboardStore // luckyGiftSendLocker 只保护同一用户幸运礼物扣费到同步返奖的小事务链路。 luckyGiftSendLocker LuckyGiftSendLocker @@ -134,7 +134,7 @@ type mutationResult struct { closeInfo *RoomCloseInfo // walletDebitMS 记录 SendGift 同步扣费耗时;非钱包命令保持 0。 walletDebitMS int64 - // roomGiftLeaderboard 是 SendGift 成功后写入跨房间金币榜的轻量增量。 + // roomGiftLeaderboard 是 SendGift 成功后写入跨房间贡献榜的轻量增量。 roomGiftLeaderboard *RoomGiftLeaderboardIncrement // roomUserGiftStats 是当前房间用户送礼价值统计,和命令日志同事务提交。 roomUserGiftStats []RoomUserGiftStatIncrement diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 8c6f5f21..1e907d9e 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -227,7 +227,8 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { return mysqlstorage.RechargeEvent{}, false, nil } payload := mysqlstorage.DecodeJSON(message.PayloadJSON) - usdMinor := firstNonZeroInt64(mysqlstorage.Int64(payload, "recharge_usd_minor"), mysqlstorage.Int64(payload, "amount_micro")) + rechargeType := firstNonEmpty(mysqlstorage.String(payload, "recharge_type"), mysqlstorage.String(payload, "channel"), mysqlstorage.String(payload, "provider"), "coin_seller_transfer") + usdMinor := rechargeUSDMinorFromPayload(payload, rechargeType) regionID := firstNonZeroInt64(mysqlstorage.Int64(payload, "target_region_id"), mysqlstorage.Int64(payload, "region_id")) return mysqlstorage.RechargeEvent{ AppCode: message.AppCode, @@ -237,11 +238,38 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { USDMinor: usdMinor, RechargeSequence: mysqlstorage.Int64(payload, "recharge_sequence"), TargetRegionID: regionID, - RechargeType: firstNonEmpty(mysqlstorage.String(payload, "recharge_type"), mysqlstorage.String(payload, "channel"), mysqlstorage.String(payload, "provider"), "coin_seller_transfer"), + RechargeType: rechargeType, OccurredAtMS: message.OccurredAtMS, }, true, nil } +func rechargeUSDMinorFromPayload(payload map[string]any, rechargeType string) int64 { + if value := mysqlstorage.Int64(payload, "recharge_usd_minor"); value > 0 { + return value + } + // 旧 Google outbox 只有 amount_micro;这里按微单位折算成美分,避免 0.99 被统计成 9900。 + if isGoogleRechargeType(rechargeType) { + return amountMicroToUSDMinor(mysqlstorage.Int64(payload, "amount_micro")) + } + return 0 +} + +func isGoogleRechargeType(value string) bool { + switch strings.ToLower(strings.TrimSpace(value)) { + case "google", "google_play": + return true + default: + return false + } +} + +func amountMicroToUSDMinor(amountMicro int64) int64 { + if amountMicro <= 0 { + return 0 + } + return amountMicro / 10_000 +} + func luckyGiftRewardEvent(body []byte) (mysqlstorage.LuckyGiftRewardEvent, bool, error) { message, err := walletmq.DecodeWalletOutboxMessage(body) if err != nil { diff --git a/services/statistics-service/internal/app/local_flow_test.go b/services/statistics-service/internal/app/local_flow_test.go index b0d61c42..20d9d05d 100644 --- a/services/statistics-service/internal/app/local_flow_test.go +++ b/services/statistics-service/internal/app/local_flow_test.go @@ -129,7 +129,7 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { if err != nil { t.Fatalf("query overview failed: %v", err) } - if overview.GoogleRechargeUSDMinor != 1_500_000 || overview.RechargeUSDMinor != 1_500_000 || overview.NewUserRechargeUSDMinor != 1_500_000 { + if overview.GoogleRechargeUSDMinor != 150 || overview.RechargeUSDMinor != 150 || overview.NewUserRechargeUSDMinor != 150 { t.Fatalf("google recharge metrics mismatch: %+v", overview) } if overview.LuckyGiftTurnover != 1_000 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 700 || overview.LuckyGiftPayers != 1 { diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index 29488d2a..376077f7 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -167,7 +167,7 @@ type CreateBDLeaderCommand struct { NowMs int64 } -// CreateBDInput 是后台创建普通 BD 的外部输入。 +// CreateBDInput 是后台创建普通 BD 的外部输入;ParentLeaderUserID 为 0 时表示独立 BD。 type CreateBDInput struct { CommandID string AdminUserID int64 @@ -177,7 +177,7 @@ type CreateBDInput struct { RequestID string } -// CreateBDCommand 是后台创建普通 BD 事务需要的完整命令。 +// CreateBDCommand 是后台创建普通 BD 事务需要的完整命令;ParentLeaderUserID 为 0 时不校验父级 Leader。 type CreateBDCommand struct { CommandID string AdminUserID int64 @@ -253,7 +253,7 @@ type SetCoinSellerStatusCommand struct { NowMs int64 } -// CreateAgencyInput 是后台直接创建 Agency 的外部输入。 +// CreateAgencyInput 是后台直接创建 Agency 的外部输入;ParentBDUserID 为 0 时表示独立 Agency。 type CreateAgencyInput struct { CommandID string AdminUserID int64 @@ -266,7 +266,7 @@ type CreateAgencyInput struct { RequestID string } -// CreateAgencyCommand 是后台直接创建 Agency 事务需要的完整命令。 +// CreateAgencyCommand 是后台直接创建 Agency 事务需要的完整命令;ParentBDUserID 为 0 时不校验父级 BD。 type CreateAgencyCommand struct { CommandID string AdminUserID int64 diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index db7cccb7..25419e16 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -343,13 +343,16 @@ func (s *Service) CreateBDLeader(ctx context.Context, command CreateBDLeaderInpu }) } -// CreateBD 由后台创建普通 BD,并绑定一个有效 BD Leader。 +// CreateBD 由后台创建普通 BD;传入父级 Leader 时绑定到该 Leader,未传时创建独立 BD。 func (s *Service) CreateBD(ctx context.Context, command CreateBDInput) (hostdomain.BDProfile, error) { if err := s.requireWriteDependencies(); err != nil { return hostdomain.BDProfile{}, err } - if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.TargetUserID <= 0 || command.ParentLeaderUserID <= 0 { - return hostdomain.BDProfile{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id, target_user_id and parent_leader_user_id are required") + if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.TargetUserID <= 0 { + return hostdomain.BDProfile{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id and target_user_id are required") + } + if command.ParentLeaderUserID < 0 { + return hostdomain.BDProfile{}, xerr.New(xerr.InvalidArgument, "parent_leader_user_id must not be negative") } nowMs := s.now().UnixMilli() @@ -438,14 +441,17 @@ func (s *Service) SetCoinSellerStatus(ctx context.Context, command SetCoinSeller }) } -// CreateAgency 由后台直接创建 Agency,并原子创建 owner 的 host_profile 和 owner membership。 +// CreateAgency 由后台直接创建 Agency;父级 BD 可选,并原子创建 owner 的 host_profile 和 owner membership。 func (s *Service) CreateAgency(ctx context.Context, command CreateAgencyInput) (hostdomain.CreateAgencyResult, error) { if err := s.requireWriteDependencies(); err != nil { return hostdomain.CreateAgencyResult{}, err } name := strings.TrimSpace(command.Name) - if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.OwnerUserID <= 0 || command.ParentBDUserID <= 0 || name == "" { - return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id, owner_user_id, parent_bd_user_id and name are required") + if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.OwnerUserID <= 0 || name == "" { + return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id, owner_user_id and name are required") + } + if command.ParentBDUserID < 0 { + return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "parent_bd_user_id must not be negative") } if command.MaxHosts < 0 { return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "max_hosts must not be negative") diff --git a/services/user-service/internal/service/host/service_test.go b/services/user-service/internal/service/host/service_test.go index 8ab15cdc..a99484c4 100644 --- a/services/user-service/internal/service/host/service_test.go +++ b/services/user-service/internal/service/host/service_test.go @@ -272,6 +272,7 @@ func TestAdminCreateBDLeaderAndBDIdempotently(t *testing.T) { repository.PutRegion(userdomain.Region{RegionID: 20, RegionCode: "R20", Name: "Region 20"}) seedActiveUser(t, repository, 801, 10) seedActiveUser(t, repository, 802, 20) + seedActiveUser(t, repository, 804, 20) svc := newHostService(repository, 4000, 5000) leader, err := svc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ @@ -323,6 +324,20 @@ func TestAdminCreateBDLeaderAndBDIdempotently(t *testing.T) { t.Fatalf("bd mismatch: %+v", bd) } + independentBD, err := svc.CreateBD(ctx, hostservice.CreateBDInput{ + CommandID: "admin-create-bd-804-independent", + AdminUserID: 1, + TargetUserID: 804, + Reason: "seed independent bd", + RequestID: "req-bd-independent-1", + }) + if err != nil { + t.Fatalf("CreateBD without parent leader failed: %v", err) + } + if independentBD.Role != hostdomain.BDRoleBD || independentBD.ParentLeaderUserID != 0 || independentBD.RegionID != 20 { + t.Fatalf("independent bd mismatch: %+v", independentBD) + } + disabled, err := svc.SetBDStatus(ctx, hostservice.SetBDStatusInput{ CommandID: "admin-disable-bd-802", AdminUserID: 1, @@ -466,6 +481,33 @@ func TestAdminCreateAgencyControlsAppSearch(t *testing.T) { } } +func TestAdminCreateAgencyWithoutParentBD(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + seedActiveUser(t, repository, 904, 31) + svc := newHostService(repository, 5600, 6600) + + created, err := svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ + CommandID: "admin-create-agency-904-independent", + AdminUserID: 1, + OwnerUserID: 904, + Name: "Independent Agency", + JoinEnabled: true, + MaxHosts: 20, + Reason: "seed independent agency", + RequestID: "req-agency-independent-1", + }) + if err != nil { + t.Fatalf("CreateAgency without parent bd failed: %v", err) + } + if created.Agency.OwnerUserID != 904 || created.Agency.ParentBDUserID != 0 || created.Agency.RegionID != 31 || !created.Agency.JoinEnabled { + t.Fatalf("independent agency mismatch: %+v", created.Agency) + } + if created.HostProfile.CurrentAgencyID != created.Agency.AgencyID || created.Membership.MembershipType != hostdomain.MembershipTypeOwner { + t.Fatalf("independent agency owner facts mismatch: host=%+v membership=%+v", created.HostProfile, created.Membership) + } +} + func TestAdminCreateAgencyRejectsExistingHost(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) diff --git a/services/user-service/internal/storage/mysql/host/admin.go b/services/user-service/internal/storage/mysql/host/admin.go index 2235ec2e..54813f18 100644 --- a/services/user-service/internal/storage/mysql/host/admin.go +++ b/services/user-service/internal/storage/mysql/host/admin.go @@ -67,7 +67,7 @@ func (r *Repository) CreateBDLeader(ctx context.Context, command hostservice.Cre return profile, nil } -// CreateBD 创建普通 BD,并把它固定到一个有效 BD 负责人名下。 +// CreateBD 创建普通 BD;父级 Leader 可选,填入时必须是同区域有效 Leader。 func (r *Repository) CreateBD(ctx context.Context, command hostservice.CreateBDCommand) (hostdomain.BDProfile, error) { tx, err := r.db.BeginTx(ctx, nil) if err != nil { @@ -84,19 +84,22 @@ func (r *Repository) CreateBD(ctx context.Context, command hostservice.CreateBDC return queryBDProfile(ctx, tx, "WHERE user_id = ?", existing.ResultID) } - leader, err := queryBDProfile(ctx, tx, "WHERE user_id = ? FOR UPDATE", command.ParentLeaderUserID) - if err != nil { - return hostdomain.BDProfile{}, err - } - if leader.Status != hostdomain.BDStatusActive || leader.Role != hostdomain.BDRoleLeader { - return hostdomain.BDProfile{}, xerr.New(xerr.PermissionDenied, "parent leader is not active") - } regionID, err := r.userRegion(ctx, tx, command.TargetUserID, "FOR UPDATE") if err != nil { return hostdomain.BDProfile{}, err } - if regionID != leader.RegionID { - return hostdomain.BDProfile{}, xerr.New(xerr.PermissionDenied, "target region does not match leader region") + if command.ParentLeaderUserID > 0 { + // 独立 BD 不需要父级行锁;只有传入 Leader 时才校验 Leader 身份、启用状态和区域归属。 + leader, err := queryBDProfile(ctx, tx, "WHERE user_id = ? FOR UPDATE", command.ParentLeaderUserID) + if err != nil { + return hostdomain.BDProfile{}, err + } + if leader.Status != hostdomain.BDStatusActive || leader.Role != hostdomain.BDRoleLeader { + return hostdomain.BDProfile{}, xerr.New(xerr.PermissionDenied, "parent leader is not active") + } + if regionID != leader.RegionID { + return hostdomain.BDProfile{}, xerr.New(xerr.PermissionDenied, "target region does not match leader region") + } } if _, ok, err := queryBDProfileByUserMaybe(ctx, tx, command.TargetUserID, true); err != nil { return hostdomain.BDProfile{}, err @@ -256,7 +259,7 @@ func (r *Repository) SetCoinSellerStatus(ctx context.Context, command hostservic return after, nil } -// CreateAgency 后台直建 Agency,并原子创建 owner 的 Host 身份和拥有者成员关系。 +// CreateAgency 后台直建 Agency;父级 BD 可选,填入时必须是同区域有效 BD。 func (r *Repository) CreateAgency(ctx context.Context, command hostservice.CreateAgencyCommand) (hostdomain.CreateAgencyResult, error) { tx, err := r.db.BeginTx(ctx, nil) if err != nil { @@ -273,19 +276,22 @@ func (r *Repository) CreateAgency(ctx context.Context, command hostservice.Creat return createAgencyResultByAgencyID(ctx, tx, existing.ResultID) } - parentBD, err := queryBDProfile(ctx, tx, "WHERE user_id = ? FOR UPDATE", command.ParentBDUserID) - if err != nil { - return hostdomain.CreateAgencyResult{}, err - } - if parentBD.Status != hostdomain.BDStatusActive { - return hostdomain.CreateAgencyResult{}, xerr.New(xerr.PermissionDenied, "parent bd is not active") - } regionID, err := r.userRegion(ctx, tx, command.OwnerUserID, "FOR UPDATE") if err != nil { return hostdomain.CreateAgencyResult{}, err } - if regionID != parentBD.RegionID { - return hostdomain.CreateAgencyResult{}, xerr.New(xerr.PermissionDenied, "owner region does not match parent bd region") + if command.ParentBDUserID > 0 { + // 独立 Agency 不需要父级行锁;只有传入 BD 时才校验 BD 启用状态和同区域归属。 + parentBD, err := queryBDProfile(ctx, tx, "WHERE user_id = ? FOR UPDATE", command.ParentBDUserID) + if err != nil { + return hostdomain.CreateAgencyResult{}, err + } + if parentBD.Status != hostdomain.BDStatusActive { + return hostdomain.CreateAgencyResult{}, xerr.New(xerr.PermissionDenied, "parent bd is not active") + } + if regionID != parentBD.RegionID { + return hostdomain.CreateAgencyResult{}, xerr.New(xerr.PermissionDenied, "owner region does not match parent bd region") + } } if _, ok, err := queryActiveAgencyByOwner(ctx, tx, command.OwnerUserID, true); err != nil { return hostdomain.CreateAgencyResult{}, err 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 5d3b6053..f6151479 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -1190,5 +1190,5 @@ INSERT IGNORE INTO gift_diamond_ratio_configs ( created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms ) VALUES ('lalu', 0, 'normal', 'active', 100.00, 0, 0, 0, 0), - ('lalu', 0, 'lucky', 'active', 100.00, 0, 0, 0, 0), - ('lalu', 0, 'super_lucky', 'active', 100.00, 0, 0, 0, 0); + ('lalu', 0, 'lucky', 'active', 10.00, 0, 0, 0, 0), + ('lalu', 0, 'super_lucky', 'active', 1.00, 0, 0, 0, 0); diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index f312ba9a..6f2813cf 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -216,7 +216,7 @@ func TestDebitGiftCreditsHostPeriodDiamondsOnlyForHost(t *testing.T) { } } -func TestDebitGiftCreditsHostPeriodDiamondsBySenderRegionAndGiftType(t *testing.T) { +func TestDebitGiftCreditsHostPeriodDiamondsByGlobalDefaultAndGiftType(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) repository.SetGiftDiamondRatio(1001, resourcedomain.GiftTypeNormal, "30.00") @@ -228,16 +228,17 @@ func TestDebitGiftCreditsHostPeriodDiamondsBySenderRegionAndGiftType(t *testing. giftType string commandID string senderID int64 + coinPrice int64 wantDiamond int64 }{ - {giftID: "normal-ratio-gift", giftType: resourcedomain.GiftTypeNormal, commandID: "cmd-normal-ratio", senderID: 11001, wantDiamond: 30}, - {giftID: "lucky-ratio-gift", giftType: resourcedomain.GiftTypeLucky, commandID: "cmd-lucky-ratio", senderID: 11002, wantDiamond: 40}, - {giftID: "super-lucky-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, commandID: "cmd-super-lucky-ratio", senderID: 11003, wantDiamond: 50}, + {giftID: "normal-ratio-gift", giftType: resourcedomain.GiftTypeNormal, commandID: "cmd-normal-ratio", senderID: 11001, coinPrice: 100, wantDiamond: 100}, + {giftID: "lucky-ratio-gift", giftType: resourcedomain.GiftTypeLucky, commandID: "cmd-lucky-ratio", senderID: 11002, coinPrice: 100, wantDiamond: 10}, + {giftID: "super-lucky-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, commandID: "cmd-super-lucky-ratio", senderID: 11003, coinPrice: 99, wantDiamond: 0}, } for _, tc := range cases { repository.SetBalance(tc.senderID, 100) - repository.SetGiftPrice(tc.giftID, "v1", 100, 100, 100) + repository.SetGiftPrice(tc.giftID, "v1", tc.coinPrice, 100, tc.coinPrice) repository.SetGiftType(tc.giftID, tc.giftType) receipt, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ CommandID: tc.commandID, @@ -258,12 +259,12 @@ func TestDebitGiftCreditsHostPeriodDiamondsBySenderRegionAndGiftType(t *testing. t.Fatalf("%s ratio diamond mismatch: got %+v want %d", tc.giftType, receipt, tc.wantDiamond) } } - if got := repository.HostPeriodGiftDiamondTotal(12001); got != 120 { + if got := repository.HostPeriodGiftDiamondTotal(12001); got != 110 { t.Fatalf("host period account total mismatch, got %d", got) } } -func TestDebitGiftAppliesRoomRegionGiftDiamondRatioToHeatValueByGiftType(t *testing.T) { +func TestDebitGiftAppliesGlobalDefaultGiftDiamondRatioToHeatValueByGiftType(t *testing.T) { repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) repository.SetGiftDiamondRatio(8801, resourcedomain.GiftTypeNormal, "30.00") @@ -275,16 +276,17 @@ func TestDebitGiftAppliesRoomRegionGiftDiamondRatioToHeatValueByGiftType(t *test giftType string command string senderID int64 + heatUnit int64 wantHeat int64 }{ - {giftID: "normal-room-ratio-gift", giftType: resourcedomain.GiftTypeNormal, command: "cmd-normal-room-ratio", senderID: 13001, wantHeat: 30}, - {giftID: "lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeLucky, command: "cmd-lucky-room-ratio", senderID: 13002, wantHeat: 40}, - {giftID: "super-lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, command: "cmd-super-lucky-room-ratio", senderID: 13003, wantHeat: 50}, + {giftID: "normal-room-ratio-gift", giftType: resourcedomain.GiftTypeNormal, command: "cmd-normal-room-ratio", senderID: 13001, heatUnit: 100, wantHeat: 100}, + {giftID: "lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeLucky, command: "cmd-lucky-room-ratio", senderID: 13002, heatUnit: 100, wantHeat: 10}, + {giftID: "super-lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, command: "cmd-super-lucky-room-ratio", senderID: 13003, heatUnit: 99, wantHeat: 0}, } for _, tc := range cases { repository.SetBalance(tc.senderID, 100) - repository.SetGiftPrice(tc.giftID, "v1", 100, 100, 100) + repository.SetGiftPrice(tc.giftID, "v1", tc.heatUnit, 100, tc.heatUnit) repository.SetGiftType(tc.giftID, tc.giftType) receipt, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ CommandID: tc.command, @@ -300,13 +302,13 @@ func TestDebitGiftAppliesRoomRegionGiftDiamondRatioToHeatValueByGiftType(t *test if err != nil { t.Fatalf("DebitGift %s failed: %v", tc.giftType, err) } - if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != 100 { + if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != tc.heatUnit { t.Fatalf("%s room contribution ratio mismatch: %+v want heat %d", tc.giftType, receipt, tc.wantHeat) } } } -func TestBatchDebitGiftAppliesRoomRegionGiftDiamondRatioToEachTargetHeatValue(t *testing.T) { +func TestBatchDebitGiftAppliesGlobalDefaultGiftDiamondRatioToEachTargetHeatValue(t *testing.T) { repository := mysqltest.NewRepository(t) repository.SetBalance(15001, 1000) repository.SetGiftPrice("batch-room-ratio-gift", "v1", 100, 100, 100) @@ -331,11 +333,11 @@ func TestBatchDebitGiftAppliesRoomRegionGiftDiamondRatioToEachTargetHeatValue(t if err != nil { t.Fatalf("BatchDebitGift failed: %v", err) } - if receipt.Aggregate.HeatValue != 50 || len(receipt.Targets) != 2 { + if receipt.Aggregate.HeatValue != 20 || len(receipt.Targets) != 2 { t.Fatalf("batch aggregate room contribution ratio mismatch: %+v", receipt) } for _, target := range receipt.Targets { - if target.Receipt.HeatValue != 25 || target.Receipt.GiftPointAdded != 100 { + if target.Receipt.HeatValue != 10 || target.Receipt.GiftPointAdded != 100 { t.Fatalf("target room contribution ratio mismatch: %+v", target) } } @@ -3619,6 +3621,12 @@ func TestConfirmGooglePaymentUsesProductNameAsGoogleProductID(t *testing.T) { if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 1 { t.Fatalf("google payment should write one wallet entry, got %d", got) } + if got := repository.CountRows("wallet_recharge_records", "transaction_id = ? AND coin_amount = ? AND usd_minor_amount = ? AND exchange_usd_minor_amount = ?", receipt.TransactionID, int64(1500), int64(150), int64(150)); got != 1 { + t.Fatalf("google payment should write recharge USD minor from micro amount, got %d", got) + } + if got := repository.CountRows("wallet_user_recharge_stats", "user_id = ? AND total_coin_amount = ? AND total_usd_minor_amount = ?", int64(53001), int64(1500), int64(150)); got != 1 { + t.Fatalf("google payment should aggregate recharge USD minor from micro amount, got %d", got) + } } func TestApplyGameCoinChangeDebitCreditAndIdempotency(t *testing.T) { diff --git a/services/wallet-service/internal/storage/mysql/google_payment_repository.go b/services/wallet-service/internal/storage/mysql/google_payment_repository.go index 3bbffa87..e86b7243 100644 --- a/services/wallet-service/internal/storage/mysql/google_payment_repository.go +++ b/services/wallet-service/internal/storage/mysql/google_payment_repository.go @@ -54,7 +54,9 @@ func (r *Repository) ConfirmGooglePayment(ctx context.Context, command ledger.Go transactionID := transactionID(command.AppCode, command.CommandID) paymentOrderID := googlePaymentOrderID(command.AppCode, tokenHash) balanceAfter := account.AvailableAmount + product.CoinAmount - rechargeSequence, err := r.reserveUserRechargeSequence(ctx, tx, command.AppCode, command.UserID, transactionID, product.CoinAmount, product.AmountMicro, nowMs) + // Google Play 返回和后台商品都保存微单位价格;充值事实表使用美元最小单位,必须在写账前收敛成美分。 + rechargeUSDMinor := googleAmountMicroToUSDMinor(product.AmountMicro) + rechargeSequence, err := r.reserveUserRechargeSequence(ctx, tx, command.AppCode, command.UserID, transactionID, product.CoinAmount, rechargeUSDMinor, nowMs) if err != nil { return ledger.GooglePaymentReceipt{}, err } @@ -79,6 +81,7 @@ func (r *Repository) ConfirmGooglePayment(ctx context.Context, command ledger.Go CoinAmount: product.CoinAmount, CurrencyCode: product.CurrencyCode, AmountMicro: product.AmountMicro, + RechargeUSDMinor: rechargeUSDMinor, BalanceAfter: balanceAfter, RechargeSequence: rechargeSequence, CreatedAtMS: nowMs, @@ -109,11 +112,11 @@ func (r *Repository) ConfirmGooglePayment(ctx context.Context, command ledger.Go TargetAssetType: ledger.AssetCoin, TargetBalanceAfter: balanceAfter, RechargeSequence: rechargeSequence, - RechargeUSDMinor: product.AmountMicro, + RechargeUSDMinor: rechargeUSDMinor, RechargeCurrencyCode: product.CurrencyCode, RechargePolicyVersion: product.PolicyVersion, RechargePolicyCoinAmount: product.CoinAmount, - RechargePolicyUSDMinorAmount: product.AmountMicro, + RechargePolicyUSDMinorAmount: rechargeUSDMinor, }, nowMs); err != nil { return ledger.GooglePaymentReceipt{}, err } @@ -306,11 +309,19 @@ type googlePaymentMetadata struct { CoinAmount int64 `json:"coin_amount"` CurrencyCode string `json:"currency_code"` AmountMicro int64 `json:"amount_micro"` + RechargeUSDMinor int64 `json:"recharge_usd_minor"` BalanceAfter int64 `json:"balance_after"` RechargeSequence int64 `json:"recharge_sequence"` CreatedAtMS int64 `json:"created_at_ms"` } +func googleAmountMicroToUSDMinor(amountMicro int64) int64 { + if amountMicro <= 0 { + return 0 + } + return amountMicro / 10_000 +} + func googlePaymentCreditedEvent(transactionID string, commandID string, metadata googlePaymentMetadata, nowMs int64) walletOutboxEvent { return walletOutboxEvent{ EventID: eventID(transactionID, "WalletGooglePaymentCredited", metadata.UserID, ledger.AssetCoin), diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 6e87b2c8..60f69e6d 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -128,8 +128,8 @@ func ensureGiftDiamondRatioSchema(ctx context.Context, db *sql.DB) error { created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms ) VALUES ('lalu', 0, 'normal', 'active', 100.00, 0, 0, 0, 0), - ('lalu', 0, 'lucky', 'active', 100.00, 0, 0, 0, 0), - ('lalu', 0, 'super_lucky', 'active', 100.00, 0, 0, 0, 0)`) + ('lalu', 0, 'lucky', 'active', 10.00, 0, 0, 0, 0), + ('lalu', 0, 'super_lucky', 'active', 1.00, 0, 0, 0, 0)`) return err } @@ -226,11 +226,11 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if err != nil { return ledger.Receipt{}, err } - roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.RegionID, giftConfig.GiftTypeCode) + roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.Receipt{}, err } - // 房间贡献由房间 visible_region_id 命中后台礼物钻石比例;room-service 只消费结算后的 heat_value,不再自己查钱包配置。 + // 房间贡献统一按全局默认礼物比例折算;room-service 只消费结算后的 heat_value,不再自己查钱包配置。 heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) if err != nil { return ledger.Receipt{}, err @@ -240,7 +240,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm giftDiamondRatioPercent := "0.00" giftDiamondRatioRegionID := int64(0) if command.TargetIsHost { - ratio, ratioRegionID, err := r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.SenderRegionID, giftConfig.GiftTypeCode) + ratio, ratioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.Receipt{}, err } @@ -414,11 +414,11 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb if err != nil { return ledger.BatchGiftReceipt{}, err } - roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.RegionID, giftConfig.GiftTypeCode) + roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.BatchGiftReceipt{}, err } - // 批量多目标仍然是每个目标各送一份同款礼物;每份房间贡献先按房间区域比例折算,再由聚合回执累加。 + // 批量多目标仍然是每个目标各送一份同款礼物;每份房间贡献先按全局默认礼物比例折算,再由聚合回执累加。 heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) if err != nil { return ledger.BatchGiftReceipt{}, err @@ -489,7 +489,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb hostRatio := giftDiamondRatioSnapshot{Percent: "0.00", PPM: 0} hostRatioRegionID := int64(0) if anyHostTarget { - hostRatio, hostRatioRegionID, err = r.resolveGiftDiamondRatio(ctx, tx, command.AppCode, command.SenderRegionID, giftConfig.GiftTypeCode) + hostRatio, hostRatioRegionID, err = r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.BatchGiftReceipt{}, err } @@ -1754,7 +1754,12 @@ func (r *Repository) resolveGiftDiamondRatio(ctx context.Context, tx *sql.Tx, ap return ratio, regionID, nil } } - return giftDiamondRatioSnapshot{Percent: "100.00", PPM: 1_000_000}, 0, nil + return defaultGiftDiamondRatio(giftTypeCode), 0, nil +} + +func (r *Repository) resolveGlobalGiftDiamondRatio(ctx context.Context, tx *sql.Tx, appCode string, giftTypeCode string) (giftDiamondRatioSnapshot, int64, error) { + // 送礼运行链路只认后台“全局默认”行,避免房间区域或送礼人区域把贡献值和主播钻石算成不同口径。 + return r.resolveGiftDiamondRatio(ctx, tx, appCode, 0, giftTypeCode) } func (r *Repository) getGiftDiamondRatio(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, giftTypeCode string) (giftDiamondRatioSnapshot, bool, error) { @@ -1794,6 +1799,17 @@ func giftDiamondAmount(chargeAmount int64, ratioPPM int64) (int64, error) { return product / 1_000_000, nil } +func defaultGiftDiamondRatio(giftTypeCode string) giftDiamondRatioSnapshot { + switch strings.TrimSpace(giftTypeCode) { + case "lucky": + return giftDiamondRatioSnapshot{Percent: "10.00", PPM: 100_000} + case "super_lucky": + return giftDiamondRatioSnapshot{Percent: "1.00", PPM: 10_000} + default: + return giftDiamondRatioSnapshot{Percent: "100.00", PPM: 1_000_000} + } +} + func (r *Repository) resolveRechargePolicy(ctx context.Context, tx *sql.Tx, regionID int64, nowMs int64) (rechargePolicy, error) { row := tx.QueryRowContext(ctx, `SELECT policy_id, region_id, policy_version, currency_code, coin_amount, usd_minor_amount, effective_from_ms From b1a9d818aaaf10261979fd75feb6ff9e4bd56f46 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 13:51:14 +0800 Subject: [PATCH 14/28] fix: settle gift contribution by coin spent --- server/admin/internal/modules/resource/dto.go | 2 -- .../internal/modules/resource/request.go | 6 ++-- .../internal/service/wallet/service_test.go | 35 ++++++++++--------- .../internal/storage/mysql/repository.go | 20 ++++------- .../storage/mysql/resource_repository.go | 10 ++++-- 5 files changed, 34 insertions(+), 39 deletions(-) diff --git a/server/admin/internal/modules/resource/dto.go b/server/admin/internal/modules/resource/dto.go index 0e8161cb..f232ebd6 100644 --- a/server/admin/internal/modules/resource/dto.go +++ b/server/admin/internal/modules/resource/dto.go @@ -75,7 +75,6 @@ type giftDTO struct { ChargeAssetType string `json:"chargeAssetType"` CoinPrice int64 `json:"coinPrice"` GiftPointAmount int64 `json:"giftPointAmount"` - HeatValue int64 `json:"heatValue"` EffectiveFromMS int64 `json:"effectiveFromMs"` EffectiveToMS int64 `json:"effectiveToMs"` EffectTypes []string `json:"effectTypes"` @@ -300,7 +299,6 @@ func giftFromProto(gift *walletv1.GiftConfig) giftDTO { ChargeAssetType: gift.GetChargeAssetType(), CoinPrice: gift.GetCoinPrice(), GiftPointAmount: gift.GetGiftPointAmount(), - HeatValue: gift.GetHeatValue(), EffectiveFromMS: gift.GetEffectiveFromMs(), EffectiveToMS: gift.GetEffectiveToMs(), EffectTypes: gift.GetEffectTypes(), diff --git a/server/admin/internal/modules/resource/request.go b/server/admin/internal/modules/resource/request.go index 81426397..ec2c2008 100644 --- a/server/admin/internal/modules/resource/request.go +++ b/server/admin/internal/modules/resource/request.go @@ -135,7 +135,7 @@ type giftRequest struct { ChargeAssetType string `json:"chargeAssetType"` CoinPrice int64 `json:"coinPrice"` GiftPointAmount int64 `json:"giftPointAmount"` - HeatValue int64 `json:"heatValue"` + HeatValue int64 `json:"heatValue"` // 兼容旧后台请求;新后台不再展示或提交热度。 EffectiveAtMS int64 `json:"effectiveAtMs"` EffectiveFromMS int64 `json:"effectiveFromMs"` EffectiveToMS int64 `json:"effectiveToMs"` @@ -371,7 +371,7 @@ func (r giftRequest) createProto(c *gin.Context) *walletv1.CreateGiftConfigReque ChargeAssetType: strings.TrimSpace(r.ChargeAssetType), CoinPrice: r.CoinPrice, GiftPointAmount: r.GiftPointAmount, - HeatValue: r.HeatValue, + HeatValue: r.CoinPrice, EffectiveAtMs: r.EffectiveAtMS, EffectiveFromMs: r.EffectiveFromMS, EffectiveToMs: r.EffectiveToMS, @@ -396,7 +396,7 @@ func (r giftRequest) updateProto(c *gin.Context, giftID string) *walletv1.Update ChargeAssetType: strings.TrimSpace(r.ChargeAssetType), CoinPrice: r.CoinPrice, GiftPointAmount: r.GiftPointAmount, - HeatValue: r.HeatValue, + HeatValue: r.CoinPrice, EffectiveAtMs: r.EffectiveAtMS, EffectiveFromMs: r.EffectiveFromMS, EffectiveToMs: r.EffectiveToMS, diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 6f2813cf..4bd94a25 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -54,7 +54,7 @@ func TestDebitGiftUsesServerPriceAndCreditsGiftPoint(t *testing.T) { t.Fatalf("DebitGift failed: %v", err) } - if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 6 || receipt.HeatValue != 22 || receipt.BalanceAfter != 86 || receipt.PriceVersion != "v9" { + if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 6 || receipt.HeatValue != 14 || receipt.BalanceAfter != 86 || receipt.PriceVersion != "v9" { t.Fatalf("server price settlement mismatch: %+v", receipt) } if receipt.TransactionID == "" || receipt.BillingReceiptID == "" { @@ -113,7 +113,7 @@ func TestBatchDebitGiftSettlesAllTargetsAtomically(t *testing.T) { t.Fatalf("BatchDebitGift failed: %v", err) } - if receipt.Aggregate.CoinSpent != 28 || receipt.Aggregate.GiftPointAdded != 12 || receipt.Aggregate.HeatValue != 44 || receipt.Aggregate.BalanceAfter != 72 || len(receipt.Targets) != 2 { + if receipt.Aggregate.CoinSpent != 28 || receipt.Aggregate.GiftPointAdded != 12 || receipt.Aggregate.HeatValue != 28 || receipt.Aggregate.BalanceAfter != 72 || len(receipt.Targets) != 2 { t.Fatalf("batch aggregate mismatch: %+v", receipt) } for _, userID := range []int64{10002, 10003} { @@ -272,21 +272,22 @@ func TestDebitGiftAppliesGlobalDefaultGiftDiamondRatioToHeatValueByGiftType(t *t repository.SetGiftDiamondRatio(8801, resourcedomain.GiftTypeSuperLucky, "50.00") cases := []struct { - giftID string - giftType string - command string - senderID int64 - heatUnit int64 - wantHeat int64 + giftID string + giftType string + command string + senderID int64 + coinPrice int64 + heatUnit int64 + wantHeat int64 }{ - {giftID: "normal-room-ratio-gift", giftType: resourcedomain.GiftTypeNormal, command: "cmd-normal-room-ratio", senderID: 13001, heatUnit: 100, wantHeat: 100}, - {giftID: "lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeLucky, command: "cmd-lucky-room-ratio", senderID: 13002, heatUnit: 100, wantHeat: 10}, - {giftID: "super-lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, command: "cmd-super-lucky-room-ratio", senderID: 13003, heatUnit: 99, wantHeat: 0}, + {giftID: "normal-room-ratio-gift", giftType: resourcedomain.GiftTypeNormal, command: "cmd-normal-room-ratio", senderID: 13001, coinPrice: 100, heatUnit: 999, wantHeat: 100}, + {giftID: "lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeLucky, command: "cmd-lucky-room-ratio", senderID: 13002, coinPrice: 100, heatUnit: 999, wantHeat: 10}, + {giftID: "super-lucky-room-ratio-gift", giftType: resourcedomain.GiftTypeSuperLucky, command: "cmd-super-lucky-room-ratio", senderID: 13003, coinPrice: 200, heatUnit: 500, wantHeat: 2}, } for _, tc := range cases { - repository.SetBalance(tc.senderID, 100) - repository.SetGiftPrice(tc.giftID, "v1", tc.heatUnit, 100, tc.heatUnit) + repository.SetBalance(tc.senderID, 500) + repository.SetGiftPrice(tc.giftID, "v1", tc.coinPrice, 100, tc.heatUnit) repository.SetGiftType(tc.giftID, tc.giftType) receipt, err := svc.DebitGift(context.Background(), ledger.DebitGiftCommand{ CommandID: tc.command, @@ -302,7 +303,7 @@ func TestDebitGiftAppliesGlobalDefaultGiftDiamondRatioToHeatValueByGiftType(t *t if err != nil { t.Fatalf("DebitGift %s failed: %v", tc.giftType, err) } - if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != tc.heatUnit { + if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != tc.coinPrice { t.Fatalf("%s room contribution ratio mismatch: %+v want heat %d", tc.giftType, receipt, tc.wantHeat) } } @@ -311,7 +312,7 @@ func TestDebitGiftAppliesGlobalDefaultGiftDiamondRatioToHeatValueByGiftType(t *t func TestBatchDebitGiftAppliesGlobalDefaultGiftDiamondRatioToEachTargetHeatValue(t *testing.T) { repository := mysqltest.NewRepository(t) repository.SetBalance(15001, 1000) - repository.SetGiftPrice("batch-room-ratio-gift", "v1", 100, 100, 100) + repository.SetGiftPrice("batch-room-ratio-gift", "v1", 100, 100, 999) repository.SetGiftType("batch-room-ratio-gift", resourcedomain.GiftTypeLucky) repository.SetGiftDiamondRatio(9901, resourcedomain.GiftTypeLucky, "25.00") svc := walletservice.New(repository) @@ -1085,7 +1086,7 @@ func TestGetUserGiftWallAggregatesSettledGifts(t *testing.T) { if err != nil { t.Fatalf("GetUserGiftWall failed: %v", err) } - if wall.GiftKindCount != 2 || wall.GiftTotalCount != 6 || wall.TotalValue != 135 || wall.TotalGiftPoint != 65 || wall.TotalHeatValue != 255 { + if wall.GiftKindCount != 2 || wall.GiftTotalCount != 6 || wall.TotalValue != 135 || wall.TotalGiftPoint != 65 || wall.TotalHeatValue != 135 { t.Fatalf("gift wall summary mismatch: %+v", wall) } rose, ok := giftWallItemByID(wall.Items, "rose") @@ -2150,7 +2151,7 @@ func TestGiftConfigMustSelectGiftResource(t *testing.T) { if err != nil { t.Fatalf("DebitGift with resource-backed gift failed: %v", err) } - if receipt.CoinSpent != 10 || receipt.GiftPointAdded != 4 || receipt.HeatValue != 18 { + if receipt.CoinSpent != 10 || receipt.GiftPointAdded != 4 || receipt.HeatValue != 10 { t.Fatalf("resource-backed gift settlement mismatch: %+v", receipt) } } diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 60f69e6d..95a24148 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -222,16 +222,12 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if err != nil { return ledger.Receipt{}, err } - baseHeatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) - if err != nil { - return ledger.Receipt{}, err - } roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.Receipt{}, err } - // 房间贡献统一按全局默认礼物比例折算;room-service 只消费结算后的 heat_value,不再自己查钱包配置。 - heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) + // 房间贡献只以真实扣费 COIN 为基数;旧 gift price heat_value 不再参与结算,避免后台热度配置覆盖实际消费。 + heatValue, err := giftDiamondAmount(chargeAmount, roomContributionRatio.PPM) if err != nil { return ledger.Receipt{}, err } @@ -301,7 +297,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm RoomContributionRatioRegionID: roomContributionRatioRegionID, CoinPrice: price.CoinPrice, GiftPointAmount: price.GiftPointAmount, - HeatUnitValue: price.HeatValue, + HeatUnitValue: price.CoinPrice, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeGiftDebit, requestHash, fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { return ledger.Receipt{}, err @@ -410,16 +406,12 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb if err != nil { return ledger.BatchGiftReceipt{}, err } - baseHeatValue, err := checkedMul(price.HeatValue, int64(command.GiftCount)) - if err != nil { - return ledger.BatchGiftReceipt{}, err - } roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.BatchGiftReceipt{}, err } - // 批量多目标仍然是每个目标各送一份同款礼物;每份房间贡献先按全局默认礼物比例折算,再由聚合回执累加。 - heatValue, err := giftDiamondAmount(baseHeatValue, roomContributionRatio.PPM) + // 批量多目标仍然是每个目标各送一份同款礼物;每份房间贡献先按真实扣费折算,再由聚合回执累加。 + heatValue, err := giftDiamondAmount(chargeAmount, roomContributionRatio.PPM) if err != nil { return ledger.BatchGiftReceipt{}, err } @@ -549,7 +541,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb RoomContributionRatioRegionID: roomContributionRatioRegionID, CoinPrice: price.CoinPrice, GiftPointAmount: price.GiftPointAmount, - HeatUnitValue: price.HeatValue, + HeatUnitValue: price.CoinPrice, } if err := r.insertTransaction(ctx, tx, transactionID, target.CommandID, bizTypeGiftDebit, debitRequestHash(debitGiftCommandFromBatchTarget(command, target)), fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { return ledger.BatchGiftReceipt{}, err diff --git a/services/wallet-service/internal/storage/mysql/resource_repository.go b/services/wallet-service/internal/storage/mysql/resource_repository.go index 213181a7..f23a2355 100644 --- a/services/wallet-service/internal/storage/mysql/resource_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_repository.go @@ -628,7 +628,7 @@ func (r *Repository) ListGiftConfigs(ctx context.Context, query resourcedomain.L item.ChargeAssetType = price.ChargeAssetType item.CoinPrice = price.CoinPrice item.GiftPointAmount = price.GiftPointAmount - item.HeatValue = price.HeatValue + item.HeatValue = price.CoinPrice } items = append(items, item) } @@ -1952,6 +1952,7 @@ func (r *Repository) listResourceGrantItemsWithQuery(ctx context.Context, querie } func (r *Repository) upsertGiftPriceTx(ctx context.Context, tx *sql.Tx, command resourcedomain.GiftConfigCommand, nowMs int64) error { + legacyHeatValue := command.CoinPrice _, err := tx.ExecContext(ctx, ` INSERT INTO wallet_gift_prices ( app_code, gift_id, price_version, status, charge_asset_type, coin_price, gift_point_amount, @@ -1966,7 +1967,7 @@ func (r *Repository) upsertGiftPriceTx(ctx context.Context, tx *sql.Tx, command effective_at_ms = VALUES(effective_at_ms), updated_at_ms = VALUES(updated_at_ms)`, appcode.FromContext(ctx), command.GiftID, command.PriceVersion, command.ChargeAssetType, command.CoinPrice, - command.GiftPointAmount, command.HeatValue, command.EffectiveAtMS, nowMs, nowMs, + command.GiftPointAmount, legacyHeatValue, command.EffectiveAtMS, nowMs, nowMs, ) return err } @@ -2006,7 +2007,8 @@ func (r *Repository) getGiftConfig(ctx context.Context, giftID string) (resource gift.ChargeAssetType = price.ChargeAssetType gift.CoinPrice = price.CoinPrice gift.GiftPointAmount = price.GiftPointAmount - gift.HeatValue = price.HeatValue + // heat_value 是旧配置列,后台不再读写;对兼容调用方只回真实价格,房间贡献也按真实扣费结算。 + gift.HeatValue = price.CoinPrice } gift.RegionIDs, err = r.listGiftConfigRegionIDs(ctx, r.db, gift.GiftID) if err != nil { @@ -3269,6 +3271,8 @@ func applyResourcePricingToGiftCommand(command resourcedomain.GiftConfigCommand, command.CoinPrice = 0 command.GiftPointAmount = 0 } + // 后台已取消热度配置;旧列只保留兼容写入,数值始终跟真实 COIN 价格一致。 + command.HeatValue = command.CoinPrice return command } From c56186ab48e232af78c93425c714cc9cf383b731 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 13:58:16 +0800 Subject: [PATCH 15/28] feat: update app user admin fields --- .../admin/internal/modules/appuser/handler.go | 10 +- .../admin/internal/modules/appuser/request.go | 10 +- .../admin/internal/modules/appuser/service.go | 227 +++++++++++++++--- .../internal/modules/appuser/service_test.go | 45 ++++ 4 files changed, 245 insertions(+), 47 deletions(-) create mode 100644 server/admin/internal/modules/appuser/service_test.go diff --git a/server/admin/internal/modules/appuser/handler.go b/server/admin/internal/modules/appuser/handler.go index c95873e2..3b67b485 100644 --- a/server/admin/internal/modules/appuser/handler.go +++ b/server/admin/internal/modules/appuser/handler.go @@ -155,10 +155,12 @@ func (h *Handler) setUserStatus(c *gin.Context, status string, action string, su func parseListQuery(c *gin.Context) listQuery { options := shared.ListOptions(c) return normalizeListQuery(listQuery{ - Page: options.Page, - PageSize: options.PageSize, - Keyword: options.Keyword, - Status: options.Status, + Page: options.Page, + PageSize: options.PageSize, + Keyword: options.Keyword, + Status: options.Status, + SortBy: firstQuery(c, "sort_by", "sortBy"), + SortDirection: firstQuery(c, "sort_direction", "sortDirection", "order"), }) } diff --git a/server/admin/internal/modules/appuser/request.go b/server/admin/internal/modules/appuser/request.go index 5fec41ce..f87e9aca 100644 --- a/server/admin/internal/modules/appuser/request.go +++ b/server/admin/internal/modules/appuser/request.go @@ -1,10 +1,12 @@ package appuser type listQuery struct { - Page int - PageSize int - Keyword string - Status string + Page int + PageSize int + Keyword string + Status string + SortBy string + SortDirection string } type loginLogQuery struct { diff --git a/server/admin/internal/modules/appuser/service.go b/server/admin/internal/modules/appuser/service.go index 8bcac220..9cced22b 100644 --- a/server/admin/internal/modules/appuser/service.go +++ b/server/admin/internal/modules/appuser/service.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "log/slog" + "sort" "strconv" "strings" "time" @@ -88,6 +89,11 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in if err != nil { return nil, 0, err } + if query.SortBy == "coin" { + // 金币余额来自 wallet 库,必须先补齐当前筛选结果的余额再排序分页,避免只按当前页局部重排。 + items, err := s.listUsersSortedByCoin(ctx, query, whereSQL, args) + return items, total, err + } rows, err := s.userDB.QueryContext(ctx, fmt.Sprintf(` SELECT u.user_id, u.current_display_user_id, @@ -128,16 +134,85 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in COALESCE((SELECT MAX(l.created_at_ms) FROM login_audit l WHERE l.app_code = u.app_code AND l.user_id = u.user_id), 0) ) %s - ORDER BY u.created_at_ms DESC, u.user_id DESC + %s LIMIT ? OFFSET ? - `, whereSQL), append(args, query.PageSize, offset(query.Page, query.PageSize))...) + `, whereSQL, appUserOrderSQL(query)), append(args, query.PageSize, offset(query.Page, query.PageSize))...) if err != nil { return nil, 0, err } defer rows.Close() - items := make([]AppUser, 0, query.PageSize) - userIDs := make([]int64, 0, query.PageSize) + items, userIDs, err := scanAppUserRows(rows, query.PageSize) + if err != nil { + return nil, 0, err + } + if err := s.fillBalances(ctx, items, userIDs); err != nil { + return nil, 0, err + } + return items, total, nil +} + +func (s *Service) listUsersSortedByCoin(ctx context.Context, query listQuery, whereSQL string, args []any) ([]AppUser, error) { + rows, err := s.userDB.QueryContext(ctx, fmt.Sprintf(` + SELECT u.user_id, + u.current_display_user_id, + COALESCE(u.username, ''), + COALESCE(u.avatar, ''), + COALESCE(u.gender, ''), + COALESCE(u.country, ''), + COALESCE((SELECT c.country_name FROM countries c WHERE c.app_code = u.app_code AND c.country_code = u.country LIMIT 1), ''), + COALESCE((SELECT c.country_display_name FROM countries c WHERE c.app_code = u.app_code AND c.country_code = u.country LIMIT 1), ''), + CASE + WHEN COALESCE(u.region_id, 0) = 0 THEN 0 + WHEN EXISTS ( + SELECT 1 FROM regions rg + WHERE rg.app_code = u.app_code + AND rg.region_id = u.region_id + AND rg.status = 'active' + AND rg.region_code NOT IN ('Australia and New Zealand', 'Caribbean', 'Melanesia', 'Micronesia', 'Polynesia', 'Southern Africa', 'UNSPECIFIED') + LIMIT 1 + ) THEN u.region_id + ELSE 0 + END, + CASE + WHEN COALESCE(u.region_id, 0) = 0 OR NOT EXISTS ( + SELECT 1 FROM regions rg + WHERE rg.app_code = u.app_code + AND rg.region_id = u.region_id + AND rg.status = 'active' + AND rg.region_code NOT IN ('Australia and New Zealand', 'Caribbean', 'Melanesia', 'Micronesia', 'Polynesia', 'Southern Africa', 'UNSPECIFIED') + LIMIT 1 + ) THEN 'GLOBAL' + ELSE COALESCE((SELECT rg.name FROM regions rg WHERE rg.app_code = u.app_code AND rg.region_id = u.region_id LIMIT 1), '') + END, + u.status, + u.created_at_ms, + u.updated_at_ms, + GREATEST( + COALESCE((SELECT MAX(s.updated_at_ms) FROM auth_sessions s WHERE s.app_code = u.app_code AND s.user_id = u.user_id), 0), + COALESCE((SELECT MAX(l.created_at_ms) FROM login_audit l WHERE l.app_code = u.app_code AND l.user_id = u.user_id), 0) + ) + %s + `, whereSQL), args...) + if err != nil { + return nil, err + } + defer rows.Close() + + items, userIDs, err := scanAppUserRows(rows, query.PageSize) + if err != nil { + return nil, err + } + if err := s.fillBalances(ctx, items, userIDs); err != nil { + return nil, err + } + sortAppUsersByCoin(items, query.SortDirection) + return paginateAppUsers(items, query.Page, query.PageSize), nil +} + +func scanAppUserRows(rows *sql.Rows, capacity int) ([]AppUser, []int64, error) { + items := make([]AppUser, 0, capacity) + userIDs := make([]int64, 0, capacity) for rows.Next() { var item AppUser var userID int64 @@ -157,19 +232,16 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in &item.UpdatedAtMs, &item.LastActiveAtMs, ); err != nil { - return nil, 0, err + return nil, nil, err } item.UserID = strconv.FormatInt(userID, 10) items = append(items, item) userIDs = append(userIDs, userID) } if err := rows.Err(); err != nil { - return nil, 0, err + return nil, nil, err } - if err := s.fillBalances(ctx, items, userIDs); err != nil { - return nil, 0, err - } - return items, total, nil + return items, userIDs, nil } func (s *Service) GetUser(ctx context.Context, userID int64) (AppUser, error) { @@ -462,44 +534,60 @@ func (s *Service) fillBalances(ctx context.Context, items []AppUser, userIDs []i if s.walletDB == nil || len(userIDs) == 0 { return nil } - placeholders := strings.TrimRight(strings.Repeat("?,", len(userIDs)), ",") - args := make([]any, 0, len(userIDs)+1) - args = append(args, appctx.FromContext(ctx)) - for _, id := range userIDs { - args = append(args, id) - } - args = append(args, "COIN") - rows, err := s.walletDB.QueryContext(ctx, fmt.Sprintf(` - SELECT user_id, asset_type, available_amount - FROM wallet_accounts - WHERE app_code = ? AND user_id IN (%s) AND asset_type = ? - `, placeholders), args...) - if err != nil { - return err - } - defer rows.Close() - index := make(map[int64]int, len(userIDs)) for i, id := range userIDs { index[id] = i } - for rows.Next() { - var userID int64 - var assetType string - var amount int64 - if err := rows.Scan(&userID, &assetType, &amount); err != nil { + appCode := appctx.FromContext(ctx) + const chunkSize = 500 + for start := 0; start < len(userIDs); start += chunkSize { + end := start + chunkSize + if end > len(userIDs) { + end = len(userIDs) + } + // 用户列表金币排序会对完整筛选集补余额,按块查询可以避免 IN 参数过长导致后台列表失败。 + chunk := userIDs[start:end] + placeholders := strings.TrimRight(strings.Repeat("?,", len(chunk)), ",") + args := make([]any, 0, len(chunk)+2) + args = append(args, appCode) + for _, id := range chunk { + args = append(args, id) + } + args = append(args, "COIN") + rows, err := s.walletDB.QueryContext(ctx, fmt.Sprintf(` + SELECT user_id, asset_type, available_amount + FROM wallet_accounts + WHERE app_code = ? AND user_id IN (%s) AND asset_type = ? + `, placeholders), args...) + if err != nil { return err } - i, ok := index[userID] - if !ok { - continue + for rows.Next() { + var userID int64 + var assetType string + var amount int64 + if err := rows.Scan(&userID, &assetType, &amount); err != nil { + _ = rows.Close() + return err + } + i, ok := index[userID] + if !ok { + continue + } + switch strings.ToUpper(assetType) { + case "COIN": + items[i].Coin = amount + } } - switch strings.ToUpper(assetType) { - case "COIN": - items[i].Coin = amount + if err := rows.Err(); err != nil { + _ = rows.Close() + return err + } + if err := rows.Close(); err != nil { + return err } } - return rows.Err() + return nil } func normalizeListQuery(query listQuery) listQuery { @@ -514,9 +602,70 @@ func normalizeListQuery(query listQuery) listQuery { } query.Keyword = strings.TrimSpace(query.Keyword) query.Status = strings.ToLower(strings.TrimSpace(query.Status)) + query.SortBy = normalizeAppUserSortBy(query.SortBy) + query.SortDirection = normalizeSortDirection(query.SortDirection) return query } +func normalizeAppUserSortBy(value string) string { + switch strings.ToLower(strings.TrimSpace(value)) { + case "coin", "coins": + return "coin" + case "created_at", "createdat", "created_at_ms", "createdatms", "created": + return "created_at" + default: + return "created_at" + } +} + +func normalizeSortDirection(value string) string { + switch strings.ToLower(strings.TrimSpace(value)) { + case "asc": + return "asc" + default: + return "desc" + } +} + +func appUserOrderSQL(query listQuery) string { + if query.SortBy == "created_at" && query.SortDirection == "asc" { + return "ORDER BY u.created_at_ms ASC, u.user_id ASC" + } + return "ORDER BY u.created_at_ms DESC, u.user_id DESC" +} + +func sortAppUsersByCoin(items []AppUser, direction string) { + sort.SliceStable(items, func(i, j int) bool { + left := items[i] + right := items[j] + if left.Coin != right.Coin { + if direction == "asc" { + return left.Coin < right.Coin + } + return left.Coin > right.Coin + } + // 金币相同的时候用内部用户 ID 做稳定排序,避免同余额用户在翻页和刷新时抖动。 + leftID, _ := strconv.ParseInt(left.UserID, 10, 64) + rightID, _ := strconv.ParseInt(right.UserID, 10, 64) + if direction == "asc" { + return leftID < rightID + } + return leftID > rightID + }) +} + +func paginateAppUsers(items []AppUser, page int, pageSize int) []AppUser { + start := offset(page, pageSize) + if start >= len(items) { + return []AppUser{} + } + end := start + pageSize + if end > len(items) { + end = len(items) + } + return items[start:end] +} + func countRows(ctx context.Context, db *sql.DB, whereSQL string, args ...any) (int64, error) { var total int64 err := db.QueryRowContext(ctx, "SELECT COUNT(*) "+whereSQL, args...).Scan(&total) diff --git a/server/admin/internal/modules/appuser/service_test.go b/server/admin/internal/modules/appuser/service_test.go new file mode 100644 index 00000000..8f68b1cc --- /dev/null +++ b/server/admin/internal/modules/appuser/service_test.go @@ -0,0 +1,45 @@ +package appuser + +import "testing" + +func TestNormalizeListQuerySort(t *testing.T) { + query := normalizeListQuery(listQuery{Page: 0, PageSize: 1000, SortBy: "coins", SortDirection: "asc"}) + if query.Page != 1 || query.PageSize != 100 || query.SortBy != "coin" || query.SortDirection != "asc" { + t.Fatalf("coin sort query mismatch: %+v", query) + } + + query = normalizeListQuery(listQuery{SortBy: "createdAtMs", SortDirection: "unknown"}) + if query.SortBy != "created_at" || query.SortDirection != "desc" { + t.Fatalf("created sort default mismatch: %+v", query) + } +} + +func TestAppUserOrderSQL(t *testing.T) { + asc := appUserOrderSQL(listQuery{SortBy: "created_at", SortDirection: "asc"}) + if asc != "ORDER BY u.created_at_ms ASC, u.user_id ASC" { + t.Fatalf("created asc order mismatch: %s", asc) + } + + desc := appUserOrderSQL(listQuery{SortBy: "created_at", SortDirection: "desc"}) + if desc != "ORDER BY u.created_at_ms DESC, u.user_id DESC" { + t.Fatalf("created desc order mismatch: %s", desc) + } +} + +func TestSortAppUsersByCoin(t *testing.T) { + items := []AppUser{ + {UserID: "1001", Coin: 10}, + {UserID: "1003", Coin: 10}, + {UserID: "1002", Coin: 80}, + } + + sortAppUsersByCoin(items, "desc") + if got := []string{items[0].UserID, items[1].UserID, items[2].UserID}; got[0] != "1002" || got[1] != "1003" || got[2] != "1001" { + t.Fatalf("coin desc order mismatch: %+v", got) + } + + sortAppUsersByCoin(items, "asc") + if got := []string{items[0].UserID, items[1].UserID, items[2].UserID}; got[0] != "1001" || got[1] != "1003" || got[2] != "1002" { + t.Fatalf("coin asc order mismatch: %+v", got) + } +} From 6de77ee02d3cc4ef0869540205d71169f0dfc46c Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 14:57:11 +0800 Subject: [PATCH 16/28] Show host policies for all trigger modes --- .../internal/transport/http/response_test.go | 6 +++--- .../http/userapi/host_center_policy_handler.go | 9 ++++----- .../internal/service/wallet/service.go | 7 ++----- .../internal/service/wallet/service_test.go | 12 ++++++++++-- .../storage/mysql/host_salary_settlement.go | 14 ++++++++++---- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index efe68243..e0cb5a10 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -3485,7 +3485,7 @@ func TestHostCenterPlatformPolicyUsesCurrentHostRegion(t *testing.T) { RegionId: 30, Status: "active", SettlementMode: "half_month", - SettlementTriggerMode: "automatic", + SettlementTriggerMode: "manual", GiftCoinToDiamondRatio: "1.0000", ResidualDiamondToUsdRate: "0.0100", EffectiveFromMs: 1700000000000, @@ -3521,7 +3521,7 @@ func TestHostCenterPlatformPolicyUsesCurrentHostRegion(t *testing.T) { if hostClient.lastHost == nil || hostClient.lastHost.GetUserId() != 42 { t.Fatalf("host profile request mismatch: %+v", hostClient.lastHost) } - if walletClient.lastHostSalaryPolicy == nil || walletClient.lastHostSalaryPolicy.GetRegionId() != 30 || walletClient.lastHostSalaryPolicy.GetSettlementTriggerMode() != "automatic" || walletClient.lastHostSalaryPolicy.GetAppCode() == "" || walletClient.lastHostSalaryPolicy.GetRequestId() == "" { + if walletClient.lastHostSalaryPolicy == nil || walletClient.lastHostSalaryPolicy.GetRegionId() != 30 || walletClient.lastHostSalaryPolicy.GetSettlementTriggerMode() != "" || walletClient.lastHostSalaryPolicy.GetAppCode() == "" || walletClient.lastHostSalaryPolicy.GetRequestId() == "" { t.Fatalf("host salary policy request mismatch: %+v", walletClient.lastHostSalaryPolicy) } if walletClient.lastHostSalaryProgress == nil || walletClient.lastHostSalaryProgress.GetHostUserId() != 42 || walletClient.lastHostSalaryProgress.GetAppCode() == "" || walletClient.lastHostSalaryProgress.GetRequestId() == "" { @@ -3537,7 +3537,7 @@ func TestHostCenterPlatformPolicyUsesCurrentHostRegion(t *testing.T) { firstLevel := levels[0].(map[string]any) progress := data["progress"].(map[string]any) levelProgress := data["level_progress"].(map[string]any) - if data["found"] != true || data["host_region_id"] != float64(30) || policy["policy_id"] != "9001" || policy["settlement_mode"] != "half_month" || firstLevel["host_salary_usd"] != 15.0 || firstLevel["agency_salary_usd"] != 3.0 { + if data["found"] != true || data["host_region_id"] != float64(30) || policy["policy_id"] != "9001" || policy["settlement_mode"] != "half_month" || policy["settlement_trigger_mode"] != "manual" || firstLevel["host_salary_usd"] != 15.0 || firstLevel["agency_salary_usd"] != 3.0 { t.Fatalf("host policy response mismatch: %+v", data) } if progress["cycle_key"] != "2026-06" || progress["total_diamonds"] != float64(1200) { diff --git a/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go b/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go index 3fa70adf..dfc24d78 100644 --- a/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/host_center_policy_handler.go @@ -68,12 +68,11 @@ func (h *Handler) getHostCenterPlatformPolicy(writer http.ResponseWriter, reques return } - // H5 不传 region 或 policy id;gateway 固定使用当前主播身份里的区域快照读取实际生效政策。 + // H5 不传 region、policy id 或 trigger;gateway 用当前主播身份区域读取 active 政策,让 automatic/manual 都能展示。 resp, err := h.walletClient.GetActiveHostSalaryPolicy(request.Context(), &walletv1.GetActiveHostSalaryPolicyRequest{ - RequestId: httpkit.RequestIDFromContext(request.Context()), - AppCode: appcode.FromContext(request.Context()), - RegionId: profile.GetRegionId(), - SettlementTriggerMode: "automatic", + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + RegionId: profile.GetRegionId(), }) if err != nil { httpkit.WriteRPCError(writer, request, err) diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index ff1727c1..32d96f64 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -256,10 +256,7 @@ func (s *Service) GetActiveHostSalaryPolicy(ctx context.Context, appCode string, return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_mode is invalid") } triggerMode = strings.TrimSpace(triggerMode) - if triggerMode == "" { - triggerMode = ledger.HostSalarySettlementTriggerAutomatic - } - if triggerMode != ledger.HostSalarySettlementTriggerAutomatic && triggerMode != ledger.HostSalarySettlementTriggerManual { + if triggerMode != "" && triggerMode != ledger.HostSalarySettlementTriggerAutomatic && triggerMode != ledger.HostSalarySettlementTriggerManual { return ledger.HostSalaryPolicy{}, false, xerr.New(xerr.InvalidArgument, "settlement_trigger_mode is invalid") } if nowMs <= 0 { @@ -267,7 +264,7 @@ func (s *Service) GetActiveHostSalaryPolicy(ctx context.Context, appCode string, } appCode = appcode.Normalize(appCode) ctx = appcode.WithContext(ctx, appCode) - // 不传 settlement_mode 时按同区域最新 active policy 返回,用于 H5 展示平台当前规则。 + // H5 展示可以不传 trigger mode,此时 automatic/manual 政策都可展示;结算任务仍会传具体 trigger 精确匹配。 return s.repository.GetActiveHostSalaryPolicy(ctx, regionID, settlementMode, triggerMode, nowMs) } diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 4bd94a25..a32cc57a 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -378,7 +378,7 @@ func TestGetActiveHostSalaryPolicyReadsRuntimePolicy(t *testing.T) { RegionID: 8801, Status: "active", SettlementMode: ledger.HostSalarySettlementModeHalfMonth, - SettlementTriggerMode: ledger.HostSalarySettlementTriggerAutomatic, + SettlementTriggerMode: ledger.HostSalarySettlementTriggerManual, GiftCoinToDiamondRatio: "1.0000", ResidualDiamondToUSDRate: "0.0100", EffectiveFromMs: nowMs - 1000, @@ -390,7 +390,7 @@ func TestGetActiveHostSalaryPolicyReadsRuntimePolicy(t *testing.T) { }) svc := walletservice.New(repository) - policy, found, err := svc.GetActiveHostSalaryPolicy(context.Background(), "lalu", 8801, "", ledger.HostSalarySettlementTriggerAutomatic, nowMs) + policy, found, err := svc.GetActiveHostSalaryPolicy(context.Background(), "lalu", 8801, "", "", nowMs) if err != nil { t.Fatalf("GetActiveHostSalaryPolicy failed: %v", err) } @@ -400,9 +400,17 @@ func TestGetActiveHostSalaryPolicyReadsRuntimePolicy(t *testing.T) { if policy.PolicyID != 901 || policy.Name != "current host policy" || policy.SettlementMode != ledger.HostSalarySettlementModeHalfMonth || policy.RegionID != 8801 { t.Fatalf("policy mismatch: %+v", policy) } + if policy.SettlementTriggerMode != ledger.HostSalarySettlementTriggerManual { + t.Fatalf("policy trigger mode mismatch: %+v", policy) + } if len(policy.Levels) != 2 || policy.Levels[1].LevelNo != 2 || policy.Levels[1].HostSalaryUSDMinor != 4500 || policy.Levels[1].AgencySalaryUSDMinor != 900 { t.Fatalf("policy levels mismatch: %+v", policy.Levels) } + if _, found, err := svc.GetActiveHostSalaryPolicy(context.Background(), "lalu", 8801, "", ledger.HostSalarySettlementTriggerAutomatic, nowMs); err != nil { + t.Fatalf("GetActiveHostSalaryPolicy with trigger failed: %v", err) + } else if found { + t.Fatal("automatic trigger query should not match manual policy") + } } // TestGetHostSalaryProgressReadsCurrentCycleDiamonds 验证 H5 等级进度读取工资周期钻石账户,查询不到时保持 0 累计。 diff --git a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go index 626ee295..2aa94320 100644 --- a/services/wallet-service/internal/storage/mysql/host_salary_settlement.go +++ b/services/wallet-service/internal/storage/mysql/host_salary_settlement.go @@ -392,12 +392,18 @@ func (r *Repository) resolveHostSalaryPolicy(ctx context.Context, tx *sql.Tx, re func (r *Repository) queryActiveHostSalaryPolicy(ctx context.Context, q hostSalaryPolicyQuerier, regionID int64, settlementMode string, triggerMode string, nowMs int64) (ledger.HostSalaryPolicy, bool, error) { modeClause := "" - args := []any{appcode.FromContext(ctx), regionID, nowMs, nowMs, triggerMode} + triggerClause := "" + args := []any{appcode.FromContext(ctx), regionID, nowMs, nowMs} if strings.TrimSpace(settlementMode) != "" { - // 结算任务必须精确匹配结算模式;H5 展示不传模式时只按区域和触发模式取最新生效政策。 + // 结算任务必须精确匹配结算模式;H5 展示不传模式时只按区域取最新生效政策。 modeClause = "AND settlement_mode = ?" args = append(args, settlementMode) } + if strings.TrimSpace(triggerMode) != "" { + // H5 展示不传 trigger 时 automatic/manual 都可展示;结算任务传 trigger 时仍精确匹配。 + triggerClause = "AND settlement_trigger_mode = ?" + args = append(args, triggerMode) + } query := fmt.Sprintf(` SELECT policy_id, name, region_id, status, settlement_mode, settlement_trigger_mode, CAST(gift_coin_to_diamond_ratio AS CHAR), @@ -409,10 +415,10 @@ func (r *Repository) queryActiveHostSalaryPolicy(ctx context.Context, q hostSala AND status = 'active' AND effective_from_ms <= ? AND (effective_to_ms = 0 OR effective_to_ms > ?) - AND settlement_trigger_mode = ? + %s %s ORDER BY effective_from_ms DESC, policy_id DESC - LIMIT 1`, modeClause) + LIMIT 1`, triggerClause, modeClause) var policy ledger.HostSalaryPolicy err := q.QueryRowContext(ctx, query, args...).Scan(&policy.PolicyID, &policy.Name, &policy.RegionID, &policy.Status, &policy.SettlementMode, &policy.SettlementTriggerMode, &policy.GiftCoinToDiamondRatio, &policy.ResidualDiamondToUSDRate, &policy.EffectiveFromMs, &policy.EffectiveToMs) if err != nil { From 427d335e4aef7f1a6f41bb54b117516c10ab72eb Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 14:58:40 +0800 Subject: [PATCH 17/28] Update wallet resources and admin host flows --- api/proto/wallet/v1/wallet.pb.go | 149 ++++++++++-------- api/proto/wallet/v1/wallet.proto | 10 ++ .../internal/integration/userclient/client.go | 34 ++-- server/admin/internal/modules/auth/handler.go | 63 +++++--- .../internal/modules/auth/handler_test.go | 95 +++++++++++ .../admin/internal/modules/hostorg/handler.go | 10 +- .../admin/internal/modules/hostorg/reader.go | 58 ++++++- .../admin/internal/modules/hostorg/request.go | 2 + .../admin/internal/modules/hostorg/service.go | 10 ++ server/admin/internal/modules/resource/dto.go | 4 - .../internal/modules/resource/handler.go | 25 ++- .../internal/modules/resource/request.go | 8 +- .../internal/modules/roomtreasure/service.go | 8 +- .../modules/userleaderboard/service.go | 18 +-- .../activityapi/user_leaderboard_handler.go | 18 +-- .../deploy/mysql/initdb/001_room_service.sql | 2 +- .../internal/room/command/command.go | 2 +- .../internal/room/service/gift.go | 2 - .../internal/room/service/room_treasure.go | 19 +-- .../internal/storage/mysql/repository.go | 2 +- .../mysql/initdb/001_wallet_service.sql | 8 +- .../internal/domain/ledger/ledger.go | 35 ++-- .../internal/domain/resource/resource.go | 97 ++++++------ .../internal/service/wallet/service_test.go | 54 +++---- .../internal/storage/mysql/repository.go | 148 ++++------------- .../storage/mysql/resource_repository.go | 25 ++- .../internal/transport/grpc/resource.go | 13 +- 27 files changed, 537 insertions(+), 382 deletions(-) create mode 100644 server/admin/internal/modules/auth/handler_test.go diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index 1171ab46..31cefea3 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -174,9 +174,10 @@ type DebitGiftResponse struct { BillingReceiptId string `protobuf:"bytes,1,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` CoinSpent int64 `protobuf:"varint,3,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - GiftPointAdded int64 `protobuf:"varint,4,opt,name=gift_point_added,json=giftPointAdded,proto3" json:"gift_point_added,omitempty"` - HeatValue int64 `protobuf:"varint,5,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` - PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + // gift_point_added 是历史回执字段;GIFT_POINT 已下线,新送礼固定返回 0。 + GiftPointAdded int64 `protobuf:"varint,4,opt,name=gift_point_added,json=giftPointAdded,proto3" json:"gift_point_added,omitempty"` + HeatValue int64 `protobuf:"varint,5,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` + PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` // balance_after 是 sender 被扣费资产 available_amount 账后余额。 BalanceAfter int64 `protobuf:"varint,7,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` ChargeAssetType string `protobuf:"bytes,8,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` @@ -2574,9 +2575,10 @@ type Resource struct { ManagerGrantEnabled bool `protobuf:"varint,21,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3" json:"manager_grant_enabled,omitempty"` PriceType string `protobuf:"bytes,22,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` CoinPrice int64 `protobuf:"varint,23,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,24,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;资源和礼物价格现在只维护真实 COIN 价格,新写入固定为 0。 + GiftPointAmount int64 `protobuf:"varint,24,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *Resource) Reset() { @@ -3053,20 +3055,21 @@ type GiftConfig struct { PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` - CreatedByUserId int64 `protobuf:"varint,13,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,14,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,16,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - RegionIds []int64 `protobuf:"varint,17,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - GiftTypeCode string `protobuf:"bytes,18,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - ChargeAssetType string `protobuf:"bytes,19,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,20,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - EffectiveToMs int64 `protobuf:"varint,21,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` - EffectTypes []string `protobuf:"bytes,22,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;送礼结算不再读取该值,新写入固定为 0。 + GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` + CreatedByUserId int64 `protobuf:"varint,13,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,14,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,16,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + RegionIds []int64 `protobuf:"varint,17,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + GiftTypeCode string `protobuf:"bytes,18,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + ChargeAssetType string `protobuf:"bytes,19,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,20,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,21,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + EffectTypes []string `protobuf:"bytes,22,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GiftConfig) Reset() { @@ -4307,9 +4310,10 @@ type CreateResourceRequest struct { ManagerGrantEnabled *bool `protobuf:"varint,18,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` PriceType string `protobuf:"bytes,19,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` CoinPrice int64 `protobuf:"varint,20,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,21,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 + GiftPointAmount int64 `protobuf:"varint,21,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateResourceRequest) Reset() { @@ -4512,9 +4516,10 @@ type UpdateResourceRequest struct { ManagerGrantEnabled *bool `protobuf:"varint,19,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` PriceType string `protobuf:"bytes,20,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` CoinPrice int64 `protobuf:"varint,21,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,22,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 + GiftPointAmount int64 `protobuf:"varint,22,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateResourceRequest) Reset() { @@ -5424,6 +5429,7 @@ type ListGiftConfigsRequest struct { ActiveOnly bool `protobuf:"varint,7,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` FilterRegion bool `protobuf:"varint,9,opt,name=filter_region,json=filterRegion,proto3" json:"filter_region,omitempty"` + GiftTypeCode string `protobuf:"bytes,10,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -5521,6 +5527,13 @@ func (x *ListGiftConfigsRequest) GetFilterRegion() bool { return false } +func (x *ListGiftConfigsRequest) GetGiftTypeCode() string { + if x != nil { + return x.GiftTypeCode + } + return "" +} + type ListGiftConfigsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` @@ -5841,18 +5854,19 @@ type CreateGiftConfigRequest struct { PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` - EffectiveAtMs int64 `protobuf:"varint,13,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` - OperatorUserId int64 `protobuf:"varint,14,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - RegionIds []int64 `protobuf:"varint,15,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - GiftTypeCode string `protobuf:"bytes,16,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - ChargeAssetType string `protobuf:"bytes,17,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` - EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 + GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` + EffectiveAtMs int64 `protobuf:"varint,13,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` + OperatorUserId int64 `protobuf:"varint,14,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + RegionIds []int64 `protobuf:"varint,15,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + GiftTypeCode string `protobuf:"bytes,16,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + ChargeAssetType string `protobuf:"bytes,17,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateGiftConfigRequest) Reset() { @@ -6037,18 +6051,19 @@ type UpdateGiftConfigRequest struct { PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` - EffectiveAtMs int64 `protobuf:"varint,13,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` - OperatorUserId int64 `protobuf:"varint,14,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - RegionIds []int64 `protobuf:"varint,15,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - GiftTypeCode string `protobuf:"bytes,16,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - ChargeAssetType string `protobuf:"bytes,17,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` - EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 + GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` + HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` + EffectiveAtMs int64 `protobuf:"varint,13,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` + OperatorUserId int64 `protobuf:"varint,14,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + RegionIds []int64 `protobuf:"varint,15,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + GiftTypeCode string `protobuf:"bytes,16,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + ChargeAssetType string `protobuf:"bytes,17,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *UpdateGiftConfigRequest) Reset() { @@ -8589,15 +8604,16 @@ type GiftWallItem struct { TotalValue int64 `protobuf:"varint,9,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` TotalCoinValue int64 `protobuf:"varint,10,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` TotalDiamondValue int64 `protobuf:"varint,11,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` - TotalGiftPoint int64 `protobuf:"varint,12,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` - TotalHeatValue int64 `protobuf:"varint,13,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` - ChargeAssetType string `protobuf:"bytes,14,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` - LastPriceVersion string `protobuf:"bytes,15,opt,name=last_price_version,json=lastPriceVersion,proto3" json:"last_price_version,omitempty"` - FirstReceivedAtMs int64 `protobuf:"varint,16,opt,name=first_received_at_ms,json=firstReceivedAtMs,proto3" json:"first_received_at_ms,omitempty"` - LastReceivedAtMs int64 `protobuf:"varint,17,opt,name=last_received_at_ms,json=lastReceivedAtMs,proto3" json:"last_received_at_ms,omitempty"` - SortOrder int32 `protobuf:"varint,18,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // total_gift_point 是历史礼物墙字段;新送礼不再累加。 + TotalGiftPoint int64 `protobuf:"varint,12,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` + TotalHeatValue int64 `protobuf:"varint,13,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` + ChargeAssetType string `protobuf:"bytes,14,opt,name=charge_asset_type,json=chargeAssetType,proto3" json:"charge_asset_type,omitempty"` + LastPriceVersion string `protobuf:"bytes,15,opt,name=last_price_version,json=lastPriceVersion,proto3" json:"last_price_version,omitempty"` + FirstReceivedAtMs int64 `protobuf:"varint,16,opt,name=first_received_at_ms,json=firstReceivedAtMs,proto3" json:"first_received_at_ms,omitempty"` + LastReceivedAtMs int64 `protobuf:"varint,17,opt,name=last_received_at_ms,json=lastReceivedAtMs,proto3" json:"last_received_at_ms,omitempty"` + SortOrder int32 `protobuf:"varint,18,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GiftWallItem) Reset() { @@ -8824,10 +8840,11 @@ type GetUserGiftWallResponse struct { TotalValue int64 `protobuf:"varint,4,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` TotalCoinValue int64 `protobuf:"varint,5,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` TotalDiamondValue int64 `protobuf:"varint,6,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` - TotalGiftPoint int64 `protobuf:"varint,7,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` - TotalHeatValue int64 `protobuf:"varint,8,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // total_gift_point 是历史礼物墙汇总字段;新送礼不再累加。 + TotalGiftPoint int64 `protobuf:"varint,7,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` + TotalHeatValue int64 `protobuf:"varint,8,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *GetUserGiftWallResponse) Reset() { @@ -14606,7 +14623,7 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x06status\x18\x04 \x01(\tR\x06status\x12(\n" + "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"M\n" + "\x15ResourceGroupResponse\x124\n" + - "\x05group\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\"\x98\x02\n" + + "\x05group\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\"\xbe\x02\n" + "\x16ListGiftConfigsRequest\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + @@ -14618,7 +14635,9 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\vactive_only\x18\a \x01(\bR\n" + "activeOnly\x12\x1b\n" + "\tregion_id\x18\b \x01(\x03R\bregionId\x12#\n" + - "\rfilter_region\x18\t \x01(\bR\ffilterRegion\"b\n" + + "\rfilter_region\x18\t \x01(\bR\ffilterRegion\x12$\n" + + "\x0egift_type_code\x18\n" + + " \x01(\tR\fgiftTypeCode\"b\n" + "\x17ListGiftConfigsResponse\x121\n" + "\x05gifts\x18\x01 \x03(\v2\x1b.hyapp.wallet.v1.GiftConfigR\x05gifts\x12\x14\n" + "\x05total\x18\x02 \x01(\x03R\x05total\"\x8f\x01\n" + diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 7bad52ac..4daa67e5 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -32,6 +32,7 @@ message DebitGiftResponse { string billing_receipt_id = 1; string transaction_id = 2; int64 coin_spent = 3; + // gift_point_added 是历史回执字段;GIFT_POINT 已下线,新送礼固定返回 0。 int64 gift_point_added = 4; int64 heat_value = 5; string price_version = 6; @@ -325,6 +326,7 @@ message Resource { bool manager_grant_enabled = 21; string price_type = 22; int64 coin_price = 23; + // gift_point_amount 是历史字段;资源和礼物价格现在只维护真实 COIN 价格,新写入固定为 0。 int64 gift_point_amount = 24; } @@ -369,6 +371,7 @@ message GiftConfig { string presentation_json = 8; string price_version = 9; int64 coin_price = 10; + // gift_point_amount 是历史字段;送礼结算不再读取该值,新写入固定为 0。 int64 gift_point_amount = 11; int64 heat_value = 12; int64 created_by_user_id = 13; @@ -518,6 +521,7 @@ message CreateResourceRequest { optional bool manager_grant_enabled = 18; string price_type = 19; int64 coin_price = 20; + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 int64 gift_point_amount = 21; } @@ -543,6 +547,7 @@ message UpdateResourceRequest { optional bool manager_grant_enabled = 19; string price_type = 20; int64 coin_price = 21; + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 int64 gift_point_amount = 22; } @@ -630,6 +635,7 @@ message ListGiftConfigsRequest { bool active_only = 7; int64 region_id = 8; bool filter_region = 9; + string gift_type_code = 10; } message ListGiftConfigsResponse { @@ -674,6 +680,7 @@ message CreateGiftConfigRequest { string presentation_json = 8; string price_version = 9; int64 coin_price = 10; + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 int64 gift_point_amount = 11; int64 heat_value = 12; int64 effective_at_ms = 13; @@ -697,6 +704,7 @@ message UpdateGiftConfigRequest { string presentation_json = 8; string price_version = 9; int64 coin_price = 10; + // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 int64 gift_point_amount = 11; int64 heat_value = 12; int64 effective_at_ms = 13; @@ -967,6 +975,7 @@ message GiftWallItem { int64 total_value = 9; int64 total_coin_value = 10; int64 total_diamond_value = 11; + // total_gift_point 是历史礼物墙字段;新送礼不再累加。 int64 total_gift_point = 12; int64 total_heat_value = 13; string charge_asset_type = 14; @@ -989,6 +998,7 @@ message GetUserGiftWallResponse { int64 total_value = 4; int64 total_coin_value = 5; int64 total_diamond_value = 6; + // total_gift_point 是历史礼物墙汇总字段;新送礼不再累加。 int64 total_gift_point = 7; int64 total_heat_value = 8; } diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 42c8d105..7c348822 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -386,21 +386,25 @@ type Agency struct { } type HostProfile struct { - UserID int64 `json:"userId,string"` - Status string `json:"status"` - RegionID int64 `json:"regionId"` - CurrentAgencyID int64 `json:"currentAgencyId"` - CurrentMembershipID int64 `json:"currentMembershipId"` - Source string `json:"source"` - FirstBecameHostAtMs int64 `json:"firstBecameHostAtMs"` - CreatedAtMs int64 `json:"createdAtMs"` - UpdatedAtMs int64 `json:"updatedAtMs"` - DisplayUserID string `json:"displayUserId"` - Username string `json:"username"` - Avatar string `json:"avatar"` - RegionName string `json:"regionName"` - CurrentAgencyName string `json:"currentAgencyName"` - Diamond int64 `json:"diamond"` + UserID int64 `json:"userId,string"` + Status string `json:"status"` + RegionID int64 `json:"regionId"` + CurrentAgencyID int64 `json:"currentAgencyId"` + CurrentMembershipID int64 `json:"currentMembershipId"` + Source string `json:"source"` + FirstBecameHostAtMs int64 `json:"firstBecameHostAtMs"` + CreatedAtMs int64 `json:"createdAtMs"` + UpdatedAtMs int64 `json:"updatedAtMs"` + DisplayUserID string `json:"displayUserId"` + Username string `json:"username"` + Avatar string `json:"avatar"` + RegionName string `json:"regionName"` + CurrentAgencyName string `json:"currentAgencyName"` + Diamond int64 `json:"diamond"` + CurrentAgencyOwnerUserID int64 `json:"currentAgencyOwnerUserId,string"` + CurrentAgencyOwnerDisplayUserID string `json:"currentAgencyOwnerDisplayUserId"` + CurrentAgencyOwnerUsername string `json:"currentAgencyOwnerUsername"` + CurrentAgencyOwnerAvatar string `json:"currentAgencyOwnerAvatar"` } type CoinSellerProfile struct { diff --git a/server/admin/internal/modules/auth/handler.go b/server/admin/internal/modules/auth/handler.go index b4657c31..d66a45d7 100644 --- a/server/admin/internal/modules/auth/handler.go +++ b/server/admin/internal/modules/auth/handler.go @@ -12,7 +12,11 @@ import ( authcore "hyapp-admin-server/internal/service" ) -const refreshCookieName = "hyapp_admin_refresh" +const ( + refreshCookieName = "hyapp_admin_refresh" + refreshCookiePath = "/" + legacyRefreshCookiePath = "/api/v1/auth" +) type Handler struct { service *AuthFlowService @@ -52,7 +56,7 @@ func (h *Handler) Login(c *gin.Context) { } func (h *Handler) Logout(c *gin.Context) { - if token, err := c.Cookie(refreshCookieName); err == nil && token != "" { + for _, token := range refreshCookieCandidates(c) { _ = h.service.Logout(token) } h.setRefreshCookie(c, "", -1) @@ -60,28 +64,32 @@ func (h *Handler) Logout(c *gin.Context) { } func (h *Handler) Refresh(c *gin.Context) { - token, err := c.Cookie(refreshCookieName) - if err != nil || token == "" { + tokens := refreshCookieCandidates(c) + if len(tokens) == 0 { response.Unauthorized(c, "刷新会话不存在") return } - result, err := h.service.Refresh(token, LoginInput{ - IP: c.ClientIP(), - UserAgent: c.Request.UserAgent(), - }) - if err != nil { - response.Unauthorized(c, "刷新会话已失效") - return + var result LoginResult + var err error + for _, token := range tokens { + result, err = h.service.Refresh(token, LoginInput{ + IP: c.ClientIP(), + UserAgent: c.Request.UserAgent(), + }) + if err == nil { + h.setRefreshCookie(c, result.RefreshToken, int(h.cfg.RefreshTokenTTL.Seconds())) + response.OK(c, gin.H{ + "accessToken": result.AccessToken, + "expiresAtMs": result.ExpiresAtMS, + "user": shared.UserDTO(result.User), + "permissions": result.Permissions, + }) + return + } } - h.setRefreshCookie(c, result.RefreshToken, int(h.cfg.RefreshTokenTTL.Seconds())) - response.OK(c, gin.H{ - "accessToken": result.AccessToken, - "expiresAtMs": result.ExpiresAtMS, - "user": shared.UserDTO(result.User), - "permissions": result.Permissions, - }) + response.Unauthorized(c, "刷新会话已失效") } func (h *Handler) Me(c *gin.Context) { @@ -114,7 +122,24 @@ func (h *Handler) ChangePassword(c *gin.Context) { func (h *Handler) setRefreshCookie(c *gin.Context, token string, maxAge int) { c.SetSameSite(refreshCookieSameSite(h.cfg.RefreshCookieSameSite)) - c.SetCookie(refreshCookieName, token, maxAge, "/api/v1/auth", "", h.cfg.RefreshCookieSecure, true) + c.SetCookie(refreshCookieName, token, maxAge, refreshCookiePath, "", h.cfg.RefreshCookieSecure, true) + c.SetCookie(refreshCookieName, "", -1, legacyRefreshCookiePath, "", h.cfg.RefreshCookieSecure, true) +} + +func refreshCookieCandidates(c *gin.Context) []string { + values := make([]string, 0, 2) + seen := map[string]struct{}{} + for _, cookie := range c.Request.Cookies() { + if cookie.Name != refreshCookieName || cookie.Value == "" { + continue + } + if _, ok := seen[cookie.Value]; ok { + continue + } + seen[cookie.Value] = struct{}{} + values = append(values, cookie.Value) + } + return values } func refreshCookieSameSite(value string) http.SameSite { diff --git a/server/admin/internal/modules/auth/handler_test.go b/server/admin/internal/modules/auth/handler_test.go new file mode 100644 index 00000000..27da8da1 --- /dev/null +++ b/server/admin/internal/modules/auth/handler_test.go @@ -0,0 +1,95 @@ +package auth + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + "time" + + "github.com/gin-gonic/gin" + "hyapp-admin-server/internal/config" + authcore "hyapp-admin-server/internal/service" +) + +func TestRefreshUsesRootCookieAndClearsLegacyCookiePath(t *testing.T) { + gin.SetMode(gin.TestMode) + store := newFakeAuthStore(t) + handler := testAuthHandler(store) + login, err := handler.service.Login(LoginInput{Username: "admin", Password: "secret", IP: "127.0.0.1", UserAgent: "browser"}) + if err != nil { + t.Fatalf("login: %v", err) + } + router := gin.New() + router.POST("/api/v1/auth/refresh", handler.Refresh) + + req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/refresh", nil) + req.AddCookie(&http.Cookie{Name: refreshCookieName, Value: login.RefreshToken}) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("refresh status = %d body=%s", rec.Code, rec.Body.String()) + } + setCookies := rec.Result().Cookies() + if !hasCookieWithPath(setCookies, refreshCookieName, refreshCookiePath) { + t.Fatalf("refresh must set root refresh cookie: %+v", setCookies) + } + if !hasExpiredCookieWithPath(setCookies, refreshCookieName, legacyRefreshCookiePath) { + t.Fatalf("refresh must clear legacy path cookie: %+v", setCookies) + } +} + +func TestRefreshTriesDuplicateRefreshCookiesUntilOneWorks(t *testing.T) { + gin.SetMode(gin.TestMode) + store := newFakeAuthStore(t) + handler := testAuthHandler(store) + first, err := handler.service.Login(LoginInput{Username: "admin", Password: "secret", IP: "127.0.0.1", UserAgent: "browser"}) + if err != nil { + t.Fatalf("login: %v", err) + } + refreshed, err := handler.service.Refresh(first.RefreshToken, LoginInput{IP: "127.0.0.1", UserAgent: "browser"}) + if err != nil { + t.Fatalf("prime refresh: %v", err) + } + router := gin.New() + router.POST("/api/v1/auth/refresh", handler.Refresh) + + req := httptest.NewRequest(http.MethodPost, "/api/v1/auth/refresh", nil) + req.Header.Set("Cookie", refreshCookieName+"="+first.RefreshToken+"; "+refreshCookieName+"="+refreshed.RefreshToken) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("refresh status = %d body=%s", rec.Code, rec.Body.String()) + } + if strings.Contains(rec.Body.String(), "刷新会话已失效") { + t.Fatalf("refresh should skip stale duplicate cookie: %s", rec.Body.String()) + } +} + +func testAuthHandler(store *fakeAuthStore) *Handler { + cfg := config.Config{RefreshTokenTTL: 7 * 24 * time.Hour, RefreshCookieSameSite: "lax"} + return &Handler{ + service: NewService(store, authcore.NewAuthService("test-secret", time.Hour), cfg), + cfg: cfg, + } +} + +func hasCookieWithPath(cookies []*http.Cookie, name string, path string) bool { + for _, cookie := range cookies { + if cookie.Name == name && cookie.Path == path && cookie.MaxAge >= 0 && cookie.Value != "" { + return true + } + } + return false +} + +func hasExpiredCookieWithPath(cookies []*http.Cookie, name string, path string) bool { + for _, cookie := range cookies { + if cookie.Name == name && cookie.Path == path && cookie.MaxAge < 0 { + return true + } + } + return false +} diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index bd336947..1558403d 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -318,10 +318,12 @@ func parseInt64ID(c *gin.Context, name string) (int64, bool) { func parseListQuery(c *gin.Context) (listQuery, bool) { options := shared.ListOptions(c) query := listQuery{ - Page: options.Page, - PageSize: options.PageSize, - Keyword: options.Keyword, - Status: options.Status, + Page: options.Page, + PageSize: options.PageSize, + Keyword: options.Keyword, + Status: options.Status, + SortBy: firstNonBlank(c.Query("sortBy"), c.Query("sort_by")), + SortDirection: firstNonBlank(c.Query("sortDirection"), c.Query("sort_direction"), c.Query("order")), } var ok bool if query.RegionID, ok = parseOptionalInt64Query(c, "regionId", "region_id"); !ok { diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index 46cccc47..b164fc0f 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "fmt" + "sort" "strings" "time" @@ -341,6 +342,7 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user FROM host_profiles hp LEFT JOIN users u ON u.app_code = hp.app_code AND u.user_id = hp.user_id LEFT JOIN agencies a ON a.app_code = hp.app_code AND a.agency_id = hp.current_agency_id + LEFT JOIN users agency_owner ON agency_owner.app_code = a.app_code AND agency_owner.user_id = a.owner_user_id LEFT JOIN regions r ON r.app_code = hp.app_code AND r.region_id = hp.region_id WHERE hp.app_code = ?` args := []any{appCode} @@ -358,24 +360,32 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user } if keyword := strings.TrimSpace(query.Keyword); keyword != "" { like := "%" + keyword + "%" - whereSQL += " AND (CAST(hp.user_id AS CHAR) LIKE ? OR u.current_display_user_id LIKE ? OR u.username LIKE ? OR a.name LIKE ? OR r.name LIKE ?)" - args = append(args, like, like, like, like, like) + whereSQL += " AND (CAST(hp.user_id AS CHAR) LIKE ? OR u.current_display_user_id LIKE ? OR u.username LIKE ? OR a.name LIKE ? OR agency_owner.current_display_user_id LIKE ? OR agency_owner.username LIKE ? OR r.name LIKE ?)" + args = append(args, like, like, like, like, like, like, like) } total, err := countRows(ctx, r.db, whereSQL, args...) if err != nil { return nil, 0, err } + limitSQL := "LIMIT ? OFFSET ?" + queryArgs := append(args, query.PageSize, offset(query.Page, query.PageSize)) + if query.SortBy == "diamond" { + limitSQL = "" + queryArgs = args + } rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` SELECT hp.user_id, hp.status, hp.region_id, COALESCE(hp.current_agency_id, 0), COALESCE(hp.current_membership_id, 0), hp.source, hp.first_became_host_at_ms, hp.created_at_ms, hp.updated_at_ms, COALESCE(u.current_display_user_id, ''), COALESCE(u.username, ''), - COALESCE(u.avatar, ''), COALESCE(r.name, ''), COALESCE(a.name, '') + COALESCE(u.avatar, ''), COALESCE(r.name, ''), COALESCE(a.name, ''), + COALESCE(a.owner_user_id, 0), COALESCE(agency_owner.current_display_user_id, ''), + COALESCE(agency_owner.username, ''), COALESCE(agency_owner.avatar, '') %s ORDER BY hp.created_at_ms DESC, hp.user_id DESC - LIMIT ? OFFSET ? - `, whereSQL), append(args, query.PageSize, offset(query.Page, query.PageSize))...) + %s + `, whereSQL, limitSQL), queryArgs...) if err != nil { return nil, 0, err } @@ -400,6 +410,10 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user &item.Avatar, &item.RegionName, &item.CurrentAgencyName, + &item.CurrentAgencyOwnerUserID, + &item.CurrentAgencyOwnerDisplayUserID, + &item.CurrentAgencyOwnerUsername, + &item.CurrentAgencyOwnerAvatar, ); err != nil { return nil, 0, err } @@ -416,6 +430,10 @@ func (r *Reader) ListHostProfiles(ctx context.Context, query listQuery) ([]*user for _, item := range items { item.Diamond = diamonds[item.UserID] } + if query.SortBy == "diamond" { + sortHostProfilesByDiamond(items, query.SortDirection) + items = paginateHostProfiles(items, query.Page, query.PageSize) + } return items, total, nil } @@ -718,6 +736,36 @@ func (r *Reader) hostPeriodDiamonds(ctx context.Context, appCode string, userIDs return result, rows.Err() } +func sortHostProfilesByDiamond(items []*userclient.HostProfile, direction string) { + sort.SliceStable(items, func(i, j int) bool { + if items[i].Diamond == items[j].Diamond { + return false + } + if direction == "asc" { + return items[i].Diamond < items[j].Diamond + } + return items[i].Diamond > items[j].Diamond + }) +} + +func paginateHostProfiles(items []*userclient.HostProfile, page int, pageSize int) []*userclient.HostProfile { + if page < 1 { + page = 1 + } + if pageSize < 1 { + pageSize = 20 + } + start := (page - 1) * pageSize + if start >= len(items) { + return []*userclient.HostProfile{} + } + end := start + pageSize + if end > len(items) { + end = len(items) + } + return items[start:end] +} + func sqlPlaceholders(count int) string { if count <= 0 { return "" diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index aa6b2ad9..b142b65c 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -9,6 +9,8 @@ type listQuery struct { AgencyID int64 ParentBDUserID int64 ParentLeaderUserID int64 + SortBy string + SortDirection string } type createBDLeaderRequest struct { diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index adeea825..10dbab77 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -472,6 +472,16 @@ func normalizeListQuery(query listQuery) listQuery { } query.Keyword = strings.TrimSpace(query.Keyword) query.Status = strings.ToLower(strings.TrimSpace(query.Status)) + query.SortBy = strings.ToLower(strings.TrimSpace(query.SortBy)) + if query.SortBy != "diamond" { + query.SortBy = "" + query.SortDirection = "" + return query + } + query.SortDirection = strings.ToLower(strings.TrimSpace(query.SortDirection)) + if query.SortDirection != "asc" { + query.SortDirection = "desc" + } return query } diff --git a/server/admin/internal/modules/resource/dto.go b/server/admin/internal/modules/resource/dto.go index f232ebd6..be9e9e36 100644 --- a/server/admin/internal/modules/resource/dto.go +++ b/server/admin/internal/modules/resource/dto.go @@ -16,7 +16,6 @@ type resourceDTO struct { WalletAssetAmount int64 `json:"walletAssetAmount"` PriceType string `json:"priceType"` CoinPrice int64 `json:"coinPrice"` - GiftPointAmount int64 `json:"giftPointAmount"` BadgeForm string `json:"badgeForm,omitempty"` BadgeKind string `json:"badgeKind,omitempty"` LevelTrack string `json:"levelTrack,omitempty"` @@ -74,7 +73,6 @@ type giftDTO struct { GiftTypeCode string `json:"giftTypeCode"` ChargeAssetType string `json:"chargeAssetType"` CoinPrice int64 `json:"coinPrice"` - GiftPointAmount int64 `json:"giftPointAmount"` EffectiveFromMS int64 `json:"effectiveFromMs"` EffectiveToMS int64 `json:"effectiveToMs"` EffectTypes []string `json:"effectTypes"` @@ -197,7 +195,6 @@ func resourceFromProto(item *walletv1.Resource) resourceDTO { WalletAssetAmount: item.GetWalletAssetAmount(), PriceType: item.GetPriceType(), CoinPrice: item.GetCoinPrice(), - GiftPointAmount: item.GetGiftPointAmount(), BadgeForm: badgeFormForResource(item.GetResourceType(), item.GetMetadataJson()), BadgeKind: badgeKindForResource(item.GetResourceType(), item.GetMetadataJson()), LevelTrack: badgeLevelTrackForResource(item.GetResourceType(), item.GetMetadataJson()), @@ -298,7 +295,6 @@ func giftFromProto(gift *walletv1.GiftConfig) giftDTO { GiftTypeCode: gift.GetGiftTypeCode(), ChargeAssetType: gift.GetChargeAssetType(), CoinPrice: gift.GetCoinPrice(), - GiftPointAmount: gift.GetGiftPointAmount(), EffectiveFromMS: gift.GetEffectiveFromMs(), EffectiveToMS: gift.GetEffectiveToMs(), EffectTypes: gift.GetEffectTypes(), diff --git a/server/admin/internal/modules/resource/handler.go b/server/admin/internal/modules/resource/handler.go index 9f4932d4..dc2a9cf1 100644 --- a/server/admin/internal/modules/resource/handler.go +++ b/server/admin/internal/modules/resource/handler.go @@ -294,14 +294,15 @@ func (h *Handler) ListGifts(c *gin.Context) { return } resp, err := h.wallet.ListGiftConfigs(c.Request.Context(), &walletv1.ListGiftConfigsRequest{ - RequestId: middleware.CurrentRequestID(c), - AppCode: appctx.FromContext(c.Request.Context()), - Status: options.Status, - Keyword: options.Keyword, - Page: int32(options.Page), - PageSize: int32(options.PageSize), - RegionId: regionID, - FilterRegion: filterRegion, + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + Status: options.Status, + Keyword: options.Keyword, + Page: int32(options.Page), + PageSize: int32(options.PageSize), + RegionId: regionID, + FilterRegion: filterRegion, + GiftTypeCode: giftTypeCodeQuery(c), }) if err != nil { response.ServerError(c, "获取礼物列表失败") @@ -719,6 +720,14 @@ func optionalInt64Query(c *gin.Context, primary string, fallback string) (int64, return value, ok } +func giftTypeCodeQuery(c *gin.Context) string { + value := strings.TrimSpace(c.Query("giftTypeCode")) + if value == "" { + value = strings.TrimSpace(c.Query("gift_type_code")) + } + return value +} + func optionalInt64QueryWithPresence(c *gin.Context, primary string, fallback string) (int64, bool, bool) { raw := strings.TrimSpace(c.Query(primary)) if raw == "" { diff --git a/server/admin/internal/modules/resource/request.go b/server/admin/internal/modules/resource/request.go index ec2c2008..86ae1f8d 100644 --- a/server/admin/internal/modules/resource/request.go +++ b/server/admin/internal/modules/resource/request.go @@ -53,7 +53,6 @@ type resourceRequest struct { Amount int64 `json:"amount"` PriceType string `json:"priceType"` CoinPrice int64 `json:"coinPrice"` - GiftPointAmount int64 `json:"giftPointAmount"` BadgeForm string `json:"badgeForm"` BadgeKind string `json:"badgeKind"` LevelTrack string `json:"levelTrack"` @@ -134,7 +133,6 @@ type giftRequest struct { GiftTypeCode string `json:"giftTypeCode"` ChargeAssetType string `json:"chargeAssetType"` CoinPrice int64 `json:"coinPrice"` - GiftPointAmount int64 `json:"giftPointAmount"` HeatValue int64 `json:"heatValue"` // 兼容旧后台请求;新后台不再展示或提交热度。 EffectiveAtMS int64 `json:"effectiveAtMs"` EffectiveFromMS int64 `json:"effectiveFromMs"` @@ -370,7 +368,7 @@ func (r giftRequest) createProto(c *gin.Context) *walletv1.CreateGiftConfigReque GiftTypeCode: strings.TrimSpace(r.GiftTypeCode), ChargeAssetType: strings.TrimSpace(r.ChargeAssetType), CoinPrice: r.CoinPrice, - GiftPointAmount: r.GiftPointAmount, + GiftPointAmount: 0, HeatValue: r.CoinPrice, EffectiveAtMs: r.EffectiveAtMS, EffectiveFromMs: r.EffectiveFromMS, @@ -395,7 +393,7 @@ func (r giftRequest) updateProto(c *gin.Context, giftID string) *walletv1.Update GiftTypeCode: strings.TrimSpace(r.GiftTypeCode), ChargeAssetType: strings.TrimSpace(r.ChargeAssetType), CoinPrice: r.CoinPrice, - GiftPointAmount: r.GiftPointAmount, + GiftPointAmount: 0, HeatValue: r.CoinPrice, EffectiveAtMs: r.EffectiveAtMS, EffectiveFromMs: r.EffectiveFromMS, @@ -502,7 +500,7 @@ func resourcePricing(priceType string, coinPrice int64) (string, int64, int64) { if priceType == resourcePriceTypeFree { return resourcePriceTypeFree, 0, 0 } - return resourcePriceTypeCoin, coinPrice, coinPrice + return resourcePriceTypeCoin, coinPrice, 0 } func validateResourcePricing(req resourceRequest) error { diff --git a/server/admin/internal/modules/roomtreasure/service.go b/server/admin/internal/modules/roomtreasure/service.go index 81fb395c..93516f7e 100644 --- a/server/admin/internal/modules/roomtreasure/service.go +++ b/server/admin/internal/modules/roomtreasure/service.go @@ -13,7 +13,7 @@ import ( const ( roomTreasureLevelCount = 7 - defaultEnergySource = "gift_point_added" + defaultEnergySource = "heat_value" defaultOpenDelayMS = int64(30_000) defaultBroadcastScope = "region" defaultRewardStackPolicy = "allow_stack" @@ -161,7 +161,11 @@ func normalizeConfig(config RoomTreasureConfig) (RoomTreasureConfig, error) { return RoomTreasureConfig{}, fmt.Errorf("%w: 配置版本不能小于 0", ErrInvalidArgument) } config.EnergySource = defaultString(strings.TrimSpace(config.EnergySource), defaultEnergySource) - if !stringIn(config.EnergySource, "gift_point_added", "heat_value") { + if config.EnergySource == "gift_point_added" { + // gift_point_added 是历史配置值;GIFT_POINT 已下线,后台读取旧配置时统一切到真实礼物贡献口径。 + config.EnergySource = defaultEnergySource + } + if config.EnergySource != defaultEnergySource { return RoomTreasureConfig{}, fmt.Errorf("%w: 能量来源不支持", ErrInvalidArgument) } if config.OpenDelayMS < 0 { diff --git a/server/admin/internal/modules/userleaderboard/service.go b/server/admin/internal/modules/userleaderboard/service.go index b120b635..3d4f2b2b 100644 --- a/server/admin/internal/modules/userleaderboard/service.go +++ b/server/admin/internal/modules/userleaderboard/service.go @@ -213,6 +213,7 @@ func periodWindow(period string, now time.Time) (time.Time, time.Time) { func (s *Service) count(ctx context.Context, appCode string, boardType string, startMS int64, endMS int64) (int64, error) { subject, predicate := leaderboardDimension(boardType) + // 排行榜价值优先使用送礼时按真实扣费比例生成的 heat_value;旧交易缺字段时只退回 coin_spent/charge_amount,不再读取 GIFT_POINT。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -220,10 +221,9 @@ func (s *Service) count(ctx context.Context, appCode string, boardType string, s CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, @@ -247,6 +247,7 @@ func (s *Service) count(ctx context.Context, appCode string, boardType string, s func (s *Service) listItems(ctx context.Context, appCode string, boardType string, startMS int64, endMS int64, limit int, offset int) ([]Item, error) { subject, predicate := leaderboardDimension(boardType) + // 排行榜列表和值排序统一使用 heat_value 口径,避免历史 gift_point 字段重新参与运营排行。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -254,10 +255,9 @@ func (s *Service) listItems(ctx context.Context, appCode string, boardType strin CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, @@ -305,6 +305,7 @@ func (s *Service) listItems(ctx context.Context, appCode string, boardType strin func (s *Service) rankForUser(ctx context.Context, appCode string, boardType string, startMS int64, endMS int64, userID int64) (Item, bool, error) { subject, predicate := leaderboardDimension(boardType) + // 用户名次查询与列表共用真实贡献口径;只兼容读取老交易的扣费金额,不兼容读取积分字段。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -312,10 +313,9 @@ func (s *Service) rankForUser(ctx context.Context, appCode string, boardType str CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, diff --git a/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler.go b/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler.go index 1afbe771..f1d1ad02 100644 --- a/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler.go +++ b/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler.go @@ -223,6 +223,7 @@ func userLeaderboardPeriodWindow(period string, now time.Time) (time.Time, time. func countUserLeaderboard(ctx context.Context, db *sql.DB, appCode string, boardType string, startMS int64, endMS int64) (int64, error) { subject, predicate := userLeaderboardDimension(boardType) + // App 排行榜价值优先使用真实送礼贡献 heat_value;旧交易只兜底扣费金额,不再读取历史 GIFT_POINT 字段。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -230,10 +231,9 @@ func countUserLeaderboard(ctx context.Context, db *sql.DB, appCode string, board CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, @@ -257,6 +257,7 @@ func countUserLeaderboard(ctx context.Context, db *sql.DB, appCode string, board func listUserLeaderboardItems(ctx context.Context, db *sql.DB, appCode string, boardType string, startMS int64, endMS int64, limit int, offset int) ([]userLeaderboardItem, error) { subject, predicate := userLeaderboardDimension(boardType) + // 列表排序和值统计统一走 heat_value,保证 App 和后台排行榜不被历史积分字段污染。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -264,10 +265,9 @@ func listUserLeaderboardItems(ctx context.Context, db *sql.DB, appCode string, b CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, @@ -315,6 +315,7 @@ func listUserLeaderboardItems(ctx context.Context, db *sql.DB, appCode string, b func userLeaderboardRankForUser(ctx context.Context, db *sql.DB, appCode string, boardType string, startMS int64, endMS int64, userID int64) (userLeaderboardItem, bool, error) { subject, predicate := userLeaderboardDimension(boardType) + // 当前用户名次查询只按真实贡献或扣费兜底统计,不再兼容 gift_point_added/gift_point_amount。 query := fmt.Sprintf(` WITH gift_facts AS ( SELECT @@ -322,10 +323,9 @@ func userLeaderboardRankForUser(ctx context.Context, db *sql.DB, appCode string, CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.target_user_id')) AS SIGNED) AS target_user_id, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.room_id')), '') AS room_id, COALESCE( - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_added')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_point_amount')) AS SIGNED), - CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.heat_value')) AS SIGNED), CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_spent')) AS SIGNED), + CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.charge_amount')) AS SIGNED), 0 ) AS gift_value, COALESCE(CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.gift_count')) AS SIGNED), 0) AS gift_count, diff --git a/services/room-service/deploy/mysql/initdb/001_room_service.sql b/services/room-service/deploy/mysql/initdb/001_room_service.sql index 26d3b27e..b267839d 100644 --- a/services/room-service/deploy/mysql/initdb/001_room_service.sql +++ b/services/room-service/deploy/mysql/initdb/001_room_service.sql @@ -254,7 +254,7 @@ INSERT IGNORE INTO room_treasure_configs ( 'lalu', 0, 1, - 'gift_point_added', + 'heat_value', 30000, 1, 'region', diff --git a/services/room-service/internal/room/command/command.go b/services/room-service/internal/room/command/command.go index bc22a9a5..c752e3d3 100644 --- a/services/room-service/internal/room/command/command.go +++ b/services/room-service/internal/room/command/command.go @@ -406,7 +406,7 @@ type SendGift struct { BillingReceiptID string `json:"billing_receipt_id,omitempty"` // CoinSpent 是 sender COIN 实际扣减值,来自 wallet-service 服务端价格。 CoinSpent int64 `json:"coin_spent,omitempty"` - // GiftPointAdded 是 target GIFT_POINT 实际入账值,来自 wallet-service。 + // GiftPointAdded 是历史命令字段;GIFT_POINT 已下线,新送礼不再赋值,恢复逻辑只依赖 HeatValue。 GiftPointAdded int64 `json:"gift_point_added,omitempty"` // HeatValue 是 Room Cell 恢复时唯一可信的热度增量,不能重新用客户端价格推导。 HeatValue int64 `json:"heat_value,omitempty"` diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index 51551591..d1a71cd0 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -123,7 +123,6 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r } settledCommand.BillingReceiptID = billing.GetBillingReceiptId() settledCommand.CoinSpent = billing.GetCoinSpent() - settledCommand.GiftPointAdded = billing.GetGiftPointAdded() settledCommand.HeatValue = billing.GetHeatValue() settledCommand.PriceVersion = billing.GetPriceVersion() settledCommand.GiftTypeCode = billing.GetGiftTypeCode() @@ -259,7 +258,6 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r "gift_count": fmt.Sprintf("%d", cmd.GiftCount), "billing_receipt_id": billing.GetBillingReceiptId(), "coin_spent": fmt.Sprintf("%d", settledCommand.CoinSpent), - "gift_point_added": fmt.Sprintf("%d", settledCommand.GiftPointAdded), "target_count": fmt.Sprintf("%d", len(cmd.TargetUserIDs)), "target_user_ids": giftTargetUserIDsAttribute(cmd.TargetUserIDs), "price_version": settledCommand.PriceVersion, diff --git a/services/room-service/internal/room/service/room_treasure.go b/services/room-service/internal/room/service/room_treasure.go index 4f80cb78..359c0de1 100644 --- a/services/room-service/internal/room/service/room_treasure.go +++ b/services/room-service/internal/room/service/room_treasure.go @@ -25,12 +25,11 @@ import ( const ( roomTreasureLevelCount = 7 - roomTreasureDefaultEnergySource = "gift_point_added" + roomTreasureDefaultEnergySource = "heat_value" roomTreasureDefaultOpenDelayMS = int64(30_000) roomTreasureDefaultBroadcastScope = "region" roomTreasureDefaultRewardStackPolicy = "allow_stack" - roomTreasureEnergyGiftPoint = "gift_point_added" roomTreasureEnergyHeatValue = "heat_value" roomTreasureBroadcastNone = "none" @@ -127,7 +126,11 @@ func normalizeRoomTreasureConfig(config RoomTreasureConfig) (RoomTreasureConfig, return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure config_version is invalid") } config.EnergySource = defaultRoomTreasureString(config.EnergySource, roomTreasureDefaultEnergySource) - if config.EnergySource != roomTreasureEnergyGiftPoint && config.EnergySource != roomTreasureEnergyHeatValue { + if config.EnergySource == "gift_point_added" { + // 旧配置可能还存着 gift_point_added;GIFT_POINT 已下线,运行时统一按真实送礼贡献 heat_value 计算宝箱能量。 + config.EnergySource = roomTreasureEnergyHeatValue + } + if config.EnergySource != roomTreasureEnergyHeatValue { return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure energy_source is invalid") } if config.OpenDelayMS < 0 || config.BroadcastDelayMS < 0 { @@ -327,7 +330,7 @@ func (s *Service) applyRoomTreasureGift(now time.Time, current *state.RoomState, treasure := treasureStateForNow(current.Treasure, cfg, now, true) result := treasureGiftApplyResult{touched: current.Treasure == nil || treasure.ResetAtMS != current.Treasure.ResetAtMS} - addedEnergy := roomTreasureEnergy(cfg, cmd.GiftID, billing.GetGiftTypeCode(), billing.GetGiftPointAdded(), billing.GetHeatValue()) + addedEnergy := roomTreasureEnergy(cfg, cmd.GiftID, billing.GetGiftTypeCode(), billing.GetHeatValue()) effectiveEnergy := int64(0) overflowEnergy := int64(0) @@ -483,11 +486,9 @@ func roomTreasureLevelByNumber(cfg RoomTreasureConfig, level int32) RoomTreasure return defaultRoomTreasureConfig(cfg.AppCode).Levels[0] } -func roomTreasureEnergy(cfg RoomTreasureConfig, giftID string, giftTypeCode string, giftPointAdded int64, heatValue int64) int64 { - base := giftPointAdded - if cfg.EnergySource == roomTreasureEnergyHeatValue { - base = heatValue - } +func roomTreasureEnergy(cfg RoomTreasureConfig, giftID string, giftTypeCode string, heatValue int64) int64 { + // 宝箱能量只读取 wallet-service 按真实扣费和贡献比例计算出的 heat_value,避免历史 GIFT_POINT 字段污染活动进度。 + base := heatValue if base < 0 { base = 0 } diff --git a/services/room-service/internal/storage/mysql/repository.go b/services/room-service/internal/storage/mysql/repository.go index 8560606d..dac7c891 100644 --- a/services/room-service/internal/storage/mysql/repository.go +++ b/services/room-service/internal/storage/mysql/repository.go @@ -291,7 +291,7 @@ func (r *Repository) Migrate(ctx context.Context) error { 'lalu', 0, 1, - 'gift_point_added', + 'heat_value', 30000, 1, 'region', 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 f6151479..95e27fc0 100644 --- a/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql +++ b/services/wallet-service/deploy/mysql/initdb/001_wallet_service.sql @@ -402,7 +402,7 @@ CREATE TABLE IF NOT EXISTS wallet_gift_prices ( status VARCHAR(32) NOT NULL COMMENT '业务状态', charge_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '扣费资产类型', coin_price BIGINT NOT NULL COMMENT '金币价格', - gift_point_amount BIGINT NOT NULL COMMENT '礼物积分数量', + gift_point_amount BIGINT NOT NULL COMMENT '历史字段:GIFT_POINT 已下线,新写入固定 0', heat_value BIGINT NOT NULL COMMENT '热度值', effective_at_ms BIGINT NOT NULL COMMENT '生效时间,UTC epoch ms', created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', @@ -590,7 +590,7 @@ CREATE TABLE IF NOT EXISTS resources ( wallet_asset_amount BIGINT NOT NULL DEFAULT 0 COMMENT '钱包资产数量', price_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '资源价格类型:coin/free', coin_price BIGINT NOT NULL DEFAULT 0 COMMENT '资源金币价格', - gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT '资源礼物积分', + gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段:GIFT_POINT 已下线,新写入固定 0', usage_scope_json JSON NOT NULL COMMENT '使用范围 JSON 配置或快照', asset_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '资产 URL', preview_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '预览 URL', @@ -635,7 +635,7 @@ DEALLOCATE PREPARE stmt; SET @ddl := IF( (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND COLUMN_NAME = 'gift_point_amount') = 0, - 'ALTER TABLE resources ADD COLUMN gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT ''资源礼物积分'' AFTER coin_price', + 'ALTER TABLE resources ADD COLUMN gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT ''历史字段:GIFT_POINT 已下线,新写入固定 0'' AFTER coin_price', 'SELECT 1' ); PREPARE stmt FROM @ddl; @@ -831,7 +831,7 @@ CREATE TABLE IF NOT EXISTS user_gift_wall ( total_value BIGINT NOT NULL DEFAULT 0 COMMENT '总值', total_coin_value BIGINT NOT NULL DEFAULT 0 COMMENT '总金币值', total_diamond_value BIGINT NOT NULL DEFAULT 0 COMMENT '总钻石值', - total_gift_point BIGINT NOT NULL DEFAULT 0 COMMENT '总礼物积分', + total_gift_point BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段:GIFT_POINT 已下线,新送礼不再累加', total_heat_value BIGINT NOT NULL DEFAULT 0 COMMENT '总热度值', charge_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '扣费资产类型', last_price_version VARCHAR(64) NOT NULL DEFAULT '' COMMENT '最后价格版本', diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index fce24118..c6ebf25b 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -7,7 +7,7 @@ const ( AssetCoin = "COIN" // AssetCoinSellerCoin 是币商专用金币资产,只能通过币商转账兑换成玩家普通 COIN。 AssetCoinSellerCoin = "COIN_SELLER_COIN" - // AssetGiftPoint 是主播礼物积分,不能直接消费或提现。 + // AssetGiftPoint 是历史礼物积分资产,只保留历史账本查询兼容;新送礼不会再给它入账。 AssetGiftPoint = "GIFT_POINT" // AssetHostPeriodDiamond 是主播工资周期钻石投影,只参与工资等级结算,不进入通用钱包余额。 AssetHostPeriodDiamond = "HOST_PERIOD_DIAMOND" @@ -126,7 +126,7 @@ type DebitGiftCommand struct { type DebitGiftTargetCommand struct { // CommandID 是单个目标交易的幂等键;同一批量送礼必须为每个目标派生独立值。 CommandID string - // TargetUserID 是本次入账 GIFT_POINT 的用户。 + // TargetUserID 是本次收礼用户;GIFT_POINT 已下线,新送礼不会再给目标用户积分入账。 TargetUserID int64 // TargetIsHost 只能由 gateway 注入,批量目标之间不能共享该身份快照。 TargetIsHost bool @@ -157,11 +157,12 @@ type Receipt struct { CoinSpent int64 ChargeAssetType string ChargeAmount int64 - GiftPointAdded int64 - HeatValue int64 - GiftTypeCode string - PriceVersion string - BalanceAfter int64 + // GiftPointAdded 是历史回执字段,新送礼固定为 0;房间贡献和主播周期钻石只按真实扣费金额计算。 + GiftPointAdded int64 + HeatValue int64 + GiftTypeCode string + PriceVersion string + BalanceAfter int64 // HostPeriodDiamondAdded 是本次送礼写入主播工资周期账户的钻石数;非主播恒为 0。 HostPeriodDiamondAdded int64 // HostPeriodCycleKey 是工资周期键,当前按 UTC 月生成,后续结算按此键定位周期账户。 @@ -447,13 +448,14 @@ type GiftWallItem struct { TotalValue int64 TotalCoinValue int64 TotalDiamondValue int64 - TotalGiftPoint int64 - TotalHeatValue int64 - ChargeAssetType string - LastPriceVersion string - FirstReceivedAtMS int64 - LastReceivedAtMS int64 - SortOrder int32 + // TotalGiftPoint 是历史礼物墙字段,新送礼不再累加,保留用于旧数据展示兼容。 + TotalGiftPoint int64 + TotalHeatValue int64 + ChargeAssetType string + LastPriceVersion string + FirstReceivedAtMS int64 + LastReceivedAtMS int64 + SortOrder int32 } // UserGiftWall 汇总礼物墙首屏需要的全量统计和按礼物类型聚合列表。 @@ -464,8 +466,9 @@ type UserGiftWall struct { TotalValue int64 TotalCoinValue int64 TotalDiamondValue int64 - TotalGiftPoint int64 - TotalHeatValue int64 + // TotalGiftPoint 是历史礼物墙汇总字段,新送礼不再累加,保留用于旧数据展示兼容。 + TotalGiftPoint int64 + TotalHeatValue int64 } // RechargeProduct 是用户充值页读取的充值档位。 diff --git a/services/wallet-service/internal/domain/resource/resource.go b/services/wallet-service/internal/domain/resource/resource.go index d2472591..4304f712 100644 --- a/services/wallet-service/internal/domain/resource/resource.go +++ b/services/wallet-service/internal/domain/resource/resource.go @@ -79,18 +79,19 @@ const ( ) type Resource struct { - AppCode string - ResourceID int64 - ResourceCode string - ResourceType string - Name string - Status string - Grantable bool - GrantStrategy string - WalletAssetType string - WalletAssetAmount int64 - PriceType string - CoinPrice int64 + AppCode string + ResourceID int64 + ResourceCode string + ResourceType string + Name string + Status string + Grantable bool + GrantStrategy string + WalletAssetType string + WalletAssetAmount int64 + PriceType string + CoinPrice int64 + // GiftPointAmount 是历史字段;GIFT_POINT 已下线,新资源和礼物配置只保留真实 COIN 价格。 GiftPointAmount int64 UsageScopes []string AssetURL string @@ -146,18 +147,19 @@ type GiftConfig struct { PresentationJSON string PriceVersion string CoinPrice int64 - GiftPointAmount int64 - HeatValue int64 - GiftTypeCode string - ChargeAssetType string - EffectiveFromMS int64 - EffectiveToMS int64 - EffectTypes []string - CreatedByUserID int64 - UpdatedByUserID int64 - CreatedAtMS int64 - UpdatedAtMS int64 - RegionIDs []int64 + // GiftPointAmount 是历史字段;送礼结算不再读取,新配置固定为 0。 + GiftPointAmount int64 + HeatValue int64 + GiftTypeCode string + ChargeAssetType string + EffectiveFromMS int64 + EffectiveToMS int64 + EffectTypes []string + CreatedByUserID int64 + UpdatedByUserID int64 + CreatedAtMS int64 + UpdatedAtMS int64 + RegionIDs []int64 } type GiftTypeConfig struct { @@ -249,18 +251,19 @@ type ListResourcesQuery struct { } type ResourceCommand struct { - AppCode string - ResourceID int64 - ResourceCode string - ResourceType string - Name string - Status string - Grantable bool - GrantStrategy string - WalletAssetType string - WalletAssetAmount int64 - PriceType string - CoinPrice int64 + AppCode string + ResourceID int64 + ResourceCode string + ResourceType string + Name string + Status string + Grantable bool + GrantStrategy string + WalletAssetType string + WalletAssetAmount int64 + PriceType string + CoinPrice int64 + // GiftPointAmount 是历史字段;保存资源时固定为 0,保留字段只兼容旧表结构。 GiftPointAmount int64 UsageScopes []string AssetURL string @@ -315,6 +318,7 @@ type ListGiftConfigsQuery struct { AppCode string Status string Keyword string + GiftTypeCode string Page int32 PageSize int32 ActiveOnly bool @@ -338,16 +342,17 @@ type GiftConfigCommand struct { PresentationJSON string PriceVersion string CoinPrice int64 - GiftPointAmount int64 - HeatValue int64 - EffectiveAtMS int64 - GiftTypeCode string - ChargeAssetType string - EffectiveFromMS int64 - EffectiveToMS int64 - EffectTypes []string - OperatorUserID int64 - RegionIDs []int64 + // GiftPointAmount 是历史字段;保存礼物价格时固定为 0,业务计算只读 CoinPrice。 + GiftPointAmount int64 + HeatValue int64 + EffectiveAtMS int64 + GiftTypeCode string + ChargeAssetType string + EffectiveFromMS int64 + EffectiveToMS int64 + EffectTypes []string + OperatorUserID int64 + RegionIDs []int64 } type GiftTypeConfigCommand struct { diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index a32cc57a..7f7864d4 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -34,8 +34,8 @@ func walletOutboxMessageFromRecord(record mysqlstorage.WalletOutboxRecord) walle } } -// TestDebitGiftUsesServerPriceAndCreditsGiftPoint 验证送礼只信服务端价格并产生双边分录。 -func TestDebitGiftUsesServerPriceAndCreditsGiftPoint(t *testing.T) { +// TestDebitGiftUsesServerPriceWithoutGiftPointCredit 验证送礼只信服务端价格,且礼物积分下线后不再给收礼人入账。 +func TestDebitGiftUsesServerPriceWithoutGiftPointCredit(t *testing.T) { repository := mysqltest.NewRepository(t) repository.SetBalance(10001, 100) repository.SetGiftPrice("rose", "v9", 7, 3, 11) @@ -54,7 +54,7 @@ func TestDebitGiftUsesServerPriceAndCreditsGiftPoint(t *testing.T) { t.Fatalf("DebitGift failed: %v", err) } - if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 6 || receipt.HeatValue != 14 || receipt.BalanceAfter != 86 || receipt.PriceVersion != "v9" { + if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 0 || receipt.HeatValue != 14 || receipt.BalanceAfter != 86 || receipt.PriceVersion != "v9" { t.Fatalf("server price settlement mismatch: %+v", receipt) } if receipt.TransactionID == "" || receipt.BillingReceiptID == "" { @@ -72,14 +72,14 @@ func TestDebitGiftUsesServerPriceAndCreditsGiftPoint(t *testing.T) { if err != nil { t.Fatalf("GetBalances target failed: %v", err) } - if balanceAmount(balances, ledger.AssetGiftPoint) != 6 { - t.Fatalf("target GIFT_POINT balance mismatch: %+v", balances) + if balanceAmount(balances, ledger.AssetGiftPoint) != 0 { + t.Fatalf("target GIFT_POINT must stay zero after point removal: %+v", balances) } - if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 2 { - t.Fatalf("gift debit should write two entries, got %d", got) + if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 1 { + t.Fatalf("gift debit should only write sender COIN entry, got %d", got) } - if got := repository.CountRows("wallet_outbox", "transaction_id = ?", receipt.TransactionID); got != 3 { - t.Fatalf("gift debit should write balance and gift outbox events, got %d", got) + if got := repository.CountRows("wallet_outbox", "transaction_id = ?", receipt.TransactionID); got != 2 { + t.Fatalf("gift debit should write sender balance and gift outbox events, got %d", got) } if receipt.HostPeriodDiamondAdded != 0 || receipt.HostPeriodCycleKey != "" { t.Fatalf("non-host gift must not credit host period diamonds: %+v", receipt) @@ -113,7 +113,7 @@ func TestBatchDebitGiftSettlesAllTargetsAtomically(t *testing.T) { t.Fatalf("BatchDebitGift failed: %v", err) } - if receipt.Aggregate.CoinSpent != 28 || receipt.Aggregate.GiftPointAdded != 12 || receipt.Aggregate.HeatValue != 28 || receipt.Aggregate.BalanceAfter != 72 || len(receipt.Targets) != 2 { + if receipt.Aggregate.CoinSpent != 28 || receipt.Aggregate.GiftPointAdded != 0 || receipt.Aggregate.HeatValue != 28 || receipt.Aggregate.BalanceAfter != 72 || len(receipt.Targets) != 2 { t.Fatalf("batch aggregate mismatch: %+v", receipt) } for _, userID := range []int64{10002, 10003} { @@ -121,8 +121,8 @@ func TestBatchDebitGiftSettlesAllTargetsAtomically(t *testing.T) { if err != nil { t.Fatalf("GetBalances target %d failed: %v", userID, err) } - if balanceAmount(balances, ledger.AssetGiftPoint) != 6 { - t.Fatalf("target %d GIFT_POINT mismatch: %+v", userID, balances) + if balanceAmount(balances, ledger.AssetGiftPoint) != 0 { + t.Fatalf("target %d GIFT_POINT must stay zero after point removal: %+v", userID, balances) } } balances, err := svc.GetBalances(context.Background(), 10001, []string{ledger.AssetCoin}) @@ -135,8 +135,8 @@ func TestBatchDebitGiftSettlesAllTargetsAtomically(t *testing.T) { if got := repository.CountRows("wallet_transactions", "command_id IN (?, ?)", "cmd-gift-batch:target:10002", "cmd-gift-batch:target:10003"); got != 2 { t.Fatalf("batch gift should write one transaction per target, got %d", got) } - if got := repository.CountRows("wallet_entries", "transaction_id IN (?, ?)", receipt.Targets[0].Receipt.TransactionID, receipt.Targets[1].Receipt.TransactionID); got != 4 { - t.Fatalf("batch gift should write sender and target entries per target, got %d", got) + if got := repository.CountRows("wallet_entries", "transaction_id IN (?, ?)", receipt.Targets[0].Receipt.TransactionID, receipt.Targets[1].Receipt.TransactionID); got != 2 { + t.Fatalf("batch gift should only write sender COIN entries per target, got %d", got) } again, err := svc.BatchDebitGift(context.Background(), ledger.BatchDebitGiftCommand{ @@ -303,7 +303,7 @@ func TestDebitGiftAppliesGlobalDefaultGiftDiamondRatioToHeatValueByGiftType(t *t if err != nil { t.Fatalf("DebitGift %s failed: %v", tc.giftType, err) } - if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 100 || receipt.CoinSpent != tc.coinPrice { + if receipt.HeatValue != tc.wantHeat || receipt.GiftPointAdded != 0 || receipt.CoinSpent != tc.coinPrice { t.Fatalf("%s room contribution ratio mismatch: %+v want heat %d", tc.giftType, receipt, tc.wantHeat) } } @@ -338,7 +338,7 @@ func TestBatchDebitGiftAppliesGlobalDefaultGiftDiamondRatioToEachTargetHeatValue t.Fatalf("batch aggregate room contribution ratio mismatch: %+v", receipt) } for _, target := range receipt.Targets { - if target.Receipt.HeatValue != 10 || target.Receipt.GiftPointAdded != 100 { + if target.Receipt.HeatValue != 10 || target.Receipt.GiftPointAdded != 0 { t.Fatalf("target room contribution ratio mismatch: %+v", target) } } @@ -1003,7 +1003,7 @@ func TestHostSalaryHalfMonthSettlementUsesPolicyMode(t *testing.T) { } } -// TestDebitGiftAllowsSelfGift 验证用户可以给自己送礼,扣 COIN 和收 GIFT_POINT 仍然分别落账。 +// TestDebitGiftAllowsSelfGift 验证用户可以给自己送礼;礼物积分下线后只扣 COIN,不再回加 GIFT_POINT。 func TestDebitGiftAllowsSelfGift(t *testing.T) { repository := mysqltest.NewRepository(t) repository.SetBalance(10001, 100) @@ -1023,18 +1023,18 @@ func TestDebitGiftAllowsSelfGift(t *testing.T) { t.Fatalf("self DebitGift failed: %v", err) } - if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 6 || receipt.BalanceAfter != 86 { + if receipt.CoinSpent != 14 || receipt.GiftPointAdded != 0 || receipt.BalanceAfter != 86 { t.Fatalf("self gift settlement mismatch: %+v", receipt) } balances, err := svc.GetBalances(context.Background(), 10001, []string{ledger.AssetCoin, ledger.AssetGiftPoint}) if err != nil { t.Fatalf("GetBalances failed: %v", err) } - if balanceAmount(balances, ledger.AssetCoin) != 86 || balanceAmount(balances, ledger.AssetGiftPoint) != 6 { + if balanceAmount(balances, ledger.AssetCoin) != 86 || balanceAmount(balances, ledger.AssetGiftPoint) != 0 { t.Fatalf("self gift balances mismatch: %+v", balances) } - if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 2 { - t.Fatalf("self gift should still write debit and credit entries, got %d", got) + if got := repository.CountRows("wallet_entries", "transaction_id = ?", receipt.TransactionID); got != 1 { + t.Fatalf("self gift should only write debit entry, got %d", got) } } @@ -2159,7 +2159,7 @@ func TestGiftConfigMustSelectGiftResource(t *testing.T) { if err != nil { t.Fatalf("DebitGift with resource-backed gift failed: %v", err) } - if receipt.CoinSpent != 10 || receipt.GiftPointAdded != 4 || receipt.HeatValue != 10 { + if receipt.CoinSpent != 10 || receipt.GiftPointAdded != 0 || receipt.HeatValue != 10 { t.Fatalf("resource-backed gift settlement mismatch: %+v", receipt) } } @@ -2244,8 +2244,8 @@ func TestGiftConfigSyncsConfiguredResourcePrice(t *testing.T) { if err != nil { t.Fatalf("create priced gift resource failed: %v", err) } - if paidResource.GiftPointAmount != 77 { - t.Fatalf("resource gift point should sync coin price: %+v", paidResource) + if paidResource.GiftPointAmount != 0 { + t.Fatalf("resource gift point should stay disabled: %+v", paidResource) } gift, err := svc.CreateGiftConfig(ctx, resourcedomain.GiftConfigCommand{ GiftID: "price-sync", @@ -2264,7 +2264,7 @@ func TestGiftConfigSyncsConfiguredResourcePrice(t *testing.T) { if err != nil { t.Fatalf("create synced gift config failed: %v", err) } - if gift.ChargeAssetType != ledger.AssetCoin || gift.CoinPrice != 77 || gift.GiftPointAmount != 77 { + if gift.ChargeAssetType != ledger.AssetCoin || gift.CoinPrice != 77 || gift.GiftPointAmount != 0 { t.Fatalf("gift price should be overridden by resource price: %+v", gift) } updatedResource, err := svc.UpdateResource(ctx, resourcedomain.ResourceCommand{ @@ -2283,7 +2283,7 @@ func TestGiftConfigSyncsConfiguredResourcePrice(t *testing.T) { if err != nil { t.Fatalf("update priced gift resource failed: %v", err) } - if updatedResource.CoinPrice != 88 || updatedResource.GiftPointAmount != 88 { + if updatedResource.CoinPrice != 88 || updatedResource.GiftPointAmount != 0 { t.Fatalf("updated resource price mismatch: %+v", updatedResource) } repository.SetBalance(54001, 100) @@ -2298,7 +2298,7 @@ func TestGiftConfigSyncsConfiguredResourcePrice(t *testing.T) { if err != nil { t.Fatalf("debit gift after resource price update failed: %v", err) } - if updatedReceipt.CoinSpent != 88 || updatedReceipt.GiftPointAdded != 88 { + if updatedReceipt.CoinSpent != 88 || updatedReceipt.GiftPointAdded != 0 { t.Fatalf("gift price should follow updated resource price: %+v", updatedReceipt) } diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 95a24148..95c7fd16 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -173,7 +173,7 @@ func (r *Repository) Ping(ctx context.Context) error { return r.db.PingContext(ctx) } -// DebitGift 在一个 MySQL 事务内完成 sender 扣费、target GIFT_POINT 入账、主播周期钻石入账、分录和 outbox。 +// DebitGift 在一个 MySQL 事务内完成 sender 扣费、主播周期钻石入账、分录和 outbox;历史 GIFT_POINT 回执字段保留但不再入账。 func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftCommand) (ledger.Receipt, error) { if r == nil || r.db == nil { return ledger.Receipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") @@ -218,10 +218,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if err != nil { return ledger.Receipt{}, err } - giftPointAdded, err := checkedMul(price.GiftPointAmount, int64(command.GiftCount)) - if err != nil { - return ledger.Receipt{}, err - } + // 礼物积分已经从运营配置和收礼收益里下线;回执字段只保留 0,兼容旧客户端和历史事件解析。 roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.Receipt{}, err @@ -240,7 +237,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if err != nil { return ledger.Receipt{}, err } - // 非主播不会进入该分支,因此普通用户收礼只增加 GIFT_POINT,不产生工资周期积分。 + // 非主播不会进入该分支,因此普通用户收礼不会产生工资周期钻石。 hostPeriodDiamondAdded, err = giftDiamondAmount(chargeAmount, ratio.PPM) if err != nil { return ledger.Receipt{}, err @@ -257,11 +254,6 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm if sender.AvailableAmount < chargeAmount { return ledger.Receipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") } - target, err := r.lockAccount(ctx, tx, command.TargetUserID, ledger.AssetGiftPoint, true, nowMs) - if err != nil { - return ledger.Receipt{}, err - } - transactionID := transactionID(command.AppCode, command.CommandID) metadata := giftMetadata{ AppCode: command.AppCode, @@ -277,7 +269,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm ChargeAssetType: price.ChargeAssetType, ChargeAmount: chargeAmount, CoinSpent: chargeAmount, - GiftPointAdded: giftPointAdded, + GiftPointAdded: 0, HeatValue: heatValue, BalanceAfter: sender.AvailableAmount - chargeAmount, BillingReceipt: billingReceiptID(command.AppCode, command.CommandID), @@ -296,7 +288,7 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm RoomContributionRatioPercent: roomContributionRatio.Percent, RoomContributionRatioRegionID: roomContributionRatioRegionID, CoinPrice: price.CoinPrice, - GiftPointAmount: price.GiftPointAmount, + GiftPointAmount: 0, HeatUnitValue: price.CoinPrice, } if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeGiftDebit, requestHash, fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { @@ -320,26 +312,8 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm }); err != nil { return ledger.Receipt{}, err } - if err := r.applyAccountDelta(ctx, tx, target, giftPointAdded, 0, nowMs); err != nil { - return ledger.Receipt{}, err - } - targetAfter := target.AvailableAmount + giftPointAdded - if err := r.insertEntry(ctx, tx, walletEntry{ - TransactionID: transactionID, - UserID: command.TargetUserID, - AssetType: ledger.AssetGiftPoint, - AvailableDelta: giftPointAdded, - FrozenDelta: 0, - AvailableAfter: targetAfter, - FrozenAfter: target.FrozenAmount, - CounterpartyUserID: command.SenderUserID, - RoomID: command.RoomID, - CreatedAtMS: nowMs, - }); err != nil { - return ledger.Receipt{}, err - } if hostPeriodDiamondAdded > 0 { - // 周期钻石与送礼扣费同事务提交;如果后续任一步失败,用户扣币、主播礼物积分和工资积分会一起回滚。 + // 周期钻石与送礼扣费同事务提交;如果后续任一步失败,用户扣币和主播工资周期钻石会一起回滚。 hostPeriodDiamondAfter, hostPeriodDiamondVersion, err := r.creditHostPeriodDiamonds(ctx, tx, transactionID, command.CommandID, metadata, nowMs) if err != nil { return ledger.Receipt{}, err @@ -350,7 +324,6 @@ func (r *Repository) DebitGift(ctx context.Context, command ledger.DebitGiftComm events := []walletOutboxEvent{ balanceChangedEvent(transactionID, command.CommandID, command.SenderUserID, price.ChargeAssetType, -chargeAmount, 0, senderAfter, sender.FrozenAmount, sender.Version+1, metadata, nowMs), - balanceChangedEvent(transactionID, command.CommandID, command.TargetUserID, ledger.AssetGiftPoint, giftPointAdded, 0, targetAfter, target.FrozenAmount, target.Version+1, metadata, nowMs), giftDebitedEvent(transactionID, command.CommandID, command.SenderUserID, price.ChargeAssetType, -chargeAmount, 0, metadata, nowMs), } if hostPeriodDiamondAdded > 0 { @@ -402,10 +375,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb if err != nil { return ledger.BatchGiftReceipt{}, err } - giftPointAdded, err := checkedMul(price.GiftPointAmount, int64(command.GiftCount)) - if err != nil { - return ledger.BatchGiftReceipt{}, err - } + // 礼物积分已经下线;批量回执仍保留字段,但每个目标都固定返回 0。 roomContributionRatio, roomContributionRatioRegionID, err := r.resolveGlobalGiftDiamondRatio(ctx, tx, command.AppCode, giftConfig.GiftTypeCode) if err != nil { return ledger.BatchGiftReceipt{}, err @@ -466,11 +436,6 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb return ledger.BatchGiftReceipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance") } - targetAccounts, err := r.lockGiftTargetAccounts(ctx, tx, command.Targets, nowMs) - if err != nil { - return ledger.BatchGiftReceipt{}, err - } - anyHostTarget := false for _, target := range command.Targets { if target.TargetIsHost { @@ -487,7 +452,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb } } - events := make([]walletOutboxEvent, 0, len(command.Targets)*4) + events := make([]walletOutboxEvent, 0, len(command.Targets)*3) targetReceipts := make([]ledger.BatchGiftTargetReceipt, 0, len(command.Targets)) for _, target := range command.Targets { hostPeriodDiamondAdded := int64(0) @@ -521,7 +486,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb ChargeAssetType: price.ChargeAssetType, ChargeAmount: chargeAmount, CoinSpent: chargeAmount, - GiftPointAdded: giftPointAdded, + GiftPointAdded: 0, HeatValue: heatValue, BalanceAfter: senderAfter, BillingReceipt: billingReceiptID(command.AppCode, target.CommandID), @@ -540,7 +505,7 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb RoomContributionRatioPercent: roomContributionRatio.Percent, RoomContributionRatioRegionID: roomContributionRatioRegionID, CoinPrice: price.CoinPrice, - GiftPointAmount: price.GiftPointAmount, + GiftPointAmount: 0, HeatUnitValue: price.CoinPrice, } if err := r.insertTransaction(ctx, tx, transactionID, target.CommandID, bizTypeGiftDebit, debitRequestHash(debitGiftCommandFromBatchTarget(command, target)), fmt.Sprintf("%s:%s", command.GiftID, price.PriceVersion), metadata, nowMs); err != nil { @@ -553,16 +518,6 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb sender.AvailableAmount = senderAfter sender.Version++ - targetAccount := targetAccounts[target.TargetUserID] - if err := r.applyAccountDelta(ctx, tx, targetAccount, giftPointAdded, 0, nowMs); err != nil { - return ledger.BatchGiftReceipt{}, err - } - targetAfter := targetAccount.AvailableAmount + giftPointAdded - events = append(events, balanceChangedEvent(transactionID, target.CommandID, target.TargetUserID, ledger.AssetGiftPoint, giftPointAdded, 0, targetAfter, targetAccount.FrozenAmount, targetAccount.Version+1, metadata, nowMs)) - targetAccount.AvailableAmount = targetAfter - targetAccount.Version++ - targetAccounts[target.TargetUserID] = targetAccount - if err := r.insertEntry(ctx, tx, walletEntry{ TransactionID: transactionID, UserID: command.SenderUserID, @@ -577,20 +532,6 @@ func (r *Repository) BatchDebitGift(ctx context.Context, command ledger.BatchDeb }); err != nil { return ledger.BatchGiftReceipt{}, err } - if err := r.insertEntry(ctx, tx, walletEntry{ - TransactionID: transactionID, - UserID: target.TargetUserID, - AssetType: ledger.AssetGiftPoint, - AvailableDelta: giftPointAdded, - FrozenDelta: 0, - AvailableAfter: targetAfter, - FrozenAfter: targetAccount.FrozenAmount, - CounterpartyUserID: command.SenderUserID, - RoomID: command.RoomID, - CreatedAtMS: nowMs, - }); err != nil { - return ledger.BatchGiftReceipt{}, err - } if hostPeriodDiamondAdded > 0 { hostPeriodDiamondAfter, hostPeriodDiamondVersion, err := r.creditHostPeriodDiamonds(ctx, tx, transactionID, target.CommandID, metadata, nowMs) if err != nil { @@ -742,7 +683,7 @@ func (r *Repository) upsertUserGiftWall(ctx context.Context, tx *sql.Tx, metadat chargeAmount, totalCoinValue, totalDiamondValue, - metadata.GiftPointAdded, + 0, metadata.HeatValue, chargeAssetType, metadata.PriceVersion, @@ -1675,6 +1616,7 @@ type giftPrice struct { PriceVersion string ChargeAssetType string CoinPrice int64 + // GiftPointAmount 是 wallet_gift_prices 的历史列;送礼结算只按 CoinPrice 和比例计算,不再读取它做收益。 GiftPointAmount int64 HeatValue int64 } @@ -1716,7 +1658,7 @@ func (r *Repository) resolveGiftPrice(ctx context.Context, tx *sql.Tx, giftID st } return giftPrice{}, err } - if price.CoinPrice < 0 || price.GiftPointAmount < 0 || price.HeatValue < 0 { + if price.CoinPrice < 0 || price.HeatValue < 0 { return giftPrice{}, xerr.New(xerr.Internal, "gift price is invalid") } price.ChargeAssetType = ledger.NormalizeGiftChargeAssetType(price.ChargeAssetType) @@ -2537,22 +2479,24 @@ func (r *Repository) balanceAfterTransaction(ctx context.Context, tx *sql.Tx, tr } type giftMetadata struct { - AppCode string `json:"app_code"` - GiftID string `json:"gift_id"` - GiftName string `json:"gift_name"` - ResourceID int64 `json:"resource_id"` - ResourceSnapshot string `json:"resource_snapshot_json"` - GiftTypeCode string `json:"gift_type_code"` - PresentationJSON string `json:"presentation_json"` - SortOrder int32 `json:"sort_order"` - GiftCount int32 `json:"gift_count"` - PriceVersion string `json:"price_version"` - CoinPrice int64 `json:"coin_price"` - GiftPointAmount int64 `json:"gift_point_amount"` - HeatUnitValue int64 `json:"heat_unit_value"` - ChargeAssetType string `json:"charge_asset_type"` - ChargeAmount int64 `json:"charge_amount"` - CoinSpent int64 `json:"coin_spent"` + AppCode string `json:"app_code"` + GiftID string `json:"gift_id"` + GiftName string `json:"gift_name"` + ResourceID int64 `json:"resource_id"` + ResourceSnapshot string `json:"resource_snapshot_json"` + GiftTypeCode string `json:"gift_type_code"` + PresentationJSON string `json:"presentation_json"` + SortOrder int32 `json:"sort_order"` + GiftCount int32 `json:"gift_count"` + PriceVersion string `json:"price_version"` + CoinPrice int64 `json:"coin_price"` + // GiftPointAmount 是历史礼物积分单价字段,新送礼固定写 0,业务统计只读真实扣费和热度。 + GiftPointAmount int64 `json:"gift_point_amount"` + HeatUnitValue int64 `json:"heat_unit_value"` + ChargeAssetType string `json:"charge_asset_type"` + ChargeAmount int64 `json:"charge_amount"` + CoinSpent int64 `json:"coin_spent"` + // GiftPointAdded 是历史收礼积分字段,新送礼固定写 0,保留 JSON 字段只为旧事件解析兼容。 GiftPointAdded int64 `json:"gift_point_added"` HeatValue int64 `json:"heat_value"` BalanceAfter int64 `json:"balance_after"` @@ -2711,7 +2655,7 @@ func receiptFromGiftMetadata(transactionID string, metadata giftMetadata) ledger CoinSpent: metadata.CoinSpent, ChargeAssetType: chargeAssetType, ChargeAmount: chargeAmount, - GiftPointAdded: metadata.GiftPointAdded, + GiftPointAdded: 0, HeatValue: metadata.HeatValue, GiftTypeCode: metadata.GiftTypeCode, PriceVersion: metadata.PriceVersion, @@ -3207,31 +3151,6 @@ func debitGiftCommandFromBatchTarget(command ledger.BatchDebitGiftCommand, targe } } -func (r *Repository) lockGiftTargetAccounts(ctx context.Context, tx *sql.Tx, targets []ledger.DebitGiftTargetCommand, nowMs int64) (map[int64]walletAccount, error) { - ids := make([]int64, 0, len(targets)) - seen := make(map[int64]struct{}, len(targets)) - for _, target := range targets { - if _, exists := seen[target.TargetUserID]; exists { - continue - } - seen[target.TargetUserID] = struct{}{} - ids = append(ids, target.TargetUserID) - } - sort.Slice(ids, func(left, right int) bool { - return ids[left] < ids[right] - }) - accounts := make(map[int64]walletAccount, len(ids)) - for _, targetUserID := range ids { - // 固定按 user_id 升序锁目标账户,降低并发批量送礼互相等待时形成死锁的概率。 - account, err := r.lockAccount(ctx, tx, targetUserID, ledger.AssetGiftPoint, true, nowMs) - if err != nil { - return nil, err - } - accounts[targetUserID] = account - } - return accounts, nil -} - func aggregateGiftReceipts(targets []ledger.BatchGiftTargetReceipt) (ledger.Receipt, error) { aggregate := ledger.Receipt{} billingReceiptIDs := make([]string, 0, len(targets)) @@ -3251,9 +3170,6 @@ func aggregateGiftReceipts(targets []ledger.BatchGiftTargetReceipt) (ledger.Rece if aggregate.ChargeAmount, err = checkedAdd(aggregate.ChargeAmount, receipt.ChargeAmount); err != nil { return ledger.Receipt{}, err } - if aggregate.GiftPointAdded, err = checkedAdd(aggregate.GiftPointAdded, receipt.GiftPointAdded); err != nil { - return ledger.Receipt{}, err - } if aggregate.HeatValue, err = checkedAdd(aggregate.HeatValue, receipt.HeatValue); err != nil { return ledger.Receipt{}, err } diff --git a/services/wallet-service/internal/storage/mysql/resource_repository.go b/services/wallet-service/internal/storage/mysql/resource_repository.go index f23a2355..521972b1 100644 --- a/services/wallet-service/internal/storage/mysql/resource_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_repository.go @@ -292,11 +292,11 @@ func (r *Repository) syncGiftPricesForResourceTx(ctx context.Context, tx *sql.Tx } coinPrice := int64(0) - giftPointAmount := int64(0) if priceType == resourcedomain.PriceTypeCoin { coinPrice = resource.CoinPrice - giftPointAmount = resource.GiftPointAmount } + // gift_point_amount 是历史字段,资源改价同步礼物价格时固定写 0,避免旧积分口径重新进入送礼链路。 + giftPointAmount := int64(0) if _, err := tx.ExecContext(ctx, ` UPDATE wallet_gift_prices gp JOIN gift_configs gc ON gc.app_code = gp.app_code AND gc.gift_id = gp.gift_id @@ -627,7 +627,7 @@ func (r *Repository) ListGiftConfigs(ctx context.Context, query resourcedomain.L item.PriceVersion = price.PriceVersion item.ChargeAssetType = price.ChargeAssetType item.CoinPrice = price.CoinPrice - item.GiftPointAmount = price.GiftPointAmount + item.GiftPointAmount = 0 item.HeatValue = price.CoinPrice } items = append(items, item) @@ -2006,7 +2006,8 @@ func (r *Repository) getGiftConfig(ctx context.Context, giftID string) (resource gift.PriceVersion = price.PriceVersion gift.ChargeAssetType = price.ChargeAssetType gift.CoinPrice = price.CoinPrice - gift.GiftPointAmount = price.GiftPointAmount + // gift_point_amount 是历史列,后台和送礼主链路只暴露真实 COIN 价格。 + gift.GiftPointAmount = 0 // heat_value 是旧配置列,后台不再读写;对兼容调用方只回真实价格,房间贡献也按真实扣费结算。 gift.HeatValue = price.CoinPrice } @@ -2837,6 +2838,10 @@ func giftConfigWhereSQL(query resourcedomain.ListGiftConfigsQuery) (string, []an where += ` AND (gc.gift_id LIKE ? OR gc.name LIKE ? OR r.resource_code LIKE ?)` args = append(args, like, like, like) } + if query.GiftTypeCode != "" { + where += ` AND gc.gift_type_code = ?` + args = append(args, query.GiftTypeCode) + } if query.FilterRegion { where += ` AND EXISTS ( SELECT 1 @@ -2908,6 +2913,7 @@ func normalizeResourceGroupListQuery(query resourcedomain.ListResourceGroupsQuer func normalizeGiftConfigListQuery(query resourcedomain.ListGiftConfigsQuery) resourcedomain.ListGiftConfigsQuery { query.Status = strings.ToLower(strings.TrimSpace(query.Status)) query.Keyword = strings.TrimSpace(query.Keyword) + query.GiftTypeCode = resourcedomain.NormalizeGiftTypeCode(query.GiftTypeCode) query.Page, query.PageSize = normalizePage(query.Page, query.PageSize) return query } @@ -3082,7 +3088,8 @@ func normalizeResourceCommand(command resourcedomain.ResourceCommand) resourcedo command.CoinPrice = 0 command.GiftPointAmount = 0 } else if command.PriceType == resourcedomain.PriceTypeCoin { - command.GiftPointAmount = command.CoinPrice + // 资源价格只保留真实 COIN 价格;gift_point_amount 是历史字段,写入 0 兼容旧表结构。 + command.GiftPointAmount = 0 } command.AssetURL = strings.TrimSpace(command.AssetURL) command.PreviewURL = strings.TrimSpace(command.PreviewURL) @@ -3124,7 +3131,7 @@ func validateResourceCommand(command resourcedomain.ResourceCommand) error { if command.PriceType == resourcedomain.PriceTypeCoin && command.CoinPrice <= 0 { return xerr.New(xerr.InvalidArgument, "resource coin price is invalid") } - if command.CoinPrice < 0 || command.GiftPointAmount < 0 || command.GiftPointAmount != command.CoinPrice { + if command.CoinPrice < 0 { return xerr.New(xerr.InvalidArgument, "resource price is invalid") } return nil @@ -3265,7 +3272,7 @@ func applyResourcePricingToGiftCommand(command resourcedomain.GiftConfigCommand, case resourcedomain.PriceTypeCoin: command.ChargeAssetType = ledger.AssetCoin command.CoinPrice = resource.CoinPrice - command.GiftPointAmount = resource.GiftPointAmount + command.GiftPointAmount = 0 case resourcedomain.PriceTypeFree: command.ChargeAssetType = ledger.AssetCoin command.CoinPrice = 0 @@ -3289,6 +3296,8 @@ func normalizeGiftConfigCommand(command resourcedomain.GiftConfigCommand) resour command.ChargeAssetType = ledger.AssetCoin } command.EffectTypes = normalizeGiftEffectTypes(command.EffectTypes) + // gift_point_amount 是历史字段,礼物配置保存时固定归零,送礼结算只读取真实 COIN 价格。 + command.GiftPointAmount = 0 if command.EffectiveAtMS < 0 { command.EffectiveAtMS = 0 } @@ -3316,7 +3325,7 @@ func validateGiftConfigCommand(command resourcedomain.GiftConfigCommand) error { if !resourcedomain.ValidStatus(command.Status) { return xerr.New(xerr.InvalidArgument, "status is invalid") } - if command.CoinPrice < 0 || command.GiftPointAmount < 0 || command.HeatValue < 0 { + if command.CoinPrice < 0 || command.HeatValue < 0 { return xerr.New(xerr.InvalidArgument, "gift price is invalid") } if !resourcedomain.ValidGiftTypeCode(command.GiftTypeCode) { diff --git a/services/wallet-service/internal/transport/grpc/resource.go b/services/wallet-service/internal/transport/grpc/resource.go index a5c3466f..48037716 100644 --- a/services/wallet-service/internal/transport/grpc/resource.go +++ b/services/wallet-service/internal/transport/grpc/resource.go @@ -128,6 +128,7 @@ func (s *Server) ListGiftConfigs(ctx context.Context, req *walletv1.ListGiftConf AppCode: req.GetAppCode(), Status: req.GetStatus(), Keyword: req.GetKeyword(), + GiftTypeCode: req.GetGiftTypeCode(), Page: req.GetPage(), PageSize: req.GetPageSize(), ActiveOnly: req.GetActiveOnly(), @@ -401,7 +402,7 @@ func resourceCommandFromCreate(req *walletv1.CreateResourceRequest) resourcedoma WalletAssetAmount: req.GetWalletAssetAmount(), PriceType: req.GetPriceType(), CoinPrice: req.GetCoinPrice(), - GiftPointAmount: req.GetGiftPointAmount(), + GiftPointAmount: 0, UsageScopes: req.GetUsageScopes(), AssetURL: req.GetAssetUrl(), PreviewURL: req.GetPreviewUrl(), @@ -426,7 +427,7 @@ func resourceCommandFromUpdate(req *walletv1.UpdateResourceRequest) resourcedoma WalletAssetAmount: req.GetWalletAssetAmount(), PriceType: req.GetPriceType(), CoinPrice: req.GetCoinPrice(), - GiftPointAmount: req.GetGiftPointAmount(), + GiftPointAmount: 0, UsageScopes: req.GetUsageScopes(), AssetUrl: req.GetAssetUrl(), PreviewUrl: req.GetPreviewUrl(), @@ -478,7 +479,7 @@ func giftConfigCommandFromCreate(req *walletv1.CreateGiftConfigRequest) resource PresentationJSON: req.GetPresentationJson(), PriceVersion: req.GetPriceVersion(), CoinPrice: req.GetCoinPrice(), - GiftPointAmount: req.GetGiftPointAmount(), + GiftPointAmount: 0, HeatValue: req.GetHeatValue(), EffectiveAtMS: req.GetEffectiveAtMs(), GiftTypeCode: req.GetGiftTypeCode(), @@ -502,7 +503,7 @@ func giftConfigCommandFromUpdate(req *walletv1.UpdateGiftConfigRequest) resource PresentationJSON: req.GetPresentationJson(), PriceVersion: req.GetPriceVersion(), CoinPrice: req.GetCoinPrice(), - GiftPointAmount: req.GetGiftPointAmount(), + GiftPointAmount: 0, HeatValue: req.GetHeatValue(), EffectiveAtMS: req.GetEffectiveAtMs(), GiftTypeCode: req.GetGiftTypeCode(), @@ -567,7 +568,7 @@ func resourceToProto(resource resourcedomain.Resource) *walletv1.Resource { WalletAssetAmount: resource.WalletAssetAmount, PriceType: resource.PriceType, CoinPrice: resource.CoinPrice, - GiftPointAmount: resource.GiftPointAmount, + GiftPointAmount: 0, UsageScopes: resource.UsageScopes, AssetUrl: resource.AssetURL, PreviewUrl: resource.PreviewURL, @@ -669,7 +670,7 @@ func giftConfigToProto(gift resourcedomain.GiftConfig) *walletv1.GiftConfig { PriceVersion: gift.PriceVersion, ChargeAssetType: gift.ChargeAssetType, CoinPrice: gift.CoinPrice, - GiftPointAmount: gift.GiftPointAmount, + GiftPointAmount: 0, HeatValue: gift.HeatValue, GiftTypeCode: gift.GiftTypeCode, EffectiveFromMs: gift.EffectiveFromMS, From 3fe8c907fd2e1acdfe0c80448985dff911bf2e0b Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 15:07:45 +0800 Subject: [PATCH 18/28] Add agency center salary policy endpoint --- .../transport/http/httproutes/router.go | 2 + .../internal/transport/http/response_test.go | 66 +++++++++++++++++++ .../http/userapi/agency_center_handler.go | 30 +++++++++ .../transport/http/userapi/handler.go | 1 + 4 files changed, 99 insertions(+) diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index e6efa71b..4a938c0a 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -75,6 +75,7 @@ type UserHandlers struct { GetHostCenterAgency http.HandlerFunc GetHostCenterPlatformPolicy http.HandlerFunc GetAgencyCenterOverview http.HandlerFunc + GetAgencyCenterPlatformPolicy http.HandlerFunc ListAgencyCenterHosts http.HandlerFunc ListAgencyCenterApplications http.HandlerFunc ReviewAgencyCenterApplication http.HandlerFunc @@ -318,6 +319,7 @@ func (r routes) registerUserRoutes() { r.profile("/host-center/agency", http.MethodGet, h.GetHostCenterAgency) r.profile("/host-center/platform-policy", http.MethodGet, h.GetHostCenterPlatformPolicy) r.profile("/agency-center/overview", http.MethodGet, h.GetAgencyCenterOverview) + r.profile("/agency-center/platform-policy", http.MethodGet, h.GetAgencyCenterPlatformPolicy) r.profile("/agency-center/hosts", http.MethodGet, h.ListAgencyCenterHosts) r.profile("/agency-center/applications", http.MethodGet, h.ListAgencyCenterApplications) r.profile("/agency-center/applications/{application_id}/review", http.MethodPost, h.ReviewAgencyCenterApplication) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index e0cb5a10..58d0f2a0 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -3634,6 +3634,72 @@ func TestAgencyCenterOverviewUsesOwnerAgencySalaryAndPendingApplications(t *test } } +func TestAgencyCenterPlatformPolicyUsesAgencyRegion(t *testing.T) { + hostClient := &fakeUserHostClient{ + roleSummary: &userv1.UserRoleSummary{UserId: 42, IsManager: true, AgencyId: 7001}, + getAgencyResp: &userv1.GetAgencyResponse{Agency: &userv1.Agency{ + AgencyId: 7001, + OwnerUserId: 42, + RegionId: 31, + Name: "Yumi Star Agency", + Status: "active", + }}, + } + walletClient := &fakeWalletClient{ + hostSalaryPolicyResp: &walletv1.GetActiveHostSalaryPolicyResponse{ + Found: true, + Policy: &walletv1.HostSalaryPolicy{ + PolicyId: 9101, + Name: "Agency Region Policy", + RegionId: 31, + Status: "active", + SettlementMode: "half_month", + SettlementTriggerMode: "manual", + GiftCoinToDiamondRatio: "1.0000", + ResidualDiamondToUsdRate: "0.0100", + Levels: []*walletv1.HostSalaryPolicyLevel{ + {LevelNo: 1, RequiredDiamonds: 1000, HostSalaryUsdMinor: 1200, HostCoinReward: 100, AgencySalaryUsdMinor: 240, Status: "active", SortOrder: 1}, + {LevelNo: 2, RequiredDiamonds: 3000, HostSalaryUsdMinor: 3600, HostCoinReward: 300, AgencySalaryUsdMinor: 720, Status: "active", SortOrder: 2}, + }, + }, + }, + } + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetUserHostClient(hostClient) + handler.SetWalletClient(walletClient) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/agency-center/platform-policy", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-agency-policy") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + if hostClient.lastRoleSummary == nil || hostClient.lastRoleSummary.GetUserId() != 42 || hostClient.lastGetAgency == nil || hostClient.lastGetAgency.GetAgencyId() != 7001 { + t.Fatalf("agency owner resolution mismatch: role=%+v agency=%+v", hostClient.lastRoleSummary, hostClient.lastGetAgency) + } + if walletClient.lastHostSalaryPolicy == nil || walletClient.lastHostSalaryPolicy.GetRegionId() != 31 || walletClient.lastHostSalaryPolicy.GetSettlementTriggerMode() != "" || walletClient.lastHostSalaryPolicy.GetAppCode() == "" || walletClient.lastHostSalaryPolicy.GetRequestId() == "" { + t.Fatalf("agency policy request mismatch: %+v", walletClient.lastHostSalaryPolicy) + } + if walletClient.lastHostSalaryProgress != nil { + t.Fatalf("agency policy should not request host progress: %+v", walletClient.lastHostSalaryProgress) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data := response.Data.(map[string]any) + policy := data["policy"].(map[string]any) + levels := policy["levels"].([]any) + secondLevel := levels[1].(map[string]any) + if data["found"] != true || data["agency_region_id"] != float64(31) || policy["policy_id"] != "9101" || len(levels) != 2 || secondLevel["agency_salary_usd"] != 7.2 { + t.Fatalf("agency policy response mismatch: %+v", data) + } +} + func TestBDCenterOverviewUsesBDSalaryAndDirectAgencies(t *testing.T) { hostClient := &fakeUserHostClient{ bdProfile: &userv1.BDProfile{UserId: 42, Role: "bd", Status: "active", RegionId: 1001}, diff --git a/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go b/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go index 4789056e..2273bc34 100644 --- a/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/agency_center_handler.go @@ -109,6 +109,36 @@ func (h *Handler) getAgencyCenterOverview(writer http.ResponseWriter, request *h }) } +func (h *Handler) getAgencyCenterPlatformPolicy(writer http.ResponseWriter, request *http.Request) { + agency, ok := h.resolveCurrentOwnerAgency(writer, request) + if !ok { + return + } + if h.walletClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + // Agency Center 不是主播身份,不能复用 host-center 的 active host 校验;这里固定用当前 agency 的区域读取完整工资政策。 + resp, err := h.walletClient.GetActiveHostSalaryPolicy(request.Context(), &walletv1.GetActiveHostSalaryPolicyRequest{ + RequestId: httpkit.RequestIDFromContext(request.Context()), + AppCode: appcode.FromContext(request.Context()), + RegionId: agency.GetRegionId(), + SettlementTriggerMode: "", + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + // H5 需要完整政策明细;hostCenterPolicyFromProto 会保留政策元数据和所有等级行,agency 端不计算主播等级进度。 + httpkit.WriteOK(writer, request, map[string]any{ + "found": resp.GetFound(), + "agency_region_id": agency.GetRegionId(), + "policy": hostCenterPolicyFromProto(resp.GetPolicy()), + }) +} + func (h *Handler) listAgencyCenterHosts(writer http.ResponseWriter, request *http.Request) { agency, ok := h.resolveCurrentOwnerAgency(writer, request) if !ok { diff --git a/services/gateway-service/internal/transport/http/userapi/handler.go b/services/gateway-service/internal/transport/http/userapi/handler.go index b97dd841..3ab9ab2e 100644 --- a/services/gateway-service/internal/transport/http/userapi/handler.go +++ b/services/gateway-service/internal/transport/http/userapi/handler.go @@ -59,6 +59,7 @@ func (h *Handler) UserHandlers() httproutes.UserHandlers { GetHostCenterAgency: h.getHostCenterAgency, GetHostCenterPlatformPolicy: h.getHostCenterPlatformPolicy, GetAgencyCenterOverview: h.getAgencyCenterOverview, + GetAgencyCenterPlatformPolicy: h.getAgencyCenterPlatformPolicy, ListAgencyCenterHosts: h.listAgencyCenterHosts, ListAgencyCenterApplications: h.listAgencyCenterApplications, ReviewAgencyCenterApplication: h.reviewAgencyCenterApplication, From 1cffc335cebabff67266d9b8389cbe5a6bf47405 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 15:23:51 +0800 Subject: [PATCH 19/28] Fix gift list type filtering --- .../internal/service/wallet/service_test.go | 120 ++++++++++++++++++ .../storage/mysql/resource_repository.go | 5 +- 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 7f7864d4..994eaf00 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -2506,6 +2506,126 @@ func TestGiftConfigRegionFilter(t *testing.T) { } } +// TestListGiftConfigsWithoutTypeFilterIncludesLuckyTypes 验证礼物面板预加载全部礼物时不会被空类型过滤误收窄到普通礼物。 +func TestListGiftConfigsWithoutTypeFilterIncludesLuckyTypes(t *testing.T) { + repository := mysqltest.NewRepository(t) + svc := walletservice.New(repository) + ctx := context.Background() + + normalResource, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ + ResourceCode: "gift_all_normal", + ResourceType: resourcedomain.TypeGift, + Name: "All Normal", + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategyIncreaseQuantity, + UsageScopes: []string{"gift"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create normal gift resource failed: %v", err) + } + luckyResource, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ + ResourceCode: "gift_all_lucky", + ResourceType: resourcedomain.TypeGift, + Name: "All Lucky", + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategyIncreaseQuantity, + UsageScopes: []string{"gift"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create lucky gift resource failed: %v", err) + } + superLuckyResource, err := svc.CreateResource(ctx, resourcedomain.ResourceCommand{ + ResourceCode: "gift_all_super_lucky", + ResourceType: resourcedomain.TypeGift, + Name: "All Super Lucky", + Status: resourcedomain.StatusActive, + Grantable: true, + GrantStrategy: resourcedomain.GrantStrategyIncreaseQuantity, + UsageScopes: []string{"gift"}, + OperatorUserID: 90001, + }) + if err != nil { + t.Fatalf("create super lucky gift resource failed: %v", err) + } + commands := []resourcedomain.GiftConfigCommand{ + { + GiftID: "all-normal", + ResourceID: normalResource.ResourceID, + Status: resourcedomain.StatusActive, + Name: "All Normal", + PriceVersion: "v1", + CoinPrice: 100, + HeatValue: 100, + OperatorUserID: 90001, + RegionIDs: []int64{0}, + }, + { + GiftID: "all-lucky", + ResourceID: luckyResource.ResourceID, + Status: resourcedomain.StatusActive, + Name: "All Lucky", + GiftTypeCode: resourcedomain.GiftTypeLucky, + PriceVersion: "v1", + CoinPrice: 200, + HeatValue: 200, + OperatorUserID: 90001, + RegionIDs: []int64{0}, + }, + { + GiftID: "all-super-lucky", + ResourceID: superLuckyResource.ResourceID, + Status: resourcedomain.StatusActive, + Name: "All Super Lucky", + GiftTypeCode: resourcedomain.GiftTypeSuperLucky, + PriceVersion: "v1", + CoinPrice: 300, + HeatValue: 300, + OperatorUserID: 90001, + RegionIDs: []int64{0}, + }, + } + for _, command := range commands { + if _, err := svc.CreateGiftConfig(ctx, command); err != nil { + t.Fatalf("create gift config %s failed: %v", command.GiftID, err) + } + } + + // 空 gift_type_code 表示“不按类型过滤”,gateway 的 gift-tabs 会依赖这次查询一次性拿到所有礼物类型。 + items, total, err := svc.ListGiftConfigs(ctx, resourcedomain.ListGiftConfigsQuery{ + ActiveOnly: true, + FilterRegion: true, + RegionID: 0, + Page: 1, + PageSize: 10, + }) + if err != nil { + t.Fatalf("list all gift configs failed: %v", err) + } + if total != 3 || !giftIDsContain(items, "all-normal") || !giftIDsContain(items, "all-lucky") || !giftIDsContain(items, "all-super-lucky") { + t.Fatalf("all gift type list mismatch total=%d items=%+v", total, items) + } + + // 显式传入 lucky 时仍保留类型过滤能力,避免修复全部礼物预加载时破坏后台按类型筛选。 + luckyItems, luckyTotal, err := svc.ListGiftConfigs(ctx, resourcedomain.ListGiftConfigsQuery{ + GiftTypeCode: resourcedomain.GiftTypeLucky, + ActiveOnly: true, + FilterRegion: true, + RegionID: 0, + Page: 1, + PageSize: 10, + }) + if err != nil { + t.Fatalf("list lucky gift configs failed: %v", err) + } + if luckyTotal != 1 || !giftIDsContain(luckyItems, "all-lucky") || giftIDsContain(luckyItems, "all-normal") || giftIDsContain(luckyItems, "all-super-lucky") { + t.Fatalf("lucky gift type filter mismatch total=%d items=%+v", luckyTotal, luckyItems) + } +} + // TestGrantResourceGroupExpandsWalletAssetAndEntitlement 验证资源组赠送会原子展开钱包资产入账和非钱包权益。 func TestGrantResourceGroupExpandsWalletAssetAndEntitlement(t *testing.T) { repository := mysqltest.NewRepository(t) diff --git a/services/wallet-service/internal/storage/mysql/resource_repository.go b/services/wallet-service/internal/storage/mysql/resource_repository.go index 521972b1..1b2d18b5 100644 --- a/services/wallet-service/internal/storage/mysql/resource_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_repository.go @@ -2913,7 +2913,10 @@ func normalizeResourceGroupListQuery(query resourcedomain.ListResourceGroupsQuer func normalizeGiftConfigListQuery(query resourcedomain.ListGiftConfigsQuery) resourcedomain.ListGiftConfigsQuery { query.Status = strings.ToLower(strings.TrimSpace(query.Status)) query.Keyword = strings.TrimSpace(query.Keyword) - query.GiftTypeCode = resourcedomain.NormalizeGiftTypeCode(query.GiftTypeCode) + // 列表查询的 gift_type_code 是可选过滤条件;空值必须保持为空,避免礼物面板加载全部礼物时被默认收窄到 normal。 + if strings.TrimSpace(query.GiftTypeCode) != "" { + query.GiftTypeCode = resourcedomain.NormalizeGiftTypeCode(query.GiftTypeCode) + } query.Page, query.PageSize = normalizePage(query.Page, query.PageSize) return query } From 9a89e76a113b268c453ae30486887aeed9716d38 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 18:27:21 +0800 Subject: [PATCH 20/28] Add BD leader admin alias support --- .../internal/integration/userclient/client.go | 1 + .../admin/internal/modules/hostorg/handler.go | 2 +- .../admin/internal/modules/hostorg/reader.go | 83 +++++++++++++++++++ .../admin/internal/modules/hostorg/request.go | 9 +- .../admin/internal/modules/hostorg/service.go | 16 +++- .../034_bd_leader_position_alias.sql | 13 +++ .../internal/appconfig/mysql.go | 80 ++++++++++++++++-- .../http/appapi/app_config_handler.go | 6 +- .../internal/transport/http/appapi/handler.go | 2 +- .../internal/transport/http/middleware.go | 30 ++++++- .../internal/transport/http/response_test.go | 39 +++++++++ .../internal/transport/http/router.go | 4 +- 12 files changed, 265 insertions(+), 20 deletions(-) create mode 100644 server/admin/migrations/034_bd_leader_position_alias.sql diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 7c348822..49f0ca71 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -347,6 +347,7 @@ type BDProfile struct { Role string `json:"role"` RegionID int64 `json:"regionId"` ParentLeaderUserID int64 `json:"parentLeaderUserId,string"` + PositionAlias string `json:"positionAlias"` Status string `json:"status"` CreatedByUserID int64 `json:"createdByUserId"` CreatedAtMs int64 `json:"createdAtMs"` diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index 1558403d..e8c5f702 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -101,7 +101,7 @@ func (h *Handler) CreateBDLeader(c *gin.Context) { return } writeHostOrgAuditLog(c, h.audit, "create-bd-leader", "bd_profiles", profile.UserID, - fmt.Sprintf("command_id=%s user_id=%d region_id=%d reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, req.RegionID, strings.TrimSpace(req.Reason))) + fmt.Sprintf("command_id=%s user_id=%d region_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, req.RegionID, strings.TrimSpace(req.PositionAlias), strings.TrimSpace(req.Reason))) response.Created(c, profile) } diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index b164fc0f..e1d536d1 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -146,6 +146,11 @@ func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role strin if err := r.fillBDProfileCreators(ctx, items); err != nil { return nil, 0, err } + if role == "bd_leader" { + if err := r.fillBDLeaderPositionAliases(ctx, appCode, items); err != nil { + return nil, 0, err + } + } return items, total, nil } @@ -206,6 +211,78 @@ func (r *Reader) fillBDProfileCreators(ctx context.Context, items []*userclient. return nil } +func (r *Reader) fillBDLeaderPositionAliases(ctx context.Context, appCode string, items []*userclient.BDProfile) error { + if r == nil || r.adminDB == nil || len(items) == 0 { + return nil + } + ids := make([]any, 0, len(items)) + for _, item := range items { + if item.UserID > 0 { + ids = append(ids, item.UserID) + } + } + if len(ids) == 0 { + return nil + } + args := append([]any{appCode}, ids...) + rows, err := r.adminDB.QueryContext(ctx, ` + SELECT user_id, position_alias + FROM admin_bd_leader_position_aliases + WHERE app_code = ? AND user_id IN (`+sqlPlaceholders(len(ids))+`) + `, args...) + if err != nil { + return err + } + defer rows.Close() + + aliases := make(map[int64]string, len(ids)) + for rows.Next() { + var userID int64 + var alias string + if err := rows.Scan(&userID, &alias); err != nil { + return err + } + aliases[userID] = strings.TrimSpace(alias) + } + if err := rows.Err(); err != nil { + return err + } + for _, item := range items { + item.PositionAlias = aliases[item.UserID] + } + return nil +} + +func (r *Reader) SaveBDLeaderPositionAlias(ctx context.Context, userID int64, actorID int64, alias string) error { + if r == nil || r.adminDB == nil { + return fmt.Errorf("admin mysql is not configured") + } + if userID <= 0 { + return fmt.Errorf("user_id is required") + } + appCode := appctx.FromContext(ctx) + positionAlias := strings.TrimSpace(alias) + if positionAlias == "" { + // 空别名表示恢复 H5 配置表里的默认 admin 展示名,删除行比保留空值更清晰。 + _, err := r.adminDB.ExecContext(ctx, ` + DELETE FROM admin_bd_leader_position_aliases + WHERE app_code = ? AND user_id = ? + `, appCode, userID) + return err + } + nowMs := time.Now().UnixMilli() + _, err := r.adminDB.ExecContext(ctx, ` + INSERT INTO admin_bd_leader_position_aliases ( + app_code, user_id, position_alias, created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + position_alias = VALUES(position_alias), + updated_by_admin_id = VALUES(updated_by_admin_id), + updated_at_ms = VALUES(updated_at_ms) + `, appCode, userID, positionAlias, actorID, actorID, nowMs, nowMs) + return err +} + func (r *Reader) DeleteBDLeader(ctx context.Context, userID int64) (*userclient.BDProfile, error) { if r == nil || r.db == nil { return nil, errUserDBNotConfigured() @@ -247,6 +324,12 @@ func (r *Reader) DeleteBDLeader(ctx context.Context, userID int64) (*userclient. if affected == 0 { return nil, fmt.Errorf("bd leader not found") } + if r.adminDB != nil { + _, _ = r.adminDB.ExecContext(ctx, ` + DELETE FROM admin_bd_leader_position_aliases + WHERE app_code = ? AND user_id = ? + `, appCode, userID) + } return item, nil } diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index b142b65c..1373b5af 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -14,10 +14,11 @@ type listQuery struct { } type createBDLeaderRequest struct { - CommandID string `json:"commandId" binding:"required"` - TargetUserID int64 `json:"targetUserId" binding:"required"` - RegionID int64 `json:"regionId" binding:"required"` - Reason string `json:"reason"` + CommandID string `json:"commandId" binding:"required"` + TargetUserID int64 `json:"targetUserId" binding:"required"` + RegionID int64 `json:"regionId" binding:"required"` + PositionAlias string `json:"positionAlias"` + Reason string `json:"reason"` } type createBDRequest struct { diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index 10dbab77..df0abf5e 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -18,6 +18,7 @@ const ( coinSellerStockTypePurchase = "usdt_purchase" coinSellerStockTypeCompensate = "coin_compensation" paidCurrencyUSDT = "USDT" + bdLeaderPositionAliasMaxRunes = 64 ) type Service struct { @@ -118,8 +119,12 @@ func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID s if err != nil { return nil, err } + positionAlias := strings.TrimSpace(req.PositionAlias) + if len([]rune(positionAlias)) > bdLeaderPositionAliasMaxRunes { + return nil, fmt.Errorf("position_alias must not exceed %d characters", bdLeaderPositionAliasMaxRunes) + } // BD Leader 创建时后台选择的区域是显式运营归属,由 user-service 在同一事务里更新 users.region_id 和 bd_profiles.region_id。 - return s.userClient.CreateBDLeader(ctx, userclient.CreateBDLeaderRequest{ + profile, err := s.userClient.CreateBDLeader(ctx, userclient.CreateBDLeaderRequest{ RequestID: requestID, Caller: "hyapp-admin-server", CommandID: strings.TrimSpace(req.CommandID), @@ -128,6 +133,15 @@ func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID s TargetUserID: targetUserID, Reason: strings.TrimSpace(req.Reason), }) + if err != nil { + return nil, err + } + // 职位别名只影响 Flutter H5 配置里 admin 入口的展示名,不参与 user-service 的身份创建事务,避免把后台展示字段扩散到 App 身份主协议。 + if err := s.reader.SaveBDLeaderPositionAlias(ctx, targetUserID, actorID, positionAlias); err != nil { + return nil, err + } + profile.PositionAlias = positionAlias + return profile, nil } func (s *Service) CreateBD(ctx context.Context, actorID int64, requestID string, req createBDRequest) (*userclient.BDProfile, error) { diff --git a/server/admin/migrations/034_bd_leader_position_alias.sql b/server/admin/migrations/034_bd_leader_position_alias.sql new file mode 100644 index 00000000..69c9b430 --- /dev/null +++ b/server/admin/migrations/034_bd_leader_position_alias.sql @@ -0,0 +1,13 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS admin_bd_leader_position_aliases ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + user_id BIGINT NOT NULL COMMENT 'BD Leader 用户 ID', + position_alias VARCHAR(64) NOT NULL DEFAULT '' COMMENT '职位别名,用于覆盖 App H5 admin 配置展示名', + created_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建管理员 ID', + updated_by_admin_id BIGINT UNSIGNED 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, user_id), + KEY idx_admin_bd_leader_position_alias_updated (app_code, updated_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BD Leader 职位别名配置表'; diff --git a/services/gateway-service/internal/appconfig/mysql.go b/services/gateway-service/internal/appconfig/mysql.go index 56819bbb..153a7b5a 100644 --- a/services/gateway-service/internal/appconfig/mysql.go +++ b/services/gateway-service/internal/appconfig/mysql.go @@ -5,15 +5,21 @@ import ( "context" "database/sql" "errors" + "strconv" "strings" "time" - _ "github.com/go-sql-driver/mysql" + mysqlDriver "github.com/go-sql-driver/mysql" ) const h5LinkGroup = "h5-links" const listH5LinksSQL = "SELECT `key`, COALESCE(description, ''), COALESCE(value, ''), updated_at_ms FROM admin_app_configs WHERE `group` = ? ORDER BY `key` ASC" +const bdLeaderPositionAliasSQL = ` + SELECT position_alias + FROM admin_bd_leader_position_aliases + WHERE app_code = ? AND user_id = ? + LIMIT 1` const listExploreTabsSQL = ` SELECT id, app_code, tab, h5_url, enabled, sort_order, updated_at_ms FROM admin_app_explore_tabs @@ -44,6 +50,12 @@ type H5Link struct { UpdatedAtMs int64 `json:"updated_at_ms"` } +// H5LinkQuery 是 H5 入口配置的可选用户态筛选条件。 +type H5LinkQuery struct { + AppCode string + UserID int64 +} + // ExploreTab 是后台 APP配置/Explore配置 中启用的 H5 tab。 type ExploreTab struct { ID uint `json:"id"` @@ -105,7 +117,7 @@ type Version struct { // Reader 是 HTTP 层读取 H5 配置的最小依赖。 type Reader interface { - ListH5Links(ctx context.Context) ([]H5Link, error) + ListH5Links(ctx context.Context, query H5LinkQuery) ([]H5Link, error) ListExploreTabs(ctx context.Context, appCode string) ([]ExploreTab, error) ListBanners(ctx context.Context, query BannerQuery) ([]Banner, error) LatestVersion(ctx context.Context, query VersionQuery) (Version, error) @@ -136,7 +148,7 @@ func (r *MySQLReader) Close() error { } // ListH5Links 返回后台动态维护的 H5 入口集合。 -func (r *MySQLReader) ListH5Links(ctx context.Context) ([]H5Link, error) { +func (r *MySQLReader) ListH5Links(ctx context.Context, query H5LinkQuery) ([]H5Link, error) { if r == nil || r.db == nil { return nil, errors.New("app config reader is not configured") } @@ -164,9 +176,33 @@ func (r *MySQLReader) ListH5Links(ctx context.Context) ([]H5Link, error) { if err := rows.Err(); err != nil { return nil, err } + if alias, err := r.bdLeaderPositionAlias(ctx, query); err != nil { + return nil, err + } else if alias != "" { + applyAdminH5LinkAlias(items, alias) + } return items, nil } +func (r *MySQLReader) bdLeaderPositionAlias(ctx context.Context, query H5LinkQuery) (string, error) { + if query.UserID <= 0 { + return "", nil + } + var alias string + err := r.db.QueryRowContext(ctx, bdLeaderPositionAliasSQL, normalizeAppCode(query.AppCode), query.UserID).Scan(&alias) + if errors.Is(err, sql.ErrNoRows) { + return "", nil + } + if isMissingTableError(err) { + // gateway 读的是 admin 库;迁移未发布前保持 H5 配置原始返回,不让可选别名阻断老环境。 + return "", nil + } + if err != nil { + return "", err + } + return strings.TrimSpace(alias), nil +} + // ListExploreTabs 返回当前 App 启用的 Explore H5 tabs;后台关闭的 tab 不下发给客户端。 func (r *MySQLReader) ListExploreTabs(ctx context.Context, appCode string) ([]ExploreTab, error) { if r == nil || r.db == nil { @@ -276,21 +312,25 @@ func (r *MySQLReader) LatestVersion(ctx context.Context, query VersionQuery) (Ve // StaticReader 给测试和临时环境提供内存版 H5 配置读取。 type StaticReader struct { - Links []H5Link - ExploreTabs []ExploreTab - Banners []Banner - Version Version - Err error + Links []H5Link + ExploreTabs []ExploreTab + Banners []Banner + Version Version + Err error + PositionAliases map[string]string } // ListH5Links 返回预置 H5 配置。 -func (r StaticReader) ListH5Links(context.Context) ([]H5Link, error) { +func (r StaticReader) ListH5Links(_ context.Context, query H5LinkQuery) ([]H5Link, error) { if r.Err != nil { return nil, r.Err } out := make([]H5Link, len(r.Links)) copy(out, r.Links) + if alias := strings.TrimSpace(r.PositionAliases[bdLeaderPositionAliasKey(query.AppCode, query.UserID)]); alias != "" { + applyAdminH5LinkAlias(out, alias) + } return out, nil } @@ -352,6 +392,28 @@ func normalizeCountry(value string) string { return strings.ToUpper(strings.TrimSpace(value)) } +func applyAdminH5LinkAlias(items []H5Link, alias string) { + alias = strings.TrimSpace(alias) + if alias == "" { + return + } + for index := range items { + if strings.EqualFold(strings.TrimSpace(items[index].Key), "admin") { + // admin 入口只覆盖展示名,key 和 URL 仍来自后台 H5 配置,保证 Flutter 路由识别不变。 + items[index].Label = alias + } + } +} + +func bdLeaderPositionAliasKey(appCode string, userID int64) string { + return normalizeAppCode(appCode) + ":" + strconv.FormatInt(userID, 10) +} + +func isMissingTableError(err error) bool { + var mysqlErr *mysqlDriver.MySQLError + return errors.As(err, &mysqlErr) && mysqlErr.Number == 1146 +} + // NormalizeBannerDisplayScope 统一 App 和后台约定的显示范围枚举。 func NormalizeBannerDisplayScope(value string) string { value = strings.ToLower(strings.TrimSpace(value)) diff --git a/services/gateway-service/internal/transport/http/appapi/app_config_handler.go b/services/gateway-service/internal/transport/http/appapi/app_config_handler.go index cf92c47d..aeba5dda 100644 --- a/services/gateway-service/internal/transport/http/appapi/app_config_handler.go +++ b/services/gateway-service/internal/transport/http/appapi/app_config_handler.go @@ -8,6 +8,7 @@ import ( "hyapp/pkg/appcode" "hyapp/services/gateway-service/internal/appconfig" + "hyapp/services/gateway-service/internal/auth" "hyapp/services/gateway-service/internal/transport/http/httpkit" ) @@ -85,7 +86,10 @@ func (h *Handler) listH5Links(writer http.ResponseWriter, request *http.Request) return } - items, err := h.appConfigReader.ListH5Links(request.Context()) + items, err := h.appConfigReader.ListH5Links(request.Context(), appconfig.H5LinkQuery{ + AppCode: appcode.FromContext(request.Context()), + UserID: auth.UserIDFromContext(request.Context()), + }) if err != nil { // 配置读取失败属于服务端依赖异常,客户端只需要根据 request_id 排查。 httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") diff --git a/services/gateway-service/internal/transport/http/appapi/handler.go b/services/gateway-service/internal/transport/http/appapi/handler.go index 1f8e6796..ec8643a3 100644 --- a/services/gateway-service/internal/transport/http/appapi/handler.go +++ b/services/gateway-service/internal/transport/http/appapi/handler.go @@ -11,7 +11,7 @@ import ( // ConfigReader 是 gateway 对后台 App 配置的只读依赖。 type ConfigReader interface { - ListH5Links(ctx context.Context) ([]appconfig.H5Link, error) + ListH5Links(ctx context.Context, query appconfig.H5LinkQuery) ([]appconfig.H5Link, error) ListExploreTabs(ctx context.Context, appCode string) ([]appconfig.ExploreTab, error) ListBanners(ctx context.Context, query appconfig.BannerQuery) ([]appconfig.Banner, error) LatestVersion(ctx context.Context, query appconfig.VersionQuery) (appconfig.Version, error) diff --git a/services/gateway-service/internal/transport/http/middleware.go b/services/gateway-service/internal/transport/http/middleware.go index 233f35ae..f0c19234 100644 --- a/services/gateway-service/internal/transport/http/middleware.go +++ b/services/gateway-service/internal/transport/http/middleware.go @@ -26,8 +26,8 @@ func (h *Handler) profileAPIHandler(jwtVerifier *auth.Verifier, next http.Handle } // publicAPIHandler 包装只需要 app 解析的公开 API;登录/注册会用解析结果创建对应 App 的用户。 -func (h *Handler) publicAPIHandler(next http.HandlerFunc) http.Handler { - return httpkit.WithRequestID(withAccessLog(h.withResolvedApp(next))) +func (h *Handler) publicAPIHandler(jwtVerifier *auth.Verifier, next http.HandlerFunc) http.Handler { + return httpkit.WithRequestID(withAccessLog(h.withResolvedApp(h.withOptionalAuth(jwtVerifier, next)))) } // withAccessLog 统一记录 gateway 业务 API 的请求体、响应体、状态码和耗时。 @@ -63,6 +63,32 @@ func (h *Handler) withAuth(jwtVerifier *auth.Verifier, next http.HandlerFunc) ht }) } +func (h *Handler) withOptionalAuth(jwtVerifier *auth.Verifier, next http.HandlerFunc) http.Handler { + return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { + header := strings.TrimSpace(request.Header.Get("Authorization")) + if header == "" || jwtVerifier == nil { + next.ServeHTTP(writer, request) + return + } + claims, err := jwtVerifier.Verify(header) + if err != nil || strings.TrimSpace(claims.SessionID) == "" { + // 公开接口不能因为旧客户端带了过期或残缺 token 就失败;无效 token 只是不参与用户态配置覆盖。 + next.ServeHTTP(writer, request) + return + } + ctx := auth.WithClaims(request.Context(), claims) + revoked, err := h.revokedSession(ctx, claims.AppCode, claims.SessionID) + if err != nil { + logx.Warn(ctx, "optional_session_denylist_read_failed", slog.String("component", "gateway_public_auth"), slog.String("session_id", claims.SessionID), slog.String("error", err.Error())) + } + if revoked { + next.ServeHTTP(writer, request) + return + } + next.ServeHTTP(writer, request.WithContext(ctx)) + }) +} + func (h *Handler) revokedSession(ctx context.Context, appCode string, sessionID string) (bool, error) { if h.loginRiskCache == nil { return false, nil diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 58d0f2a0..2fa2293c 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -2995,6 +2995,45 @@ func TestListH5LinksReturnsAdminAppConfig(t *testing.T) { } } +func TestListH5LinksUsesBDLeaderPositionAliasForAdminItem(t *testing.T) { + handler := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}) + handler.SetAppConfigReader(appconfig.StaticReader{ + Links: []appconfig.H5Link{ + {Key: "admin", Label: "Admin Center", URL: "https://h5.example.com/admin", UpdatedAtMs: 1700000000000}, + {Key: "bd", Label: "BD Center", URL: "https://h5.example.com/bd", UpdatedAtMs: 1700000001000}, + }, + PositionAliases: map[string]string{"lalu:42": "Senior Admin"}, + }) + router := handler.Routes(auth.NewVerifier("secret")) + request := httptest.NewRequest(http.MethodGet, "/api/v1/app/h5-links", nil) + request.Header.Set("Authorization", "Bearer "+signGatewayToken(t, "secret", 42)) + request.Header.Set("X-Request-ID", "req-h5-links-alias") + request.Header.Set("X-App-Package", "com.org.laluparty") + recorder := httptest.NewRecorder() + + router.ServeHTTP(recorder, request) + + if recorder.Code != http.StatusOK { + t.Fatalf("status mismatch: got %d body=%s", recorder.Code, recorder.Body.String()) + } + var response httpkit.ResponseEnvelope + if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil { + t.Fatalf("decode response failed: %v", err) + } + data, ok := response.Data.(map[string]any) + if response.Code != httpkit.CodeOK || !ok { + t.Fatalf("unexpected envelope: %+v", response) + } + items, ok := data["items"].([]any) + if !ok || len(items) != 2 { + t.Fatalf("h5 items shape mismatch: %+v", data) + } + first, ok := items[0].(map[string]any) + if !ok || first["key"] != "admin" || first["label"] != "Senior Admin" || first["url"] != "https://h5.example.com/admin" { + t.Fatalf("admin h5 alias mismatch: %+v", first) + } +} + func TestListH5LinksRequiresConfigReader(t *testing.T) { router := NewHandlerWithClients(&fakeRoomClient{}, nil, nil, &fakeUserProfileClient{}).Routes(auth.NewVerifier("secret")) request := httptest.NewRequest(http.MethodGet, "/api/v1/app/h5-links", nil) diff --git a/services/gateway-service/internal/transport/http/router.go b/services/gateway-service/internal/transport/http/router.go index 2150fac0..bc0a7ad7 100644 --- a/services/gateway-service/internal/transport/http/router.go +++ b/services/gateway-service/internal/transport/http/router.go @@ -119,7 +119,9 @@ func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler { userHandlers.UnequipMyResource = resourceAPI.UnequipMyResource return httproutes.New(httproutes.Config{ - PublicWrap: h.publicAPIHandler, + PublicWrap: func(handler http.HandlerFunc) http.Handler { + return h.publicAPIHandler(jwtVerifier, handler) + }, AuthWrap: func(handler http.HandlerFunc) http.Handler { return h.apiHandler(jwtVerifier, handler) }, From 3417ee44efcc712d9203dc8e33abd251eb93bd27 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 19:22:39 +0800 Subject: [PATCH 21/28] Add room rocket services and coin seller ledger --- AGENTS.md | 3 +- README.md | 10 +- api/proto/events/room/v1/events.pb.go | 430 +-- api/proto/events/room/v1/events.proto | 53 +- api/proto/room/v1/room.pb.go | 2295 +++++++++-------- api/proto/room/v1/room.proto | 119 +- api/proto/room/v1/room_grpc.pb.go | 178 +- docs/IM全局与区域广播架构.md | 22 +- ...宝箱Flutter对接.md => 语音房火箭Flutter对接.md} | 152 +- docs/定时任务服务架构.md | 6 +- docs/房间Outbox补偿开发.md | 22 +- docs/语音房功能清单.md | 2 +- ...房宝箱功能架构.md => 语音房火箭功能架构.md} | 162 +- pkg/roommq/messages.go | 38 +- pkg/roommq/messages_test.go | 26 +- server/admin/cmd/server/main.go | 4 +- .../internal/integration/roomclient/client.go | 168 +- .../admin/internal/modules/coinledger/dto.go | 17 + .../internal/modules/coinledger/handler.go | 59 + .../internal/modules/coinledger/request.go | 10 + .../internal/modules/coinledger/routes.go | 1 + .../internal/modules/coinledger/service.go | 303 ++- .../modules/coinledger/service_test.go | 55 + .../admin/internal/modules/hostorg/handler.go | 20 + .../admin/internal/modules/hostorg/reader.go | 59 + .../admin/internal/modules/hostorg/request.go | 6 + .../admin/internal/modules/hostorg/routes.go | 1 + .../admin/internal/modules/hostorg/service.go | 34 +- .../{roomtreasure => roomrocket}/handler.go | 16 +- .../internal/modules/roomrocket/routes.go | 16 + .../internal/modules/roomrocket/service.go | 431 ++++ .../modules/roomrocket/service_test.go | 79 + .../internal/modules/roomtreasure/routes.go | 16 - .../internal/modules/roomtreasure/service.go | 431 ---- .../modules/roomtreasure/service_test.go | 79 - server/admin/internal/repository/seed.go | 31 +- server/admin/internal/router/router.go | 6 +- .../018_room_treasure_navigation.sql | 25 +- .../035_coin_seller_ledger_navigation.sql | 56 + .../internal/domain/broadcast/broadcast.go | 6 +- .../internal/service/broadcast/service.go | 194 +- .../internal/client/room_client.go | 6 +- .../user_leaderboard_handler_test.go | 4 +- .../transport/http/httproutes/router.go | 4 +- .../internal/transport/http/response_test.go | 20 +- .../transport/http/roomapi/handler.go | 2 +- .../transport/http/roomapi/room_handler.go | 8 +- .../transport/http/roomapi/room_view.go | 196 +- .../room-service/configs/config.docker.yaml | 10 +- .../configs/config.tencent.example.yaml | 12 +- services/room-service/configs/config.yaml | 12 +- .../deploy/mysql/initdb/001_room_service.sql | 41 +- services/room-service/internal/app/app.go | 32 +- .../room-service/internal/config/config.go | 40 +- .../internal/config/config_test.go | 6 +- .../internal/integration/clients.go | 28 +- .../internal/integration/rocketmq_outbox.go | 42 +- .../internal/integration/tencent_im.go | 84 +- .../internal/room/command/command.go | 154 +- .../internal/room/service/admin_rocket.go | 154 ++ .../internal/room/service/admin_treasure.go | 154 -- .../internal/room/service/gift.go | 14 +- .../room/service/gift_leaderboard_test.go | 8 +- .../internal/room/service/kick_test.go | 4 +- .../internal/room/service/lucky_gift_test.go | 14 +- .../internal/room/service/mic_test.go | 26 +- .../room/service/online_users_test.go | 26 +- .../internal/room/service/outbox_worker.go | 4 +- .../internal/room/service/recovery.go | 90 +- .../internal/room/service/repository.go | 52 +- .../internal/room/service/room_rocket.go | 1075 ++++++++ .../internal/room/service/room_rocket_mq.go | 112 + ...m_treasure_test.go => room_rocket_test.go} | 324 +-- .../internal/room/service/room_treasure.go | 933 ------- .../internal/room/service/room_treasure_mq.go | 111 - .../internal/room/service/service.go | 10 +- .../room-service/internal/room/state/state.go | 205 +- .../internal/storage/mysql/repository.go | 80 +- .../internal/transport/grpc/server.go | 20 +- 79 files changed, 5485 insertions(+), 4273 deletions(-) rename docs/flutter对接/{语音房宝箱Flutter对接.md => 语音房火箭Flutter对接.md} (76%) rename docs/{语音房宝箱功能架构.md => 语音房火箭功能架构.md} (64%) rename server/admin/internal/modules/{roomtreasure => roomrocket}/handler.go (63%) create mode 100644 server/admin/internal/modules/roomrocket/routes.go create mode 100644 server/admin/internal/modules/roomrocket/service.go create mode 100644 server/admin/internal/modules/roomrocket/service_test.go delete mode 100644 server/admin/internal/modules/roomtreasure/routes.go delete mode 100644 server/admin/internal/modules/roomtreasure/service.go delete mode 100644 server/admin/internal/modules/roomtreasure/service_test.go create mode 100644 server/admin/migrations/035_coin_seller_ledger_navigation.sql create mode 100644 services/room-service/internal/room/service/admin_rocket.go delete mode 100644 services/room-service/internal/room/service/admin_treasure.go create mode 100644 services/room-service/internal/room/service/room_rocket.go create mode 100644 services/room-service/internal/room/service/room_rocket_mq.go rename services/room-service/internal/room/service/{room_treasure_test.go => room_rocket_test.go} (53%) delete mode 100644 services/room-service/internal/room/service/room_treasure.go delete mode 100644 services/room-service/internal/room/service/room_treasure_mq.go diff --git a/AGENTS.md b/AGENTS.md index 4d1cff2b..447b7193 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ ## Non-negotiables -0. 任何开发,不需要历史兼容,目前只是在开发阶段 + 1. 写代码不要猜。先读当前实现、接口、配置和测试,再改。 2. 不写流水账。文档、注释和总结都要解释边界、决策和可执行动作。 3. 前端或客户端改动不要添加无意义描述文案。界面文字必须服务真实操作或状态。 @@ -10,6 +10,7 @@ 5. 不把连接态塞进 `room-service`。客户端长连接和消息投递属于腾讯云 IM。 6. 代码永远保持高密度注释 7. 写代码的时候碰到为提交修改不用关心,只去做自己的 +8. 注意关心代码历史兼容问题 ## Architecture Boundaries diff --git a/README.md b/README.md index 182ce8f3..e0aa3c94 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,6 @@ HY Voice Room 是语音房后端 monorepo。当前架构不再自研 IM 长连 核心边界: -任何开发,不需要历史兼容,目前只是在开发阶段 - - `gateway-service` 是客户端 HTTP JSON 入口,负责鉴权、协议转换、签发腾讯云 IM UserSig,以及调用内部 gRPC 服务。 - `room-service` 是房间业务状态 owner,负责 Room Cell、麦位、房间 presence、本地礼物榜、送礼落房间、语音房宝箱、snapshot、command log、outbox、Redis lease、RocketMQ room outbox relay,以及腾讯云 IM 群组/系统消息桥接。 - `wallet-service` 当前提供 `DebitGift` 送礼扣费语义,余额、流水和幂等记录落 MySQL;`room-service` 的 `SendGift` 同步调用它。 @@ -31,11 +29,15 @@ HY Voice Room 是语音房后端 monorepo。当前架构不再自研 IM 长连 ## Time Model -项目全局时间模型固定为 UTC + epoch milliseconds: +项目全局时间模型固定为 UTC + epoch milliseconds。除客户端展示外,App 后端所有按天、按周、按月归档或结算的业务口径都按 UTC,不按中国时区、服务器本地时区、用户设备时区或 IP 推断时区切分。 - 跨服务、数据库和 HTTP/gRPC 响应里的业务时间统一使用 Unix epoch milliseconds,字段名保持 `*_ms`,例如 `created_at_ms`、`expire_at_ms`、`start_at_ms`、`end_at_ms`、`next_refresh_at_ms`。 -- 后端业务自然日统一按 UTC 切日。每日任务的 `task_day` 是 UTC `YYYY-MM-DD`,`next_refresh_at_ms` 是下一次 UTC 00:00:00 的毫秒时间戳。 +- 后端业务自然日统一按 UTC 00:00:00 切日。`task_day`、`reward_day`、`checkin_day`、`stat_day`、`budget_day` 都是 UTC `YYYY-MM-DD`;`next_refresh_at_ms` 是下一次 UTC 00:00:00 的毫秒时间戳。 +- App 每日任务和七日签到按 UTC 日刷新。任务事件归属到 `occurred_at_ms` 所在 UTC 日;七日签到连续性只比较今天和昨天的 UTC 日期。 +- 日榜、周榜、月榜按 UTC 周期计算。`today/day/daily` 是 UTC 当天,`week/weekly` 从 UTC 周一 00:00 开始,`month/monthly` 从 UTC 月初 00:00 开始;后台用户送礼榜按 `[周期开始, 当前 UTC 时间)` 查询,房间礼物榜 Redis key 也按 UTC 周期开始时间生成。 - 统计和账务时间范围统一使用 `[start_ms, end_ms)`,也就是包含开始、不包含结束。查询“昨天充值多少”时,调用方必须先把“昨天”转换成明确的 UTC 毫秒范围,再交给后端查询。 +- 定时任务由 `cron-service` 按 `interval` 轮询,不使用本地时区表达“几点运行”。任务运行记录、lease 和传给 owner service 的 `now_ms` 都是 UTC epoch milliseconds。 +- 工资和结算周期按 UTC 月锚定。主播工资周期键 `cycle_key` 是 UTC `YYYY-MM`;主播日结、半月结和月底清算由 cron 触发后在 `wallet-service` 内按这个周期键幂等结算。团队 BD/Admin 自动结算在后台按 UTC 每月 5 日判断,结算上一个 UTC 自然月。 - MySQL DSN 必须使用 `loc=UTC`。Docker 环境设置 `TZ=UTC`,MySQL 使用 `--default-time-zone=+00:00`,避免依赖服务器所在地或容器本地时区。 - 用户所在时区、设备时区或 IP 推断时区只能用于展示、风控或资料字段;不能作为结算、统计、任务刷新和幂等周期的业务切日来源。 diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index 9466dc61..02adbad7 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -1386,7 +1386,7 @@ func (x *RoomRankChanged) GetGiftValue() int64 { return 0 } -type RoomTreasureRewardGrant struct { +type RoomRocketRewardGrant struct { state protoimpl.MessageState `protogen:"open.v1"` RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` @@ -1400,20 +1400,20 @@ type RoomTreasureRewardGrant struct { sizeCache protoimpl.SizeCache } -func (x *RoomTreasureRewardGrant) Reset() { - *x = RoomTreasureRewardGrant{} +func (x *RoomRocketRewardGrant) Reset() { + *x = RoomRocketRewardGrant{} mi := &file_proto_events_room_v1_events_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureRewardGrant) String() string { +func (x *RoomRocketRewardGrant) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureRewardGrant) ProtoMessage() {} +func (*RoomRocketRewardGrant) ProtoMessage() {} -func (x *RoomTreasureRewardGrant) ProtoReflect() protoreflect.Message { +func (x *RoomRocketRewardGrant) ProtoReflect() protoreflect.Message { mi := &file_proto_events_room_v1_events_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1425,102 +1425,102 @@ func (x *RoomTreasureRewardGrant) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureRewardGrant.ProtoReflect.Descriptor instead. -func (*RoomTreasureRewardGrant) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketRewardGrant.ProtoReflect.Descriptor instead. +func (*RoomRocketRewardGrant) Descriptor() ([]byte, []int) { return file_proto_events_room_v1_events_proto_rawDescGZIP(), []int{19} } -func (x *RoomTreasureRewardGrant) GetRewardRole() string { +func (x *RoomRocketRewardGrant) GetRewardRole() string { if x != nil { return x.RewardRole } return "" } -func (x *RoomTreasureRewardGrant) GetUserId() int64 { +func (x *RoomRocketRewardGrant) GetUserId() int64 { if x != nil { return x.UserId } return 0 } -func (x *RoomTreasureRewardGrant) GetRewardItemId() string { +func (x *RoomRocketRewardGrant) GetRewardItemId() string { if x != nil { return x.RewardItemId } return "" } -func (x *RoomTreasureRewardGrant) GetResourceGroupId() int64 { +func (x *RoomRocketRewardGrant) GetResourceGroupId() int64 { if x != nil { return x.ResourceGroupId } return 0 } -func (x *RoomTreasureRewardGrant) GetDisplayName() string { +func (x *RoomRocketRewardGrant) GetDisplayName() string { if x != nil { return x.DisplayName } return "" } -func (x *RoomTreasureRewardGrant) GetIconUrl() string { +func (x *RoomRocketRewardGrant) GetIconUrl() string { if x != nil { return x.IconUrl } return "" } -func (x *RoomTreasureRewardGrant) GetGrantId() string { +func (x *RoomRocketRewardGrant) GetGrantId() string { if x != nil { return x.GrantId } return "" } -func (x *RoomTreasureRewardGrant) GetStatus() string { +func (x *RoomRocketRewardGrant) GetStatus() string { if x != nil { return x.Status } return "" } -// RoomTreasureProgressChanged 表达送礼扣费成功后宝箱有效能量发生变化。 -type RoomTreasureProgressChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - BoxId string `protobuf:"bytes,1,opt,name=box_id,json=boxId,proto3" json:"box_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - AddedEnergy int64 `protobuf:"varint,3,opt,name=added_energy,json=addedEnergy,proto3" json:"added_energy,omitempty"` - EffectiveAddedEnergy int64 `protobuf:"varint,4,opt,name=effective_added_energy,json=effectiveAddedEnergy,proto3" json:"effective_added_energy,omitempty"` - OverflowEnergy int64 `protobuf:"varint,5,opt,name=overflow_energy,json=overflowEnergy,proto3" json:"overflow_energy,omitempty"` - CurrentProgress int64 `protobuf:"varint,6,opt,name=current_progress,json=currentProgress,proto3" json:"current_progress,omitempty"` - EnergyThreshold int64 `protobuf:"varint,7,opt,name=energy_threshold,json=energyThreshold,proto3" json:"energy_threshold,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - ResetAtMs int64 `protobuf:"varint,9,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - SenderUserId int64 `protobuf:"varint,10,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - GiftId string `protobuf:"bytes,11,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,14,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +// RoomRocketFuelChanged 表达送礼扣费成功后火箭有效燃料发生变化。 +type RoomRocketFuelChanged struct { + state protoimpl.MessageState `protogen:"open.v1"` + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + AddedFuel int64 `protobuf:"varint,3,opt,name=added_fuel,json=addedFuel,proto3" json:"added_fuel,omitempty"` + EffectiveAddedFuel int64 `protobuf:"varint,4,opt,name=effective_added_fuel,json=effectiveAddedFuel,proto3" json:"effective_added_fuel,omitempty"` + OverflowFuel int64 `protobuf:"varint,5,opt,name=overflow_fuel,json=overflowFuel,proto3" json:"overflow_fuel,omitempty"` + CurrentFuel int64 `protobuf:"varint,6,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` + FuelThreshold int64 `protobuf:"varint,7,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + ResetAtMs int64 `protobuf:"varint,9,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + SenderUserId int64 `protobuf:"varint,10,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + GiftId string `protobuf:"bytes,11,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,14,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (x *RoomTreasureProgressChanged) Reset() { - *x = RoomTreasureProgressChanged{} +func (x *RoomRocketFuelChanged) Reset() { + *x = RoomRocketFuelChanged{} mi := &file_proto_events_room_v1_events_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureProgressChanged) String() string { +func (x *RoomRocketFuelChanged) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureProgressChanged) ProtoMessage() {} +func (*RoomRocketFuelChanged) ProtoMessage() {} -func (x *RoomTreasureProgressChanged) ProtoReflect() protoreflect.Message { +func (x *RoomRocketFuelChanged) ProtoReflect() protoreflect.Message { mi := &file_proto_events_room_v1_events_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1532,141 +1532,143 @@ func (x *RoomTreasureProgressChanged) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureProgressChanged.ProtoReflect.Descriptor instead. -func (*RoomTreasureProgressChanged) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketFuelChanged.ProtoReflect.Descriptor instead. +func (*RoomRocketFuelChanged) Descriptor() ([]byte, []int) { return file_proto_events_room_v1_events_proto_rawDescGZIP(), []int{20} } -func (x *RoomTreasureProgressChanged) GetBoxId() string { +func (x *RoomRocketFuelChanged) GetRocketId() string { if x != nil { - return x.BoxId + return x.RocketId } return "" } -func (x *RoomTreasureProgressChanged) GetLevel() int32 { +func (x *RoomRocketFuelChanged) GetLevel() int32 { if x != nil { return x.Level } return 0 } -func (x *RoomTreasureProgressChanged) GetAddedEnergy() int64 { +func (x *RoomRocketFuelChanged) GetAddedFuel() int64 { if x != nil { - return x.AddedEnergy + return x.AddedFuel } return 0 } -func (x *RoomTreasureProgressChanged) GetEffectiveAddedEnergy() int64 { +func (x *RoomRocketFuelChanged) GetEffectiveAddedFuel() int64 { if x != nil { - return x.EffectiveAddedEnergy + return x.EffectiveAddedFuel } return 0 } -func (x *RoomTreasureProgressChanged) GetOverflowEnergy() int64 { +func (x *RoomRocketFuelChanged) GetOverflowFuel() int64 { if x != nil { - return x.OverflowEnergy + return x.OverflowFuel } return 0 } -func (x *RoomTreasureProgressChanged) GetCurrentProgress() int64 { +func (x *RoomRocketFuelChanged) GetCurrentFuel() int64 { if x != nil { - return x.CurrentProgress + return x.CurrentFuel } return 0 } -func (x *RoomTreasureProgressChanged) GetEnergyThreshold() int64 { +func (x *RoomRocketFuelChanged) GetFuelThreshold() int64 { if x != nil { - return x.EnergyThreshold + return x.FuelThreshold } return 0 } -func (x *RoomTreasureProgressChanged) GetStatus() string { +func (x *RoomRocketFuelChanged) GetStatus() string { if x != nil { return x.Status } return "" } -func (x *RoomTreasureProgressChanged) GetResetAtMs() int64 { +func (x *RoomRocketFuelChanged) GetResetAtMs() int64 { if x != nil { return x.ResetAtMs } return 0 } -func (x *RoomTreasureProgressChanged) GetSenderUserId() int64 { +func (x *RoomRocketFuelChanged) GetSenderUserId() int64 { if x != nil { return x.SenderUserId } return 0 } -func (x *RoomTreasureProgressChanged) GetGiftId() string { +func (x *RoomRocketFuelChanged) GetGiftId() string { if x != nil { return x.GiftId } return "" } -func (x *RoomTreasureProgressChanged) GetGiftCount() int32 { +func (x *RoomRocketFuelChanged) GetGiftCount() int32 { if x != nil { return x.GiftCount } return 0 } -func (x *RoomTreasureProgressChanged) GetCommandId() string { +func (x *RoomRocketFuelChanged) GetCommandId() string { if x != nil { return x.CommandId } return "" } -func (x *RoomTreasureProgressChanged) GetVisibleRegionId() int64 { +func (x *RoomRocketFuelChanged) GetVisibleRegionId() int64 { if x != nil { return x.VisibleRegionId } return 0 } -// RoomTreasureCountdownStarted 表达宝箱满能量后进入倒计时,并作为区域/全局播报的事实源。 -type RoomTreasureCountdownStarted struct { - state protoimpl.MessageState `protogen:"open.v1"` - BoxId string `protobuf:"bytes,1,opt,name=box_id,json=boxId,proto3" json:"box_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - CurrentProgress int64 `protobuf:"varint,3,opt,name=current_progress,json=currentProgress,proto3" json:"current_progress,omitempty"` - EnergyThreshold int64 `protobuf:"varint,4,opt,name=energy_threshold,json=energyThreshold,proto3" json:"energy_threshold,omitempty"` - CountdownStartedAtMs int64 `protobuf:"varint,5,opt,name=countdown_started_at_ms,json=countdownStartedAtMs,proto3" json:"countdown_started_at_ms,omitempty"` - OpenAtMs int64 `protobuf:"varint,6,opt,name=open_at_ms,json=openAtMs,proto3" json:"open_at_ms,omitempty"` - BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` - VisibleRegionId int64 `protobuf:"varint,8,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` - IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` - CommandId string `protobuf:"bytes,11,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +// RoomRocketIgnited 表达火箭燃料满后进入倒计时,并作为区域/全局播报的事实源。 +type RoomRocketIgnited struct { + state protoimpl.MessageState `protogen:"open.v1"` + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + CurrentFuel int64 `protobuf:"varint,3,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` + FuelThreshold int64 `protobuf:"varint,4,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + IgnitedAtMs int64 `protobuf:"varint,5,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` + LaunchAtMs int64 `protobuf:"varint,6,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` + BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` + VisibleRegionId int64 `protobuf:"varint,8,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + CommandId string `protobuf:"bytes,11,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RoomShortId string `protobuf:"bytes,12,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + RocketCoverUrl string `protobuf:"bytes,13,opt,name=rocket_cover_url,json=rocketCoverUrl,proto3" json:"rocket_cover_url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (x *RoomTreasureCountdownStarted) Reset() { - *x = RoomTreasureCountdownStarted{} +func (x *RoomRocketIgnited) Reset() { + *x = RoomRocketIgnited{} mi := &file_proto_events_room_v1_events_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureCountdownStarted) String() string { +func (x *RoomRocketIgnited) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureCountdownStarted) ProtoMessage() {} +func (*RoomRocketIgnited) ProtoMessage() {} -func (x *RoomTreasureCountdownStarted) ProtoReflect() protoreflect.Message { +func (x *RoomRocketIgnited) ProtoReflect() protoreflect.Message { mi := &file_proto_events_room_v1_events_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1678,118 +1680,132 @@ func (x *RoomTreasureCountdownStarted) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureCountdownStarted.ProtoReflect.Descriptor instead. -func (*RoomTreasureCountdownStarted) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketIgnited.ProtoReflect.Descriptor instead. +func (*RoomRocketIgnited) Descriptor() ([]byte, []int) { return file_proto_events_room_v1_events_proto_rawDescGZIP(), []int{21} } -func (x *RoomTreasureCountdownStarted) GetBoxId() string { +func (x *RoomRocketIgnited) GetRocketId() string { if x != nil { - return x.BoxId + return x.RocketId } return "" } -func (x *RoomTreasureCountdownStarted) GetLevel() int32 { +func (x *RoomRocketIgnited) GetLevel() int32 { if x != nil { return x.Level } return 0 } -func (x *RoomTreasureCountdownStarted) GetCurrentProgress() int64 { +func (x *RoomRocketIgnited) GetCurrentFuel() int64 { if x != nil { - return x.CurrentProgress + return x.CurrentFuel } return 0 } -func (x *RoomTreasureCountdownStarted) GetEnergyThreshold() int64 { +func (x *RoomRocketIgnited) GetFuelThreshold() int64 { if x != nil { - return x.EnergyThreshold + return x.FuelThreshold } return 0 } -func (x *RoomTreasureCountdownStarted) GetCountdownStartedAtMs() int64 { +func (x *RoomRocketIgnited) GetIgnitedAtMs() int64 { if x != nil { - return x.CountdownStartedAtMs + return x.IgnitedAtMs } return 0 } -func (x *RoomTreasureCountdownStarted) GetOpenAtMs() int64 { +func (x *RoomRocketIgnited) GetLaunchAtMs() int64 { if x != nil { - return x.OpenAtMs + return x.LaunchAtMs } return 0 } -func (x *RoomTreasureCountdownStarted) GetBroadcastScope() string { +func (x *RoomRocketIgnited) GetBroadcastScope() string { if x != nil { return x.BroadcastScope } return "" } -func (x *RoomTreasureCountdownStarted) GetVisibleRegionId() int64 { +func (x *RoomRocketIgnited) GetVisibleRegionId() int64 { if x != nil { return x.VisibleRegionId } return 0 } -func (x *RoomTreasureCountdownStarted) GetTop1UserId() int64 { +func (x *RoomRocketIgnited) GetTop1UserId() int64 { if x != nil { return x.Top1UserId } return 0 } -func (x *RoomTreasureCountdownStarted) GetIgniterUserId() int64 { +func (x *RoomRocketIgnited) GetIgniterUserId() int64 { if x != nil { return x.IgniterUserId } return 0 } -func (x *RoomTreasureCountdownStarted) GetCommandId() string { +func (x *RoomRocketIgnited) GetCommandId() string { if x != nil { return x.CommandId } return "" } -// RoomTreasureOpened 表达宝箱已经打开,在线用户名单按开箱瞬间 Room Cell presence 结算。 -type RoomTreasureOpened struct { - state protoimpl.MessageState `protogen:"open.v1"` - BoxId string `protobuf:"bytes,1,opt,name=box_id,json=boxId,proto3" json:"box_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - NextLevel int32 `protobuf:"varint,3,opt,name=next_level,json=nextLevel,proto3" json:"next_level,omitempty"` - OpenedAtMs int64 `protobuf:"varint,4,opt,name=opened_at_ms,json=openedAtMs,proto3" json:"opened_at_ms,omitempty"` - ResetAtMs int64 `protobuf:"varint,5,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - Top1UserId int64 `protobuf:"varint,6,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` - IgniterUserId int64 `protobuf:"varint,7,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` - InRoomUserIds []int64 `protobuf:"varint,8,rep,packed,name=in_room_user_ids,json=inRoomUserIds,proto3" json:"in_room_user_ids,omitempty"` - Rewards []*RoomTreasureRewardGrant `protobuf:"bytes,9,rep,name=rewards,proto3" json:"rewards,omitempty"` +func (x *RoomRocketIgnited) GetRoomShortId() string { + if x != nil { + return x.RoomShortId + } + return "" +} + +func (x *RoomRocketIgnited) GetRocketCoverUrl() string { + if x != nil { + return x.RocketCoverUrl + } + return "" +} + +// RoomRocketLaunched 表达火箭已经发射,在线用户名单按发射瞬间 Room Cell presence 结算。 +type RoomRocketLaunched struct { + state protoimpl.MessageState `protogen:"open.v1"` + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + NextLevel int32 `protobuf:"varint,3,opt,name=next_level,json=nextLevel,proto3" json:"next_level,omitempty"` + LaunchedAtMs int64 `protobuf:"varint,4,opt,name=launched_at_ms,json=launchedAtMs,proto3" json:"launched_at_ms,omitempty"` + ResetAtMs int64 `protobuf:"varint,5,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + Top1UserId int64 `protobuf:"varint,6,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,7,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + InRoomUserIds []int64 `protobuf:"varint,8,rep,packed,name=in_room_user_ids,json=inRoomUserIds,proto3" json:"in_room_user_ids,omitempty"` + Rewards []*RoomRocketRewardGrant `protobuf:"bytes,9,rep,name=rewards,proto3" json:"rewards,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *RoomTreasureOpened) Reset() { - *x = RoomTreasureOpened{} +func (x *RoomRocketLaunched) Reset() { + *x = RoomRocketLaunched{} mi := &file_proto_events_room_v1_events_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureOpened) String() string { +func (x *RoomRocketLaunched) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureOpened) ProtoMessage() {} +func (*RoomRocketLaunched) ProtoMessage() {} -func (x *RoomTreasureOpened) ProtoReflect() protoreflect.Message { +func (x *RoomRocketLaunched) ProtoReflect() protoreflect.Message { mi := &file_proto_events_room_v1_events_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1801,98 +1817,98 @@ func (x *RoomTreasureOpened) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureOpened.ProtoReflect.Descriptor instead. -func (*RoomTreasureOpened) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketLaunched.ProtoReflect.Descriptor instead. +func (*RoomRocketLaunched) Descriptor() ([]byte, []int) { return file_proto_events_room_v1_events_proto_rawDescGZIP(), []int{22} } -func (x *RoomTreasureOpened) GetBoxId() string { +func (x *RoomRocketLaunched) GetRocketId() string { if x != nil { - return x.BoxId + return x.RocketId } return "" } -func (x *RoomTreasureOpened) GetLevel() int32 { +func (x *RoomRocketLaunched) GetLevel() int32 { if x != nil { return x.Level } return 0 } -func (x *RoomTreasureOpened) GetNextLevel() int32 { +func (x *RoomRocketLaunched) GetNextLevel() int32 { if x != nil { return x.NextLevel } return 0 } -func (x *RoomTreasureOpened) GetOpenedAtMs() int64 { +func (x *RoomRocketLaunched) GetLaunchedAtMs() int64 { if x != nil { - return x.OpenedAtMs + return x.LaunchedAtMs } return 0 } -func (x *RoomTreasureOpened) GetResetAtMs() int64 { +func (x *RoomRocketLaunched) GetResetAtMs() int64 { if x != nil { return x.ResetAtMs } return 0 } -func (x *RoomTreasureOpened) GetTop1UserId() int64 { +func (x *RoomRocketLaunched) GetTop1UserId() int64 { if x != nil { return x.Top1UserId } return 0 } -func (x *RoomTreasureOpened) GetIgniterUserId() int64 { +func (x *RoomRocketLaunched) GetIgniterUserId() int64 { if x != nil { return x.IgniterUserId } return 0 } -func (x *RoomTreasureOpened) GetInRoomUserIds() []int64 { +func (x *RoomRocketLaunched) GetInRoomUserIds() []int64 { if x != nil { return x.InRoomUserIds } return nil } -func (x *RoomTreasureOpened) GetRewards() []*RoomTreasureRewardGrant { +func (x *RoomRocketLaunched) GetRewards() []*RoomRocketRewardGrant { if x != nil { return x.Rewards } return nil } -// RoomTreasureRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。 -type RoomTreasureRewardGranted struct { - state protoimpl.MessageState `protogen:"open.v1"` - BoxId string `protobuf:"bytes,1,opt,name=box_id,json=boxId,proto3" json:"box_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - Rewards []*RoomTreasureRewardGrant `protobuf:"bytes,3,rep,name=rewards,proto3" json:"rewards,omitempty"` +// RoomRocketRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。 +type RoomRocketRewardGranted struct { + state protoimpl.MessageState `protogen:"open.v1"` + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + Rewards []*RoomRocketRewardGrant `protobuf:"bytes,3,rep,name=rewards,proto3" json:"rewards,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *RoomTreasureRewardGranted) Reset() { - *x = RoomTreasureRewardGranted{} +func (x *RoomRocketRewardGranted) Reset() { + *x = RoomRocketRewardGranted{} mi := &file_proto_events_room_v1_events_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureRewardGranted) String() string { +func (x *RoomRocketRewardGranted) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureRewardGranted) ProtoMessage() {} +func (*RoomRocketRewardGranted) ProtoMessage() {} -func (x *RoomTreasureRewardGranted) ProtoReflect() protoreflect.Message { +func (x *RoomRocketRewardGranted) ProtoReflect() protoreflect.Message { mi := &file_proto_events_room_v1_events_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1904,26 +1920,26 @@ func (x *RoomTreasureRewardGranted) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureRewardGranted.ProtoReflect.Descriptor instead. -func (*RoomTreasureRewardGranted) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketRewardGranted.ProtoReflect.Descriptor instead. +func (*RoomRocketRewardGranted) Descriptor() ([]byte, []int) { return file_proto_events_room_v1_events_proto_rawDescGZIP(), []int{23} } -func (x *RoomTreasureRewardGranted) GetBoxId() string { +func (x *RoomRocketRewardGranted) GetRocketId() string { if x != nil { - return x.BoxId + return x.RocketId } return "" } -func (x *RoomTreasureRewardGranted) GetLevel() int32 { +func (x *RoomRocketRewardGranted) GetLevel() int32 { if x != nil { return x.Level } return 0 } -func (x *RoomTreasureRewardGranted) GetRewards() []*RoomTreasureRewardGrant { +func (x *RoomRocketRewardGranted) GetRewards() []*RoomRocketRewardGrant { if x != nil { return x.Rewards } @@ -2049,8 +2065,8 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n" + "\x05score\x18\x02 \x01(\x03R\x05score\x12\x1d\n" + "\n" + - "gift_value\x18\x03 \x01(\x03R\tgiftValue\"\x96\x02\n" + - "\x17RoomTreasureRewardGrant\x12\x1f\n" + + "gift_value\x18\x03 \x01(\x03R\tgiftValue\"\x94\x02\n" + + "\x15RoomRocketRewardGrant\x12\x1f\n" + "\vreward_role\x18\x01 \x01(\tR\n" + "rewardRole\x12\x17\n" + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + @@ -2059,15 +2075,16 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\fdisplay_name\x18\x05 \x01(\tR\vdisplayName\x12\x19\n" + "\bicon_url\x18\x06 \x01(\tR\aiconUrl\x12\x19\n" + "\bgrant_id\x18\a \x01(\tR\agrantId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\"\x83\x04\n" + - "\x1bRoomTreasureProgressChanged\x12\x15\n" + - "\x06box_id\x18\x01 \x01(\tR\x05boxId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12!\n" + - "\fadded_energy\x18\x03 \x01(\x03R\vaddedEnergy\x124\n" + - "\x16effective_added_energy\x18\x04 \x01(\x03R\x14effectiveAddedEnergy\x12'\n" + - "\x0foverflow_energy\x18\x05 \x01(\x03R\x0eoverflowEnergy\x12)\n" + - "\x10current_progress\x18\x06 \x01(\x03R\x0fcurrentProgress\x12)\n" + - "\x10energy_threshold\x18\a \x01(\x03R\x0fenergyThreshold\x12\x16\n" + + "\x06status\x18\b \x01(\tR\x06status\"\xeb\x03\n" + + "\x15RoomRocketFuelChanged\x12\x1b\n" + + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + + "\x05level\x18\x02 \x01(\x05R\x05level\x12\x1d\n" + + "\n" + + "added_fuel\x18\x03 \x01(\x03R\taddedFuel\x120\n" + + "\x14effective_added_fuel\x18\x04 \x01(\x03R\x12effectiveAddedFuel\x12#\n" + + "\roverflow_fuel\x18\x05 \x01(\x03R\foverflowFuel\x12!\n" + + "\fcurrent_fuel\x18\x06 \x01(\x03R\vcurrentFuel\x12%\n" + + "\x0efuel_threshold\x18\a \x01(\x03R\rfuelThreshold\x12\x16\n" + "\x06status\x18\b \x01(\tR\x06status\x12\x1e\n" + "\vreset_at_ms\x18\t \x01(\x03R\tresetAtMs\x12$\n" + "\x0esender_user_id\x18\n" + @@ -2077,15 +2094,15 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "gift_count\x18\f \x01(\x05R\tgiftCount\x12\x1d\n" + "\n" + "command_id\x18\r \x01(\tR\tcommandId\x12*\n" + - "\x11visible_region_id\x18\x0e \x01(\x03R\x0fvisibleRegionId\"\xb4\x03\n" + - "\x1cRoomTreasureCountdownStarted\x12\x15\n" + - "\x06box_id\x18\x01 \x01(\tR\x05boxId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12)\n" + - "\x10current_progress\x18\x03 \x01(\x03R\x0fcurrentProgress\x12)\n" + - "\x10energy_threshold\x18\x04 \x01(\x03R\x0fenergyThreshold\x125\n" + - "\x17countdown_started_at_ms\x18\x05 \x01(\x03R\x14countdownStartedAtMs\x12\x1c\n" + - "\n" + - "open_at_ms\x18\x06 \x01(\x03R\bopenAtMs\x12'\n" + + "\x11visible_region_id\x18\x0e \x01(\x03R\x0fvisibleRegionId\"\xe2\x03\n" + + "\x11RoomRocketIgnited\x12\x1b\n" + + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + + "\x05level\x18\x02 \x01(\x05R\x05level\x12!\n" + + "\fcurrent_fuel\x18\x03 \x01(\x03R\vcurrentFuel\x12%\n" + + "\x0efuel_threshold\x18\x04 \x01(\x03R\rfuelThreshold\x12\"\n" + + "\rignited_at_ms\x18\x05 \x01(\x03R\vignitedAtMs\x12 \n" + + "\flaunch_at_ms\x18\x06 \x01(\x03R\n" + + "launchAtMs\x12'\n" + "\x0fbroadcast_scope\x18\a \x01(\tR\x0ebroadcastScope\x12*\n" + "\x11visible_region_id\x18\b \x01(\x03R\x0fvisibleRegionId\x12 \n" + "\ftop1_user_id\x18\t \x01(\x03R\n" + @@ -2093,24 +2110,25 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\x0figniter_user_id\x18\n" + " \x01(\x03R\rigniterUserId\x12\x1d\n" + "\n" + - "command_id\x18\v \x01(\tR\tcommandId\"\xde\x02\n" + - "\x12RoomTreasureOpened\x12\x15\n" + - "\x06box_id\x18\x01 \x01(\tR\x05boxId\x12\x14\n" + + "command_id\x18\v \x01(\tR\tcommandId\x12\"\n" + + "\rroom_short_id\x18\f \x01(\tR\vroomShortId\x12(\n" + + "\x10rocket_cover_url\x18\r \x01(\tR\x0erocketCoverUrl\"\xe6\x02\n" + + "\x12RoomRocketLaunched\x12\x1b\n" + + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + "\x05level\x18\x02 \x01(\x05R\x05level\x12\x1d\n" + "\n" + - "next_level\x18\x03 \x01(\x05R\tnextLevel\x12 \n" + - "\fopened_at_ms\x18\x04 \x01(\x03R\n" + - "openedAtMs\x12\x1e\n" + + "next_level\x18\x03 \x01(\x05R\tnextLevel\x12$\n" + + "\x0elaunched_at_ms\x18\x04 \x01(\x03R\flaunchedAtMs\x12\x1e\n" + "\vreset_at_ms\x18\x05 \x01(\x03R\tresetAtMs\x12 \n" + "\ftop1_user_id\x18\x06 \x01(\x03R\n" + "top1UserId\x12&\n" + "\x0figniter_user_id\x18\a \x01(\x03R\rigniterUserId\x12'\n" + - "\x10in_room_user_ids\x18\b \x03(\x03R\rinRoomUserIds\x12G\n" + - "\arewards\x18\t \x03(\v2-.hyapp.events.room.v1.RoomTreasureRewardGrantR\arewards\"\x91\x01\n" + - "\x19RoomTreasureRewardGranted\x12\x15\n" + - "\x06box_id\x18\x01 \x01(\tR\x05boxId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12G\n" + - "\arewards\x18\x03 \x03(\v2-.hyapp.events.room.v1.RoomTreasureRewardGrantR\arewardsB3Z1hyapp.local/api/proto/events/room/v1;roomeventsv1b\x06proto3" + "\x10in_room_user_ids\x18\b \x03(\x03R\rinRoomUserIds\x12E\n" + + "\arewards\x18\t \x03(\v2+.hyapp.events.room.v1.RoomRocketRewardGrantR\arewards\"\x93\x01\n" + + "\x17RoomRocketRewardGranted\x12\x1b\n" + + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + + "\x05level\x18\x02 \x01(\x05R\x05level\x12E\n" + + "\arewards\x18\x03 \x03(\v2+.hyapp.events.room.v1.RoomRocketRewardGrantR\arewardsB3Z1hyapp.local/api/proto/events/room/v1;roomeventsv1b\x06proto3" var ( file_proto_events_room_v1_events_proto_rawDescOnce sync.Once @@ -2126,35 +2144,35 @@ func file_proto_events_room_v1_events_proto_rawDescGZIP() []byte { var file_proto_events_room_v1_events_proto_msgTypes = make([]protoimpl.MessageInfo, 24) var file_proto_events_room_v1_events_proto_goTypes = []any{ - (*EventEnvelope)(nil), // 0: hyapp.events.room.v1.EventEnvelope - (*RoomCreated)(nil), // 1: hyapp.events.room.v1.RoomCreated - (*RoomProfileUpdated)(nil), // 2: hyapp.events.room.v1.RoomProfileUpdated - (*RoomBackgroundChanged)(nil), // 3: hyapp.events.room.v1.RoomBackgroundChanged - (*RoomEntryVehicleSnapshot)(nil), // 4: hyapp.events.room.v1.RoomEntryVehicleSnapshot - (*RoomUserJoined)(nil), // 5: hyapp.events.room.v1.RoomUserJoined - (*RoomUserLeft)(nil), // 6: hyapp.events.room.v1.RoomUserLeft - (*RoomClosed)(nil), // 7: hyapp.events.room.v1.RoomClosed - (*RoomMicChanged)(nil), // 8: hyapp.events.room.v1.RoomMicChanged - (*RoomMicSeatLocked)(nil), // 9: hyapp.events.room.v1.RoomMicSeatLocked - (*RoomChatEnabledChanged)(nil), // 10: hyapp.events.room.v1.RoomChatEnabledChanged - (*RoomPasswordChanged)(nil), // 11: hyapp.events.room.v1.RoomPasswordChanged - (*RoomAdminChanged)(nil), // 12: hyapp.events.room.v1.RoomAdminChanged - (*RoomUserMuted)(nil), // 13: hyapp.events.room.v1.RoomUserMuted - (*RoomUserKicked)(nil), // 14: hyapp.events.room.v1.RoomUserKicked - (*RoomUserUnbanned)(nil), // 15: hyapp.events.room.v1.RoomUserUnbanned - (*RoomGiftSent)(nil), // 16: hyapp.events.room.v1.RoomGiftSent - (*RoomHeatChanged)(nil), // 17: hyapp.events.room.v1.RoomHeatChanged - (*RoomRankChanged)(nil), // 18: hyapp.events.room.v1.RoomRankChanged - (*RoomTreasureRewardGrant)(nil), // 19: hyapp.events.room.v1.RoomTreasureRewardGrant - (*RoomTreasureProgressChanged)(nil), // 20: hyapp.events.room.v1.RoomTreasureProgressChanged - (*RoomTreasureCountdownStarted)(nil), // 21: hyapp.events.room.v1.RoomTreasureCountdownStarted - (*RoomTreasureOpened)(nil), // 22: hyapp.events.room.v1.RoomTreasureOpened - (*RoomTreasureRewardGranted)(nil), // 23: hyapp.events.room.v1.RoomTreasureRewardGranted + (*EventEnvelope)(nil), // 0: hyapp.events.room.v1.EventEnvelope + (*RoomCreated)(nil), // 1: hyapp.events.room.v1.RoomCreated + (*RoomProfileUpdated)(nil), // 2: hyapp.events.room.v1.RoomProfileUpdated + (*RoomBackgroundChanged)(nil), // 3: hyapp.events.room.v1.RoomBackgroundChanged + (*RoomEntryVehicleSnapshot)(nil), // 4: hyapp.events.room.v1.RoomEntryVehicleSnapshot + (*RoomUserJoined)(nil), // 5: hyapp.events.room.v1.RoomUserJoined + (*RoomUserLeft)(nil), // 6: hyapp.events.room.v1.RoomUserLeft + (*RoomClosed)(nil), // 7: hyapp.events.room.v1.RoomClosed + (*RoomMicChanged)(nil), // 8: hyapp.events.room.v1.RoomMicChanged + (*RoomMicSeatLocked)(nil), // 9: hyapp.events.room.v1.RoomMicSeatLocked + (*RoomChatEnabledChanged)(nil), // 10: hyapp.events.room.v1.RoomChatEnabledChanged + (*RoomPasswordChanged)(nil), // 11: hyapp.events.room.v1.RoomPasswordChanged + (*RoomAdminChanged)(nil), // 12: hyapp.events.room.v1.RoomAdminChanged + (*RoomUserMuted)(nil), // 13: hyapp.events.room.v1.RoomUserMuted + (*RoomUserKicked)(nil), // 14: hyapp.events.room.v1.RoomUserKicked + (*RoomUserUnbanned)(nil), // 15: hyapp.events.room.v1.RoomUserUnbanned + (*RoomGiftSent)(nil), // 16: hyapp.events.room.v1.RoomGiftSent + (*RoomHeatChanged)(nil), // 17: hyapp.events.room.v1.RoomHeatChanged + (*RoomRankChanged)(nil), // 18: hyapp.events.room.v1.RoomRankChanged + (*RoomRocketRewardGrant)(nil), // 19: hyapp.events.room.v1.RoomRocketRewardGrant + (*RoomRocketFuelChanged)(nil), // 20: hyapp.events.room.v1.RoomRocketFuelChanged + (*RoomRocketIgnited)(nil), // 21: hyapp.events.room.v1.RoomRocketIgnited + (*RoomRocketLaunched)(nil), // 22: hyapp.events.room.v1.RoomRocketLaunched + (*RoomRocketRewardGranted)(nil), // 23: hyapp.events.room.v1.RoomRocketRewardGranted } var file_proto_events_room_v1_events_proto_depIdxs = []int32{ 4, // 0: hyapp.events.room.v1.RoomUserJoined.entry_vehicle:type_name -> hyapp.events.room.v1.RoomEntryVehicleSnapshot - 19, // 1: hyapp.events.room.v1.RoomTreasureOpened.rewards:type_name -> hyapp.events.room.v1.RoomTreasureRewardGrant - 19, // 2: hyapp.events.room.v1.RoomTreasureRewardGranted.rewards:type_name -> hyapp.events.room.v1.RoomTreasureRewardGrant + 19, // 1: hyapp.events.room.v1.RoomRocketLaunched.rewards:type_name -> hyapp.events.room.v1.RoomRocketRewardGrant + 19, // 2: hyapp.events.room.v1.RoomRocketRewardGranted.rewards:type_name -> hyapp.events.room.v1.RoomRocketRewardGrant 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name diff --git a/api/proto/events/room/v1/events.proto b/api/proto/events/room/v1/events.proto index 2c749ea0..7b4ec45b 100644 --- a/api/proto/events/room/v1/events.proto +++ b/api/proto/events/room/v1/events.proto @@ -168,7 +168,7 @@ message RoomRankChanged { int64 gift_value = 3; } -message RoomTreasureRewardGrant { +message RoomRocketRewardGrant { string reward_role = 1; int64 user_id = 2; string reward_item_id = 3; @@ -179,15 +179,15 @@ message RoomTreasureRewardGrant { string status = 8; } -// RoomTreasureProgressChanged 表达送礼扣费成功后宝箱有效能量发生变化。 -message RoomTreasureProgressChanged { - string box_id = 1; +// RoomRocketFuelChanged 表达送礼扣费成功后火箭有效燃料发生变化。 +message RoomRocketFuelChanged { + string rocket_id = 1; int32 level = 2; - int64 added_energy = 3; - int64 effective_added_energy = 4; - int64 overflow_energy = 5; - int64 current_progress = 6; - int64 energy_threshold = 7; + int64 added_fuel = 3; + int64 effective_added_fuel = 4; + int64 overflow_fuel = 5; + int64 current_fuel = 6; + int64 fuel_threshold = 7; string status = 8; int64 reset_at_ms = 9; int64 sender_user_id = 10; @@ -197,37 +197,40 @@ message RoomTreasureProgressChanged { int64 visible_region_id = 14; } -// RoomTreasureCountdownStarted 表达宝箱满能量后进入倒计时,并作为区域/全局播报的事实源。 -message RoomTreasureCountdownStarted { - string box_id = 1; +// RoomRocketIgnited 表达火箭燃料满后进入倒计时,并作为区域/全局播报的事实源。 +message RoomRocketIgnited { + string rocket_id = 1; int32 level = 2; - int64 current_progress = 3; - int64 energy_threshold = 4; - int64 countdown_started_at_ms = 5; - int64 open_at_ms = 6; + int64 current_fuel = 3; + int64 fuel_threshold = 4; + int64 ignited_at_ms = 5; + int64 launch_at_ms = 6; string broadcast_scope = 7; int64 visible_region_id = 8; int64 top1_user_id = 9; int64 igniter_user_id = 10; string command_id = 11; + string room_short_id = 12; + string rocket_cover_url = 13; + int64 reset_at_ms = 14; } -// RoomTreasureOpened 表达宝箱已经打开,在线用户名单按开箱瞬间 Room Cell presence 结算。 -message RoomTreasureOpened { - string box_id = 1; +// RoomRocketLaunched 表达火箭已经发射,在线用户名单按发射瞬间 Room Cell presence 结算。 +message RoomRocketLaunched { + string rocket_id = 1; int32 level = 2; int32 next_level = 3; - int64 opened_at_ms = 4; + int64 launched_at_ms = 4; int64 reset_at_ms = 5; int64 top1_user_id = 6; int64 igniter_user_id = 7; repeated int64 in_room_user_ids = 8; - repeated RoomTreasureRewardGrant rewards = 9; + repeated RoomRocketRewardGrant rewards = 9; } -// RoomTreasureRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。 -message RoomTreasureRewardGranted { - string box_id = 1; +// RoomRocketRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。 +message RoomRocketRewardGranted { + string rocket_id = 1; int32 level = 2; - repeated RoomTreasureRewardGrant rewards = 3; + repeated RoomRocketRewardGrant rewards = 3; } diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 6c35bdb5..488289fe 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -749,8 +749,8 @@ func (x *LuckyGiftDrawResult) GetTargetUserId() int64 { return 0 } -// RoomTreasureRewardItem 是后台配置给客户端展示的宝箱奖励候选项。 -type RoomTreasureRewardItem struct { +// RoomRocketRewardItem 是后台配置给客户端展示的火箭奖励候选项。 +type RoomRocketRewardItem struct { state protoimpl.MessageState `protogen:"open.v1"` RewardItemId string `protobuf:"bytes,1,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` ResourceGroupId int64 `protobuf:"varint,2,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` @@ -761,20 +761,20 @@ type RoomTreasureRewardItem struct { sizeCache protoimpl.SizeCache } -func (x *RoomTreasureRewardItem) Reset() { - *x = RoomTreasureRewardItem{} +func (x *RoomRocketRewardItem) Reset() { + *x = RoomRocketRewardItem{} mi := &file_proto_room_v1_room_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureRewardItem) String() string { +func (x *RoomRocketRewardItem) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureRewardItem) ProtoMessage() {} +func (*RoomRocketRewardItem) ProtoMessage() {} -func (x *RoomTreasureRewardItem) ProtoReflect() protoreflect.Message { +func (x *RoomRocketRewardItem) ProtoReflect() protoreflect.Message { mi := &file_proto_room_v1_room_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -786,76 +786,76 @@ func (x *RoomTreasureRewardItem) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureRewardItem.ProtoReflect.Descriptor instead. -func (*RoomTreasureRewardItem) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketRewardItem.ProtoReflect.Descriptor instead. +func (*RoomRocketRewardItem) Descriptor() ([]byte, []int) { return file_proto_room_v1_room_proto_rawDescGZIP(), []int{7} } -func (x *RoomTreasureRewardItem) GetRewardItemId() string { +func (x *RoomRocketRewardItem) GetRewardItemId() string { if x != nil { return x.RewardItemId } return "" } -func (x *RoomTreasureRewardItem) GetResourceGroupId() int64 { +func (x *RoomRocketRewardItem) GetResourceGroupId() int64 { if x != nil { return x.ResourceGroupId } return 0 } -func (x *RoomTreasureRewardItem) GetWeight() int64 { +func (x *RoomRocketRewardItem) GetWeight() int64 { if x != nil { return x.Weight } return 0 } -func (x *RoomTreasureRewardItem) GetDisplayName() string { +func (x *RoomRocketRewardItem) GetDisplayName() string { if x != nil { return x.DisplayName } return "" } -func (x *RoomTreasureRewardItem) GetIconUrl() string { +func (x *RoomRocketRewardItem) GetIconUrl() string { if x != nil { return x.IconUrl } return "" } -// RoomTreasureLevel 暴露单个等级宝箱的物料、阈值和三类奖励池。 -type RoomTreasureLevel struct { - state protoimpl.MessageState `protogen:"open.v1"` - Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` - EnergyThreshold int64 `protobuf:"varint,2,opt,name=energy_threshold,json=energyThreshold,proto3" json:"energy_threshold,omitempty"` - CoverUrl string `protobuf:"bytes,3,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - AnimationUrl string `protobuf:"bytes,4,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - OpeningAnimationUrl string `protobuf:"bytes,5,opt,name=opening_animation_url,json=openingAnimationUrl,proto3" json:"opening_animation_url,omitempty"` - OpenedImageUrl string `protobuf:"bytes,6,opt,name=opened_image_url,json=openedImageUrl,proto3" json:"opened_image_url,omitempty"` - InRoomRewards []*RoomTreasureRewardItem `protobuf:"bytes,7,rep,name=in_room_rewards,json=inRoomRewards,proto3" json:"in_room_rewards,omitempty"` - Top1Rewards []*RoomTreasureRewardItem `protobuf:"bytes,8,rep,name=top1_rewards,json=top1Rewards,proto3" json:"top1_rewards,omitempty"` - IgniterRewards []*RoomTreasureRewardItem `protobuf:"bytes,9,rep,name=igniter_rewards,json=igniterRewards,proto3" json:"igniter_rewards,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +// RoomRocketLevel 暴露单个等级火箭的物料、阈值和三类奖励池。 +type RoomRocketLevel struct { + state protoimpl.MessageState `protogen:"open.v1"` + Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` + FuelThreshold int64 `protobuf:"varint,2,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + CoverUrl string `protobuf:"bytes,3,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` + AnimationUrl string `protobuf:"bytes,4,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + LaunchAnimationUrl string `protobuf:"bytes,5,opt,name=launch_animation_url,json=launchAnimationUrl,proto3" json:"launch_animation_url,omitempty"` + LaunchedImageUrl string `protobuf:"bytes,6,opt,name=launched_image_url,json=launchedImageUrl,proto3" json:"launched_image_url,omitempty"` + InRoomRewards []*RoomRocketRewardItem `protobuf:"bytes,7,rep,name=in_room_rewards,json=inRoomRewards,proto3" json:"in_room_rewards,omitempty"` + Top1Rewards []*RoomRocketRewardItem `protobuf:"bytes,8,rep,name=top1_rewards,json=top1Rewards,proto3" json:"top1_rewards,omitempty"` + IgniterRewards []*RoomRocketRewardItem `protobuf:"bytes,9,rep,name=igniter_rewards,json=igniterRewards,proto3" json:"igniter_rewards,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (x *RoomTreasureLevel) Reset() { - *x = RoomTreasureLevel{} +func (x *RoomRocketLevel) Reset() { + *x = RoomRocketLevel{} mi := &file_proto_room_v1_room_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureLevel) String() string { +func (x *RoomRocketLevel) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureLevel) ProtoMessage() {} +func (*RoomRocketLevel) ProtoMessage() {} -func (x *RoomTreasureLevel) ProtoReflect() protoreflect.Message { +func (x *RoomRocketLevel) ProtoReflect() protoreflect.Message { mi := &file_proto_room_v1_room_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -867,76 +867,76 @@ func (x *RoomTreasureLevel) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureLevel.ProtoReflect.Descriptor instead. -func (*RoomTreasureLevel) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketLevel.ProtoReflect.Descriptor instead. +func (*RoomRocketLevel) Descriptor() ([]byte, []int) { return file_proto_room_v1_room_proto_rawDescGZIP(), []int{8} } -func (x *RoomTreasureLevel) GetLevel() int32 { +func (x *RoomRocketLevel) GetLevel() int32 { if x != nil { return x.Level } return 0 } -func (x *RoomTreasureLevel) GetEnergyThreshold() int64 { +func (x *RoomRocketLevel) GetFuelThreshold() int64 { if x != nil { - return x.EnergyThreshold + return x.FuelThreshold } return 0 } -func (x *RoomTreasureLevel) GetCoverUrl() string { +func (x *RoomRocketLevel) GetCoverUrl() string { if x != nil { return x.CoverUrl } return "" } -func (x *RoomTreasureLevel) GetAnimationUrl() string { +func (x *RoomRocketLevel) GetAnimationUrl() string { if x != nil { return x.AnimationUrl } return "" } -func (x *RoomTreasureLevel) GetOpeningAnimationUrl() string { +func (x *RoomRocketLevel) GetLaunchAnimationUrl() string { if x != nil { - return x.OpeningAnimationUrl + return x.LaunchAnimationUrl } return "" } -func (x *RoomTreasureLevel) GetOpenedImageUrl() string { +func (x *RoomRocketLevel) GetLaunchedImageUrl() string { if x != nil { - return x.OpenedImageUrl + return x.LaunchedImageUrl } return "" } -func (x *RoomTreasureLevel) GetInRoomRewards() []*RoomTreasureRewardItem { +func (x *RoomRocketLevel) GetInRoomRewards() []*RoomRocketRewardItem { if x != nil { return x.InRoomRewards } return nil } -func (x *RoomTreasureLevel) GetTop1Rewards() []*RoomTreasureRewardItem { +func (x *RoomRocketLevel) GetTop1Rewards() []*RoomRocketRewardItem { if x != nil { return x.Top1Rewards } return nil } -func (x *RoomTreasureLevel) GetIgniterRewards() []*RoomTreasureRewardItem { +func (x *RoomRocketLevel) GetIgniterRewards() []*RoomRocketRewardItem { if x != nil { return x.IgniterRewards } return nil } -// RoomTreasureRewardGrant 是一次宝箱打开后给某个用户结算出的具体奖励。 -type RoomTreasureRewardGrant struct { +// RoomRocketRewardGrant 是一次火箭打开后给某个用户结算出的具体奖励。 +type RoomRocketRewardGrant struct { state protoimpl.MessageState `protogen:"open.v1"` RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` @@ -950,20 +950,20 @@ type RoomTreasureRewardGrant struct { sizeCache protoimpl.SizeCache } -func (x *RoomTreasureRewardGrant) Reset() { - *x = RoomTreasureRewardGrant{} +func (x *RoomRocketRewardGrant) Reset() { + *x = RoomRocketRewardGrant{} mi := &file_proto_room_v1_room_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureRewardGrant) String() string { +func (x *RoomRocketRewardGrant) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureRewardGrant) ProtoMessage() {} +func (*RoomRocketRewardGrant) ProtoMessage() {} -func (x *RoomTreasureRewardGrant) ProtoReflect() protoreflect.Message { +func (x *RoomRocketRewardGrant) ProtoReflect() protoreflect.Message { mi := &file_proto_room_v1_room_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -975,101 +975,98 @@ func (x *RoomTreasureRewardGrant) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureRewardGrant.ProtoReflect.Descriptor instead. -func (*RoomTreasureRewardGrant) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketRewardGrant.ProtoReflect.Descriptor instead. +func (*RoomRocketRewardGrant) Descriptor() ([]byte, []int) { return file_proto_room_v1_room_proto_rawDescGZIP(), []int{9} } -func (x *RoomTreasureRewardGrant) GetRewardRole() string { +func (x *RoomRocketRewardGrant) GetRewardRole() string { if x != nil { return x.RewardRole } return "" } -func (x *RoomTreasureRewardGrant) GetUserId() int64 { +func (x *RoomRocketRewardGrant) GetUserId() int64 { if x != nil { return x.UserId } return 0 } -func (x *RoomTreasureRewardGrant) GetRewardItemId() string { +func (x *RoomRocketRewardGrant) GetRewardItemId() string { if x != nil { return x.RewardItemId } return "" } -func (x *RoomTreasureRewardGrant) GetResourceGroupId() int64 { +func (x *RoomRocketRewardGrant) GetResourceGroupId() int64 { if x != nil { return x.ResourceGroupId } return 0 } -func (x *RoomTreasureRewardGrant) GetDisplayName() string { +func (x *RoomRocketRewardGrant) GetDisplayName() string { if x != nil { return x.DisplayName } return "" } -func (x *RoomTreasureRewardGrant) GetIconUrl() string { +func (x *RoomRocketRewardGrant) GetIconUrl() string { if x != nil { return x.IconUrl } return "" } -func (x *RoomTreasureRewardGrant) GetGrantId() string { +func (x *RoomRocketRewardGrant) GetGrantId() string { if x != nil { return x.GrantId } return "" } -func (x *RoomTreasureRewardGrant) GetStatus() string { +func (x *RoomRocketRewardGrant) GetStatus() string { if x != nil { return x.Status } return "" } -// RoomTreasureState 是 Room Cell 持有并随快照恢复的当前宝箱状态。 -type RoomTreasureState struct { - state protoimpl.MessageState `protogen:"open.v1"` - CurrentLevel int32 `protobuf:"varint,1,opt,name=current_level,json=currentLevel,proto3" json:"current_level,omitempty"` - CurrentProgress int64 `protobuf:"varint,2,opt,name=current_progress,json=currentProgress,proto3" json:"current_progress,omitempty"` - EnergyThreshold int64 `protobuf:"varint,3,opt,name=energy_threshold,json=energyThreshold,proto3" json:"energy_threshold,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - CountdownStartedAtMs int64 `protobuf:"varint,5,opt,name=countdown_started_at_ms,json=countdownStartedAtMs,proto3" json:"countdown_started_at_ms,omitempty"` - OpenAtMs int64 `protobuf:"varint,6,opt,name=open_at_ms,json=openAtMs,proto3" json:"open_at_ms,omitempty"` - OpenedAtMs int64 `protobuf:"varint,7,opt,name=opened_at_ms,json=openedAtMs,proto3" json:"opened_at_ms,omitempty"` - ResetAtMs int64 `protobuf:"varint,8,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` - IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` - BoxId string `protobuf:"bytes,11,opt,name=box_id,json=boxId,proto3" json:"box_id,omitempty"` - ConfigVersion int64 `protobuf:"varint,12,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` - LastRewards []*RoomTreasureRewardGrant `protobuf:"bytes,13,rep,name=last_rewards,json=lastRewards,proto3" json:"last_rewards,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache +// RoomRocketPendingLaunch 是已经点火、等待延迟发射的单枚火箭。 +type RoomRocketPendingLaunch struct { + state protoimpl.MessageState `protogen:"open.v1"` + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + FuelThreshold int64 `protobuf:"varint,3,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + IgnitedAtMs int64 `protobuf:"varint,4,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` + LaunchAtMs int64 `protobuf:"varint,5,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` + ResetAtMs int64 `protobuf:"varint,6,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + Top1UserId int64 `protobuf:"varint,7,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,8,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + ConfigVersion int64 `protobuf:"varint,9,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + CoverUrl string `protobuf:"bytes,10,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } -func (x *RoomTreasureState) Reset() { - *x = RoomTreasureState{} +func (x *RoomRocketPendingLaunch) Reset() { + *x = RoomRocketPendingLaunch{} mi := &file_proto_room_v1_room_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureState) String() string { +func (x *RoomRocketPendingLaunch) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureState) ProtoMessage() {} +func (*RoomRocketPendingLaunch) ProtoMessage() {} -func (x *RoomTreasureState) ProtoReflect() protoreflect.Message { +func (x *RoomRocketPendingLaunch) ProtoReflect() protoreflect.Message { mi := &file_proto_room_v1_room_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1081,132 +1078,260 @@ func (x *RoomTreasureState) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureState.ProtoReflect.Descriptor instead. -func (*RoomTreasureState) Descriptor() ([]byte, []int) { +// Deprecated: Use RoomRocketPendingLaunch.ProtoReflect.Descriptor instead. +func (*RoomRocketPendingLaunch) Descriptor() ([]byte, []int) { return file_proto_room_v1_room_proto_rawDescGZIP(), []int{10} } -func (x *RoomTreasureState) GetCurrentLevel() int32 { +func (x *RoomRocketPendingLaunch) GetRocketId() string { if x != nil { - return x.CurrentLevel - } - return 0 -} - -func (x *RoomTreasureState) GetCurrentProgress() int64 { - if x != nil { - return x.CurrentProgress - } - return 0 -} - -func (x *RoomTreasureState) GetEnergyThreshold() int64 { - if x != nil { - return x.EnergyThreshold - } - return 0 -} - -func (x *RoomTreasureState) GetStatus() string { - if x != nil { - return x.Status + return x.RocketId } return "" } -func (x *RoomTreasureState) GetCountdownStartedAtMs() int64 { +func (x *RoomRocketPendingLaunch) GetLevel() int32 { if x != nil { - return x.CountdownStartedAtMs + return x.Level } return 0 } -func (x *RoomTreasureState) GetOpenAtMs() int64 { +func (x *RoomRocketPendingLaunch) GetFuelThreshold() int64 { if x != nil { - return x.OpenAtMs + return x.FuelThreshold } return 0 } -func (x *RoomTreasureState) GetOpenedAtMs() int64 { +func (x *RoomRocketPendingLaunch) GetIgnitedAtMs() int64 { if x != nil { - return x.OpenedAtMs + return x.IgnitedAtMs } return 0 } -func (x *RoomTreasureState) GetResetAtMs() int64 { +func (x *RoomRocketPendingLaunch) GetLaunchAtMs() int64 { + if x != nil { + return x.LaunchAtMs + } + return 0 +} + +func (x *RoomRocketPendingLaunch) GetResetAtMs() int64 { if x != nil { return x.ResetAtMs } return 0 } -func (x *RoomTreasureState) GetTop1UserId() int64 { +func (x *RoomRocketPendingLaunch) GetTop1UserId() int64 { if x != nil { return x.Top1UserId } return 0 } -func (x *RoomTreasureState) GetIgniterUserId() int64 { +func (x *RoomRocketPendingLaunch) GetIgniterUserId() int64 { if x != nil { return x.IgniterUserId } return 0 } -func (x *RoomTreasureState) GetBoxId() string { - if x != nil { - return x.BoxId - } - return "" -} - -func (x *RoomTreasureState) GetConfigVersion() int64 { +func (x *RoomRocketPendingLaunch) GetConfigVersion() int64 { if x != nil { return x.ConfigVersion } return 0 } -func (x *RoomTreasureState) GetLastRewards() []*RoomTreasureRewardGrant { +func (x *RoomRocketPendingLaunch) GetCoverUrl() string { + if x != nil { + return x.CoverUrl + } + return "" +} + +// RoomRocketState 是 Room Cell 持有并随快照恢复的当前火箭状态。 +type RoomRocketState struct { + state protoimpl.MessageState `protogen:"open.v1"` + CurrentLevel int32 `protobuf:"varint,1,opt,name=current_level,json=currentLevel,proto3" json:"current_level,omitempty"` + CurrentFuel int64 `protobuf:"varint,2,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` + FuelThreshold int64 `protobuf:"varint,3,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + IgnitedAtMs int64 `protobuf:"varint,5,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` + LaunchAtMs int64 `protobuf:"varint,6,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` + LaunchedAtMs int64 `protobuf:"varint,7,opt,name=launched_at_ms,json=launchedAtMs,proto3" json:"launched_at_ms,omitempty"` + ResetAtMs int64 `protobuf:"varint,8,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + RocketId string `protobuf:"bytes,11,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + ConfigVersion int64 `protobuf:"varint,12,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + LastRewards []*RoomRocketRewardGrant `protobuf:"bytes,13,rep,name=last_rewards,json=lastRewards,proto3" json:"last_rewards,omitempty"` + PendingLaunches []*RoomRocketPendingLaunch `protobuf:"bytes,14,rep,name=pending_launches,json=pendingLaunches,proto3" json:"pending_launches,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoomRocketState) Reset() { + *x = RoomRocketState{} + mi := &file_proto_room_v1_room_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomRocketState) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomRocketState) ProtoMessage() {} + +func (x *RoomRocketState) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[11] + 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 RoomRocketState.ProtoReflect.Descriptor instead. +func (*RoomRocketState) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{11} +} + +func (x *RoomRocketState) GetCurrentLevel() int32 { + if x != nil { + return x.CurrentLevel + } + return 0 +} + +func (x *RoomRocketState) GetCurrentFuel() int64 { + if x != nil { + return x.CurrentFuel + } + return 0 +} + +func (x *RoomRocketState) GetFuelThreshold() int64 { + if x != nil { + return x.FuelThreshold + } + return 0 +} + +func (x *RoomRocketState) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *RoomRocketState) GetIgnitedAtMs() int64 { + if x != nil { + return x.IgnitedAtMs + } + return 0 +} + +func (x *RoomRocketState) GetLaunchAtMs() int64 { + if x != nil { + return x.LaunchAtMs + } + return 0 +} + +func (x *RoomRocketState) GetLaunchedAtMs() int64 { + if x != nil { + return x.LaunchedAtMs + } + return 0 +} + +func (x *RoomRocketState) GetResetAtMs() int64 { + if x != nil { + return x.ResetAtMs + } + return 0 +} + +func (x *RoomRocketState) GetTop1UserId() int64 { + if x != nil { + return x.Top1UserId + } + return 0 +} + +func (x *RoomRocketState) GetIgniterUserId() int64 { + if x != nil { + return x.IgniterUserId + } + return 0 +} + +func (x *RoomRocketState) GetRocketId() string { + if x != nil { + return x.RocketId + } + return "" +} + +func (x *RoomRocketState) GetConfigVersion() int64 { + if x != nil { + return x.ConfigVersion + } + return 0 +} + +func (x *RoomRocketState) GetLastRewards() []*RoomRocketRewardGrant { if x != nil { return x.LastRewards } return nil } -// RoomTreasureInfo 是 App 初始化宝箱 UI 的完整读模型。 -type RoomTreasureInfo struct { +func (x *RoomRocketState) GetPendingLaunches() []*RoomRocketPendingLaunch { + if x != nil { + return x.PendingLaunches + } + return nil +} + +// RoomRocketInfo 是 App 初始化火箭 UI 的完整读模型。 +type RoomRocketInfo struct { state protoimpl.MessageState `protogen:"open.v1"` Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - Levels []*RoomTreasureLevel `protobuf:"bytes,2,rep,name=levels,proto3" json:"levels,omitempty"` - State *RoomTreasureState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + Levels []*RoomRocketLevel `protobuf:"bytes,2,rep,name=levels,proto3" json:"levels,omitempty"` + State *RoomRocketState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` BroadcastScope string `protobuf:"bytes,5,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` - OpenDelayMs int64 `protobuf:"varint,6,opt,name=open_delay_ms,json=openDelayMs,proto3" json:"open_delay_ms,omitempty"` + LaunchDelayMs int64 `protobuf:"varint,6,opt,name=launch_delay_ms,json=launchDelayMs,proto3" json:"launch_delay_ms,omitempty"` BroadcastDelayMs int64 `protobuf:"varint,7,opt,name=broadcast_delay_ms,json=broadcastDelayMs,proto3" json:"broadcast_delay_ms,omitempty"` RewardStackPolicy string `protobuf:"bytes,8,opt,name=reward_stack_policy,json=rewardStackPolicy,proto3" json:"reward_stack_policy,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *RoomTreasureInfo) Reset() { - *x = RoomTreasureInfo{} - mi := &file_proto_room_v1_room_proto_msgTypes[11] +func (x *RoomRocketInfo) Reset() { + *x = RoomRocketInfo{} + mi := &file_proto_room_v1_room_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureInfo) String() string { +func (x *RoomRocketInfo) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureInfo) ProtoMessage() {} +func (*RoomRocketInfo) ProtoMessage() {} -func (x *RoomTreasureInfo) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[11] +func (x *RoomRocketInfo) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1217,95 +1342,95 @@ func (x *RoomTreasureInfo) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureInfo.ProtoReflect.Descriptor instead. -func (*RoomTreasureInfo) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{11} +// Deprecated: Use RoomRocketInfo.ProtoReflect.Descriptor instead. +func (*RoomRocketInfo) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{12} } -func (x *RoomTreasureInfo) GetEnabled() bool { +func (x *RoomRocketInfo) GetEnabled() bool { if x != nil { return x.Enabled } return false } -func (x *RoomTreasureInfo) GetLevels() []*RoomTreasureLevel { +func (x *RoomRocketInfo) GetLevels() []*RoomRocketLevel { if x != nil { return x.Levels } return nil } -func (x *RoomTreasureInfo) GetState() *RoomTreasureState { +func (x *RoomRocketInfo) GetState() *RoomRocketState { if x != nil { return x.State } return nil } -func (x *RoomTreasureInfo) GetServerTimeMs() int64 { +func (x *RoomRocketInfo) GetServerTimeMs() int64 { if x != nil { return x.ServerTimeMs } return 0 } -func (x *RoomTreasureInfo) GetBroadcastScope() string { +func (x *RoomRocketInfo) GetBroadcastScope() string { if x != nil { return x.BroadcastScope } return "" } -func (x *RoomTreasureInfo) GetOpenDelayMs() int64 { +func (x *RoomRocketInfo) GetLaunchDelayMs() int64 { if x != nil { - return x.OpenDelayMs + return x.LaunchDelayMs } return 0 } -func (x *RoomTreasureInfo) GetBroadcastDelayMs() int64 { +func (x *RoomRocketInfo) GetBroadcastDelayMs() int64 { if x != nil { return x.BroadcastDelayMs } return 0 } -func (x *RoomTreasureInfo) GetRewardStackPolicy() string { +func (x *RoomRocketInfo) GetRewardStackPolicy() string { if x != nil { return x.RewardStackPolicy } return "" } -// RoomTreasureGiftEnergyRule 是后台配置的礼物能量覆盖规则。 -type RoomTreasureGiftEnergyRule struct { +// RoomRocketGiftFuelRule 是后台配置的礼物燃料覆盖规则。 +type RoomRocketGiftFuelRule struct { state protoimpl.MessageState `protogen:"open.v1"` RuleId string `protobuf:"bytes,1,opt,name=rule_id,json=ruleId,proto3" json:"rule_id,omitempty"` GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` GiftTypeCode string `protobuf:"bytes,3,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` MultiplierPpm int64 `protobuf:"varint,4,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - FixedEnergy int64 `protobuf:"varint,5,opt,name=fixed_energy,json=fixedEnergy,proto3" json:"fixed_energy,omitempty"` + FixedFuel int64 `protobuf:"varint,5,opt,name=fixed_fuel,json=fixedFuel,proto3" json:"fixed_fuel,omitempty"` Excluded bool `protobuf:"varint,6,opt,name=excluded,proto3" json:"excluded,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *RoomTreasureGiftEnergyRule) Reset() { - *x = RoomTreasureGiftEnergyRule{} - mi := &file_proto_room_v1_room_proto_msgTypes[12] +func (x *RoomRocketGiftFuelRule) Reset() { + *x = RoomRocketGiftFuelRule{} + mi := &file_proto_room_v1_room_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *RoomTreasureGiftEnergyRule) String() string { +func (x *RoomRocketGiftFuelRule) String() string { return protoimpl.X.MessageStringOf(x) } -func (*RoomTreasureGiftEnergyRule) ProtoMessage() {} +func (*RoomRocketGiftFuelRule) ProtoMessage() {} -func (x *RoomTreasureGiftEnergyRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[12] +func (x *RoomRocketGiftFuelRule) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1316,89 +1441,89 @@ func (x *RoomTreasureGiftEnergyRule) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use RoomTreasureGiftEnergyRule.ProtoReflect.Descriptor instead. -func (*RoomTreasureGiftEnergyRule) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{12} +// Deprecated: Use RoomRocketGiftFuelRule.ProtoReflect.Descriptor instead. +func (*RoomRocketGiftFuelRule) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{13} } -func (x *RoomTreasureGiftEnergyRule) GetRuleId() string { +func (x *RoomRocketGiftFuelRule) GetRuleId() string { if x != nil { return x.RuleId } return "" } -func (x *RoomTreasureGiftEnergyRule) GetGiftId() string { +func (x *RoomRocketGiftFuelRule) GetGiftId() string { if x != nil { return x.GiftId } return "" } -func (x *RoomTreasureGiftEnergyRule) GetGiftTypeCode() string { +func (x *RoomRocketGiftFuelRule) GetGiftTypeCode() string { if x != nil { return x.GiftTypeCode } return "" } -func (x *RoomTreasureGiftEnergyRule) GetMultiplierPpm() int64 { +func (x *RoomRocketGiftFuelRule) GetMultiplierPpm() int64 { if x != nil { return x.MultiplierPpm } return 0 } -func (x *RoomTreasureGiftEnergyRule) GetFixedEnergy() int64 { +func (x *RoomRocketGiftFuelRule) GetFixedFuel() int64 { if x != nil { - return x.FixedEnergy + return x.FixedFuel } return 0 } -func (x *RoomTreasureGiftEnergyRule) GetExcluded() bool { +func (x *RoomRocketGiftFuelRule) GetExcluded() bool { if x != nil { return x.Excluded } return false } -// AdminRoomTreasureConfig 是后台管理读写的完整宝箱配置。 -type AdminRoomTreasureConfig 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"` - ConfigVersion int64 `protobuf:"varint,3,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` - EnergySource string `protobuf:"bytes,4,opt,name=energy_source,json=energySource,proto3" json:"energy_source,omitempty"` - OpenDelayMs int64 `protobuf:"varint,5,opt,name=open_delay_ms,json=openDelayMs,proto3" json:"open_delay_ms,omitempty"` - BroadcastEnabled bool `protobuf:"varint,6,opt,name=broadcast_enabled,json=broadcastEnabled,proto3" json:"broadcast_enabled,omitempty"` - BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` - BroadcastDelayMs int64 `protobuf:"varint,8,opt,name=broadcast_delay_ms,json=broadcastDelayMs,proto3" json:"broadcast_delay_ms,omitempty"` - RewardStackPolicy string `protobuf:"bytes,9,opt,name=reward_stack_policy,json=rewardStackPolicy,proto3" json:"reward_stack_policy,omitempty"` - Levels []*RoomTreasureLevel `protobuf:"bytes,10,rep,name=levels,proto3" json:"levels,omitempty"` - GiftEnergyRules []*RoomTreasureGiftEnergyRule `protobuf:"bytes,11,rep,name=gift_energy_rules,json=giftEnergyRules,proto3" json:"gift_energy_rules,omitempty"` - UpdatedByAdminId int64 `protobuf:"varint,12,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,14,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` +// AdminRoomRocketConfig 是后台管理读写的完整火箭配置。 +type AdminRoomRocketConfig 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"` + ConfigVersion int64 `protobuf:"varint,3,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + FuelSource string `protobuf:"bytes,4,opt,name=fuel_source,json=fuelSource,proto3" json:"fuel_source,omitempty"` + LaunchDelayMs int64 `protobuf:"varint,5,opt,name=launch_delay_ms,json=launchDelayMs,proto3" json:"launch_delay_ms,omitempty"` + BroadcastEnabled bool `protobuf:"varint,6,opt,name=broadcast_enabled,json=broadcastEnabled,proto3" json:"broadcast_enabled,omitempty"` + BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` + BroadcastDelayMs int64 `protobuf:"varint,8,opt,name=broadcast_delay_ms,json=broadcastDelayMs,proto3" json:"broadcast_delay_ms,omitempty"` + RewardStackPolicy string `protobuf:"bytes,9,opt,name=reward_stack_policy,json=rewardStackPolicy,proto3" json:"reward_stack_policy,omitempty"` + Levels []*RoomRocketLevel `protobuf:"bytes,10,rep,name=levels,proto3" json:"levels,omitempty"` + GiftFuelRules []*RoomRocketGiftFuelRule `protobuf:"bytes,11,rep,name=gift_fuel_rules,json=giftFuelRules,proto3" json:"gift_fuel_rules,omitempty"` + UpdatedByAdminId int64 `protobuf:"varint,12,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,14,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *AdminRoomTreasureConfig) Reset() { - *x = AdminRoomTreasureConfig{} - mi := &file_proto_room_v1_room_proto_msgTypes[13] +func (x *AdminRoomRocketConfig) Reset() { + *x = AdminRoomRocketConfig{} + mi := &file_proto_room_v1_room_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *AdminRoomTreasureConfig) String() string { +func (x *AdminRoomRocketConfig) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AdminRoomTreasureConfig) ProtoMessage() {} +func (*AdminRoomRocketConfig) ProtoMessage() {} -func (x *AdminRoomTreasureConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[13] +func (x *AdminRoomRocketConfig) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1409,131 +1534,131 @@ func (x *AdminRoomTreasureConfig) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use AdminRoomTreasureConfig.ProtoReflect.Descriptor instead. -func (*AdminRoomTreasureConfig) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{13} +// Deprecated: Use AdminRoomRocketConfig.ProtoReflect.Descriptor instead. +func (*AdminRoomRocketConfig) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{14} } -func (x *AdminRoomTreasureConfig) GetAppCode() string { +func (x *AdminRoomRocketConfig) GetAppCode() string { if x != nil { return x.AppCode } return "" } -func (x *AdminRoomTreasureConfig) GetEnabled() bool { +func (x *AdminRoomRocketConfig) GetEnabled() bool { if x != nil { return x.Enabled } return false } -func (x *AdminRoomTreasureConfig) GetConfigVersion() int64 { +func (x *AdminRoomRocketConfig) GetConfigVersion() int64 { if x != nil { return x.ConfigVersion } return 0 } -func (x *AdminRoomTreasureConfig) GetEnergySource() string { +func (x *AdminRoomRocketConfig) GetFuelSource() string { if x != nil { - return x.EnergySource + return x.FuelSource } return "" } -func (x *AdminRoomTreasureConfig) GetOpenDelayMs() int64 { +func (x *AdminRoomRocketConfig) GetLaunchDelayMs() int64 { if x != nil { - return x.OpenDelayMs + return x.LaunchDelayMs } return 0 } -func (x *AdminRoomTreasureConfig) GetBroadcastEnabled() bool { +func (x *AdminRoomRocketConfig) GetBroadcastEnabled() bool { if x != nil { return x.BroadcastEnabled } return false } -func (x *AdminRoomTreasureConfig) GetBroadcastScope() string { +func (x *AdminRoomRocketConfig) GetBroadcastScope() string { if x != nil { return x.BroadcastScope } return "" } -func (x *AdminRoomTreasureConfig) GetBroadcastDelayMs() int64 { +func (x *AdminRoomRocketConfig) GetBroadcastDelayMs() int64 { if x != nil { return x.BroadcastDelayMs } return 0 } -func (x *AdminRoomTreasureConfig) GetRewardStackPolicy() string { +func (x *AdminRoomRocketConfig) GetRewardStackPolicy() string { if x != nil { return x.RewardStackPolicy } return "" } -func (x *AdminRoomTreasureConfig) GetLevels() []*RoomTreasureLevel { +func (x *AdminRoomRocketConfig) GetLevels() []*RoomRocketLevel { if x != nil { return x.Levels } return nil } -func (x *AdminRoomTreasureConfig) GetGiftEnergyRules() []*RoomTreasureGiftEnergyRule { +func (x *AdminRoomRocketConfig) GetGiftFuelRules() []*RoomRocketGiftFuelRule { if x != nil { - return x.GiftEnergyRules + return x.GiftFuelRules } return nil } -func (x *AdminRoomTreasureConfig) GetUpdatedByAdminId() int64 { +func (x *AdminRoomRocketConfig) GetUpdatedByAdminId() int64 { if x != nil { return x.UpdatedByAdminId } return 0 } -func (x *AdminRoomTreasureConfig) GetCreatedAtMs() int64 { +func (x *AdminRoomRocketConfig) GetCreatedAtMs() int64 { if x != nil { return x.CreatedAtMs } return 0 } -func (x *AdminRoomTreasureConfig) GetUpdatedAtMs() int64 { +func (x *AdminRoomRocketConfig) GetUpdatedAtMs() int64 { if x != nil { return x.UpdatedAtMs } return 0 } -type AdminGetRoomTreasureConfigRequest struct { +type AdminGetRoomRocketConfigRequest 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 *AdminGetRoomTreasureConfigRequest) Reset() { - *x = AdminGetRoomTreasureConfigRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[14] +func (x *AdminGetRoomRocketConfigRequest) Reset() { + *x = AdminGetRoomRocketConfigRequest{} + mi := &file_proto_room_v1_room_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *AdminGetRoomTreasureConfigRequest) String() string { +func (x *AdminGetRoomRocketConfigRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AdminGetRoomTreasureConfigRequest) ProtoMessage() {} +func (*AdminGetRoomRocketConfigRequest) ProtoMessage() {} -func (x *AdminGetRoomTreasureConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[14] +func (x *AdminGetRoomRocketConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1544,41 +1669,41 @@ func (x *AdminGetRoomTreasureConfigRequest) ProtoReflect() protoreflect.Message return mi.MessageOf(x) } -// Deprecated: Use AdminGetRoomTreasureConfigRequest.ProtoReflect.Descriptor instead. -func (*AdminGetRoomTreasureConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{14} +// Deprecated: Use AdminGetRoomRocketConfigRequest.ProtoReflect.Descriptor instead. +func (*AdminGetRoomRocketConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{15} } -func (x *AdminGetRoomTreasureConfigRequest) GetMeta() *RequestMeta { +func (x *AdminGetRoomRocketConfigRequest) GetMeta() *RequestMeta { if x != nil { return x.Meta } return nil } -type AdminGetRoomTreasureConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomTreasureConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` +type AdminGetRoomRocketConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *AdminGetRoomTreasureConfigResponse) Reset() { - *x = AdminGetRoomTreasureConfigResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[15] +func (x *AdminGetRoomRocketConfigResponse) Reset() { + *x = AdminGetRoomRocketConfigResponse{} + mi := &file_proto_room_v1_room_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *AdminGetRoomTreasureConfigResponse) String() string { +func (x *AdminGetRoomRocketConfigResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AdminGetRoomTreasureConfigResponse) ProtoMessage() {} +func (*AdminGetRoomRocketConfigResponse) ProtoMessage() {} -func (x *AdminGetRoomTreasureConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[15] +func (x *AdminGetRoomRocketConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1589,49 +1714,49 @@ func (x *AdminGetRoomTreasureConfigResponse) ProtoReflect() protoreflect.Message return mi.MessageOf(x) } -// Deprecated: Use AdminGetRoomTreasureConfigResponse.ProtoReflect.Descriptor instead. -func (*AdminGetRoomTreasureConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{15} +// Deprecated: Use AdminGetRoomRocketConfigResponse.ProtoReflect.Descriptor instead. +func (*AdminGetRoomRocketConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{16} } -func (x *AdminGetRoomTreasureConfigResponse) GetConfig() *AdminRoomTreasureConfig { +func (x *AdminGetRoomRocketConfigResponse) GetConfig() *AdminRoomRocketConfig { if x != nil { return x.Config } return nil } -func (x *AdminGetRoomTreasureConfigResponse) GetServerTimeMs() int64 { +func (x *AdminGetRoomRocketConfigResponse) GetServerTimeMs() int64 { if x != nil { return x.ServerTimeMs } return 0 } -type AdminUpdateRoomTreasureConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Config *AdminRoomTreasureConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - AdminId int64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` +type AdminUpdateRoomRocketConfigRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Config *AdminRoomRocketConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + AdminId int64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *AdminUpdateRoomTreasureConfigRequest) Reset() { - *x = AdminUpdateRoomTreasureConfigRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[16] +func (x *AdminUpdateRoomRocketConfigRequest) Reset() { + *x = AdminUpdateRoomRocketConfigRequest{} + mi := &file_proto_room_v1_room_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *AdminUpdateRoomTreasureConfigRequest) String() string { +func (x *AdminUpdateRoomRocketConfigRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AdminUpdateRoomTreasureConfigRequest) ProtoMessage() {} +func (*AdminUpdateRoomRocketConfigRequest) ProtoMessage() {} -func (x *AdminUpdateRoomTreasureConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[16] +func (x *AdminUpdateRoomRocketConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[17] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1642,55 +1767,55 @@ func (x *AdminUpdateRoomTreasureConfigRequest) ProtoReflect() protoreflect.Messa return mi.MessageOf(x) } -// Deprecated: Use AdminUpdateRoomTreasureConfigRequest.ProtoReflect.Descriptor instead. -func (*AdminUpdateRoomTreasureConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{16} +// Deprecated: Use AdminUpdateRoomRocketConfigRequest.ProtoReflect.Descriptor instead. +func (*AdminUpdateRoomRocketConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{17} } -func (x *AdminUpdateRoomTreasureConfigRequest) GetMeta() *RequestMeta { +func (x *AdminUpdateRoomRocketConfigRequest) GetMeta() *RequestMeta { if x != nil { return x.Meta } return nil } -func (x *AdminUpdateRoomTreasureConfigRequest) GetConfig() *AdminRoomTreasureConfig { +func (x *AdminUpdateRoomRocketConfigRequest) GetConfig() *AdminRoomRocketConfig { if x != nil { return x.Config } return nil } -func (x *AdminUpdateRoomTreasureConfigRequest) GetAdminId() int64 { +func (x *AdminUpdateRoomRocketConfigRequest) GetAdminId() int64 { if x != nil { return x.AdminId } return 0 } -type AdminUpdateRoomTreasureConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomTreasureConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` +type AdminUpdateRoomRocketConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *AdminUpdateRoomTreasureConfigResponse) Reset() { - *x = AdminUpdateRoomTreasureConfigResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[17] +func (x *AdminUpdateRoomRocketConfigResponse) Reset() { + *x = AdminUpdateRoomRocketConfigResponse{} + mi := &file_proto_room_v1_room_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *AdminUpdateRoomTreasureConfigResponse) String() string { +func (x *AdminUpdateRoomRocketConfigResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*AdminUpdateRoomTreasureConfigResponse) ProtoMessage() {} +func (*AdminUpdateRoomRocketConfigResponse) ProtoMessage() {} -func (x *AdminUpdateRoomTreasureConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[17] +func (x *AdminUpdateRoomRocketConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[18] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1701,19 +1826,19 @@ func (x *AdminUpdateRoomTreasureConfigResponse) ProtoReflect() protoreflect.Mess return mi.MessageOf(x) } -// Deprecated: Use AdminUpdateRoomTreasureConfigResponse.ProtoReflect.Descriptor instead. -func (*AdminUpdateRoomTreasureConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{17} +// Deprecated: Use AdminUpdateRoomRocketConfigResponse.ProtoReflect.Descriptor instead. +func (*AdminUpdateRoomRocketConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{18} } -func (x *AdminUpdateRoomTreasureConfigResponse) GetConfig() *AdminRoomTreasureConfig { +func (x *AdminUpdateRoomRocketConfigResponse) GetConfig() *AdminRoomRocketConfig { if x != nil { return x.Config } return nil } -func (x *AdminUpdateRoomTreasureConfigResponse) GetServerTimeMs() int64 { +func (x *AdminUpdateRoomRocketConfigResponse) GetServerTimeMs() int64 { if x != nil { return x.ServerTimeMs } @@ -1732,7 +1857,7 @@ type AdminRoomSeatConfig struct { func (x *AdminRoomSeatConfig) Reset() { *x = AdminRoomSeatConfig{} - mi := &file_proto_room_v1_room_proto_msgTypes[18] + mi := &file_proto_room_v1_room_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1744,7 +1869,7 @@ func (x *AdminRoomSeatConfig) String() string { func (*AdminRoomSeatConfig) ProtoMessage() {} func (x *AdminRoomSeatConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[18] + mi := &file_proto_room_v1_room_proto_msgTypes[19] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1757,7 +1882,7 @@ func (x *AdminRoomSeatConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminRoomSeatConfig.ProtoReflect.Descriptor instead. func (*AdminRoomSeatConfig) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{18} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{19} } func (x *AdminRoomSeatConfig) GetCandidateSeatCounts() []int32 { @@ -1797,7 +1922,7 @@ type AdminGetRoomSeatConfigRequest struct { func (x *AdminGetRoomSeatConfigRequest) Reset() { *x = AdminGetRoomSeatConfigRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[19] + mi := &file_proto_room_v1_room_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1809,7 +1934,7 @@ func (x *AdminGetRoomSeatConfigRequest) String() string { func (*AdminGetRoomSeatConfigRequest) ProtoMessage() {} func (x *AdminGetRoomSeatConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[19] + mi := &file_proto_room_v1_room_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1822,7 +1947,7 @@ func (x *AdminGetRoomSeatConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomSeatConfigRequest.ProtoReflect.Descriptor instead. func (*AdminGetRoomSeatConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{19} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{20} } func (x *AdminGetRoomSeatConfigRequest) GetMeta() *RequestMeta { @@ -1842,7 +1967,7 @@ type AdminGetRoomSeatConfigResponse struct { func (x *AdminGetRoomSeatConfigResponse) Reset() { *x = AdminGetRoomSeatConfigResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[20] + mi := &file_proto_room_v1_room_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1854,7 +1979,7 @@ func (x *AdminGetRoomSeatConfigResponse) String() string { func (*AdminGetRoomSeatConfigResponse) ProtoMessage() {} func (x *AdminGetRoomSeatConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[20] + mi := &file_proto_room_v1_room_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1867,7 +1992,7 @@ func (x *AdminGetRoomSeatConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomSeatConfigResponse.ProtoReflect.Descriptor instead. func (*AdminGetRoomSeatConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{20} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{21} } func (x *AdminGetRoomSeatConfigResponse) GetConfig() *AdminRoomSeatConfig { @@ -1895,7 +2020,7 @@ type AdminUpdateRoomSeatConfigRequest struct { func (x *AdminUpdateRoomSeatConfigRequest) Reset() { *x = AdminUpdateRoomSeatConfigRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[21] + mi := &file_proto_room_v1_room_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1907,7 +2032,7 @@ func (x *AdminUpdateRoomSeatConfigRequest) String() string { func (*AdminUpdateRoomSeatConfigRequest) ProtoMessage() {} func (x *AdminUpdateRoomSeatConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[21] + mi := &file_proto_room_v1_room_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1920,7 +2045,7 @@ func (x *AdminUpdateRoomSeatConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminUpdateRoomSeatConfigRequest.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomSeatConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{21} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{22} } func (x *AdminUpdateRoomSeatConfigRequest) GetMeta() *RequestMeta { @@ -1954,7 +2079,7 @@ type AdminUpdateRoomSeatConfigResponse struct { func (x *AdminUpdateRoomSeatConfigResponse) Reset() { *x = AdminUpdateRoomSeatConfigResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[22] + mi := &file_proto_room_v1_room_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1966,7 +2091,7 @@ func (x *AdminUpdateRoomSeatConfigResponse) String() string { func (*AdminUpdateRoomSeatConfigResponse) ProtoMessage() {} func (x *AdminUpdateRoomSeatConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[22] + mi := &file_proto_room_v1_room_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1979,7 +2104,7 @@ func (x *AdminUpdateRoomSeatConfigResponse) ProtoReflect() protoreflect.Message // Deprecated: Use AdminUpdateRoomSeatConfigResponse.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomSeatConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{22} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{23} } func (x *AdminUpdateRoomSeatConfigResponse) GetConfig() *AdminRoomSeatConfig { @@ -2011,7 +2136,7 @@ type AdminRoomPinRoom struct { func (x *AdminRoomPinRoom) Reset() { *x = AdminRoomPinRoom{} - mi := &file_proto_room_v1_room_proto_msgTypes[23] + mi := &file_proto_room_v1_room_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2023,7 +2148,7 @@ func (x *AdminRoomPinRoom) String() string { func (*AdminRoomPinRoom) ProtoMessage() {} func (x *AdminRoomPinRoom) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[23] + mi := &file_proto_room_v1_room_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2036,7 +2161,7 @@ func (x *AdminRoomPinRoom) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminRoomPinRoom.ProtoReflect.Descriptor instead. func (*AdminRoomPinRoom) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{23} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{24} } func (x *AdminRoomPinRoom) GetRoomId() string { @@ -2109,7 +2234,7 @@ type AdminRoomPin struct { func (x *AdminRoomPin) Reset() { *x = AdminRoomPin{} - mi := &file_proto_room_v1_room_proto_msgTypes[24] + mi := &file_proto_room_v1_room_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2121,7 +2246,7 @@ func (x *AdminRoomPin) String() string { func (*AdminRoomPin) ProtoMessage() {} func (x *AdminRoomPin) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[24] + mi := &file_proto_room_v1_room_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2134,7 +2259,7 @@ func (x *AdminRoomPin) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminRoomPin.ProtoReflect.Descriptor instead. func (*AdminRoomPin) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{24} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{25} } func (x *AdminRoomPin) GetId() int64 { @@ -2242,7 +2367,7 @@ type AdminListRoomPinsRequest struct { func (x *AdminListRoomPinsRequest) Reset() { *x = AdminListRoomPinsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[25] + mi := &file_proto_room_v1_room_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2254,7 +2379,7 @@ func (x *AdminListRoomPinsRequest) String() string { func (*AdminListRoomPinsRequest) ProtoMessage() {} func (x *AdminListRoomPinsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[25] + mi := &file_proto_room_v1_room_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2267,7 +2392,7 @@ func (x *AdminListRoomPinsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomPinsRequest.ProtoReflect.Descriptor instead. func (*AdminListRoomPinsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{25} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{26} } func (x *AdminListRoomPinsRequest) GetMeta() *RequestMeta { @@ -2323,7 +2448,7 @@ type AdminListRoomPinsResponse struct { func (x *AdminListRoomPinsResponse) Reset() { *x = AdminListRoomPinsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[26] + mi := &file_proto_room_v1_room_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2335,7 +2460,7 @@ func (x *AdminListRoomPinsResponse) String() string { func (*AdminListRoomPinsResponse) ProtoMessage() {} func (x *AdminListRoomPinsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[26] + mi := &file_proto_room_v1_room_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2348,7 +2473,7 @@ func (x *AdminListRoomPinsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomPinsResponse.ProtoReflect.Descriptor instead. func (*AdminListRoomPinsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{26} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{27} } func (x *AdminListRoomPinsResponse) GetPins() []*AdminRoomPin { @@ -2385,7 +2510,7 @@ type AdminCreateRoomPinRequest struct { func (x *AdminCreateRoomPinRequest) Reset() { *x = AdminCreateRoomPinRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[27] + mi := &file_proto_room_v1_room_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2397,7 +2522,7 @@ func (x *AdminCreateRoomPinRequest) String() string { func (*AdminCreateRoomPinRequest) ProtoMessage() {} func (x *AdminCreateRoomPinRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[27] + mi := &file_proto_room_v1_room_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2410,7 +2535,7 @@ func (x *AdminCreateRoomPinRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCreateRoomPinRequest.ProtoReflect.Descriptor instead. func (*AdminCreateRoomPinRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{27} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{28} } func (x *AdminCreateRoomPinRequest) GetMeta() *RequestMeta { @@ -2458,7 +2583,7 @@ type AdminCreateRoomPinResponse struct { func (x *AdminCreateRoomPinResponse) Reset() { *x = AdminCreateRoomPinResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[28] + mi := &file_proto_room_v1_room_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2470,7 +2595,7 @@ func (x *AdminCreateRoomPinResponse) String() string { func (*AdminCreateRoomPinResponse) ProtoMessage() {} func (x *AdminCreateRoomPinResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[28] + mi := &file_proto_room_v1_room_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2483,7 +2608,7 @@ func (x *AdminCreateRoomPinResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCreateRoomPinResponse.ProtoReflect.Descriptor instead. func (*AdminCreateRoomPinResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{28} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{29} } func (x *AdminCreateRoomPinResponse) GetPin() *AdminRoomPin { @@ -2511,7 +2636,7 @@ type AdminCancelRoomPinRequest struct { func (x *AdminCancelRoomPinRequest) Reset() { *x = AdminCancelRoomPinRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[29] + mi := &file_proto_room_v1_room_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2523,7 +2648,7 @@ func (x *AdminCancelRoomPinRequest) String() string { func (*AdminCancelRoomPinRequest) ProtoMessage() {} func (x *AdminCancelRoomPinRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[29] + mi := &file_proto_room_v1_room_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2536,7 +2661,7 @@ func (x *AdminCancelRoomPinRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCancelRoomPinRequest.ProtoReflect.Descriptor instead. func (*AdminCancelRoomPinRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{29} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{30} } func (x *AdminCancelRoomPinRequest) GetMeta() *RequestMeta { @@ -2570,7 +2695,7 @@ type AdminCancelRoomPinResponse struct { func (x *AdminCancelRoomPinResponse) Reset() { *x = AdminCancelRoomPinResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[30] + mi := &file_proto_room_v1_room_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2582,7 +2707,7 @@ func (x *AdminCancelRoomPinResponse) String() string { func (*AdminCancelRoomPinResponse) ProtoMessage() {} func (x *AdminCancelRoomPinResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[30] + mi := &file_proto_room_v1_room_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2595,7 +2720,7 @@ func (x *AdminCancelRoomPinResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminCancelRoomPinResponse.ProtoReflect.Descriptor instead. func (*AdminCancelRoomPinResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{30} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{31} } func (x *AdminCancelRoomPinResponse) GetPin() *AdminRoomPin { @@ -2626,7 +2751,7 @@ type RoomBanState struct { func (x *RoomBanState) Reset() { *x = RoomBanState{} - mi := &file_proto_room_v1_room_proto_msgTypes[31] + mi := &file_proto_room_v1_room_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2638,7 +2763,7 @@ func (x *RoomBanState) String() string { func (*RoomBanState) ProtoMessage() {} func (x *RoomBanState) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[31] + mi := &file_proto_room_v1_room_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2651,7 +2776,7 @@ func (x *RoomBanState) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBanState.ProtoReflect.Descriptor instead. func (*RoomBanState) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{31} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{32} } func (x *RoomBanState) GetUserId() int64 { @@ -2704,8 +2829,8 @@ type RoomSnapshot struct { VisibleRegionId int64 `protobuf:"varint,18,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` // locked 只表达房间是否需要入房密码;具体密码哈希不对外映射到 HTTP JSON。 Locked bool `protobuf:"varint,19,opt,name=locked,proto3" json:"locked,omitempty"` - // treasure 是语音房宝箱当前状态;配置物料通过 GetRoomTreasure 单独读取,避免快照过大。 - Treasure *RoomTreasureState `protobuf:"bytes,20,opt,name=treasure,proto3" json:"treasure,omitempty"` + // rocket 是语音房火箭当前状态;配置物料通过 GetRoomRocket 单独读取,避免快照过大。 + Rocket *RoomRocketState `protobuf:"bytes,20,opt,name=rocket,proto3" json:"rocket,omitempty"` // ban_states 保存 ban 的过期边界;ban_user_ids 仍只服务简单集合判断。 BanStates []*RoomBanState `protobuf:"bytes,21,rep,name=ban_states,json=banStates,proto3" json:"ban_states,omitempty"` unknownFields protoimpl.UnknownFields @@ -2714,7 +2839,7 @@ type RoomSnapshot struct { func (x *RoomSnapshot) Reset() { *x = RoomSnapshot{} - mi := &file_proto_room_v1_room_proto_msgTypes[32] + mi := &file_proto_room_v1_room_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2726,7 +2851,7 @@ func (x *RoomSnapshot) String() string { func (*RoomSnapshot) ProtoMessage() {} func (x *RoomSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[32] + mi := &file_proto_room_v1_room_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2739,7 +2864,7 @@ func (x *RoomSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomSnapshot.ProtoReflect.Descriptor instead. func (*RoomSnapshot) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{32} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{33} } func (x *RoomSnapshot) GetRoomId() string { @@ -2868,9 +2993,9 @@ func (x *RoomSnapshot) GetLocked() bool { return false } -func (x *RoomSnapshot) GetTreasure() *RoomTreasureState { +func (x *RoomSnapshot) GetRocket() *RoomRocketState { if x != nil { - return x.Treasure + return x.Rocket } return nil } @@ -2898,7 +3023,7 @@ type RoomBackgroundImage struct { func (x *RoomBackgroundImage) Reset() { *x = RoomBackgroundImage{} - mi := &file_proto_room_v1_room_proto_msgTypes[33] + mi := &file_proto_room_v1_room_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2910,7 +3035,7 @@ func (x *RoomBackgroundImage) String() string { func (*RoomBackgroundImage) ProtoMessage() {} func (x *RoomBackgroundImage) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[33] + mi := &file_proto_room_v1_room_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2923,7 +3048,7 @@ func (x *RoomBackgroundImage) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBackgroundImage.ProtoReflect.Descriptor instead. func (*RoomBackgroundImage) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{33} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{34} } func (x *RoomBackgroundImage) GetBackgroundId() int64 { @@ -2979,7 +3104,7 @@ type SaveRoomBackgroundRequest struct { func (x *SaveRoomBackgroundRequest) Reset() { *x = SaveRoomBackgroundRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[34] + mi := &file_proto_room_v1_room_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2991,7 +3116,7 @@ func (x *SaveRoomBackgroundRequest) String() string { func (*SaveRoomBackgroundRequest) ProtoMessage() {} func (x *SaveRoomBackgroundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[34] + mi := &file_proto_room_v1_room_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3004,7 +3129,7 @@ func (x *SaveRoomBackgroundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveRoomBackgroundRequest.ProtoReflect.Descriptor instead. func (*SaveRoomBackgroundRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{34} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{35} } func (x *SaveRoomBackgroundRequest) GetMeta() *RequestMeta { @@ -3038,7 +3163,7 @@ type SaveRoomBackgroundResponse struct { func (x *SaveRoomBackgroundResponse) Reset() { *x = SaveRoomBackgroundResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[35] + mi := &file_proto_room_v1_room_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3050,7 +3175,7 @@ func (x *SaveRoomBackgroundResponse) String() string { func (*SaveRoomBackgroundResponse) ProtoMessage() {} func (x *SaveRoomBackgroundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[35] + mi := &file_proto_room_v1_room_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3063,7 +3188,7 @@ func (x *SaveRoomBackgroundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveRoomBackgroundResponse.ProtoReflect.Descriptor instead. func (*SaveRoomBackgroundResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{35} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{36} } func (x *SaveRoomBackgroundResponse) GetBackground() *RoomBackgroundImage { @@ -3091,7 +3216,7 @@ type ListRoomBackgroundsRequest struct { func (x *ListRoomBackgroundsRequest) Reset() { *x = ListRoomBackgroundsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[36] + mi := &file_proto_room_v1_room_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3103,7 +3228,7 @@ func (x *ListRoomBackgroundsRequest) String() string { func (*ListRoomBackgroundsRequest) ProtoMessage() {} func (x *ListRoomBackgroundsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[36] + mi := &file_proto_room_v1_room_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3116,7 +3241,7 @@ func (x *ListRoomBackgroundsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBackgroundsRequest.ProtoReflect.Descriptor instead. func (*ListRoomBackgroundsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{36} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{37} } func (x *ListRoomBackgroundsRequest) GetMeta() *RequestMeta { @@ -3151,7 +3276,7 @@ type ListRoomBackgroundsResponse struct { func (x *ListRoomBackgroundsResponse) Reset() { *x = ListRoomBackgroundsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[37] + mi := &file_proto_room_v1_room_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3163,7 +3288,7 @@ func (x *ListRoomBackgroundsResponse) String() string { func (*ListRoomBackgroundsResponse) ProtoMessage() {} func (x *ListRoomBackgroundsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[37] + mi := &file_proto_room_v1_room_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3176,7 +3301,7 @@ func (x *ListRoomBackgroundsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBackgroundsResponse.ProtoReflect.Descriptor instead. func (*ListRoomBackgroundsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{37} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{38} } func (x *ListRoomBackgroundsResponse) GetBackgrounds() []*RoomBackgroundImage { @@ -3210,7 +3335,7 @@ type SetRoomBackgroundRequest struct { func (x *SetRoomBackgroundRequest) Reset() { *x = SetRoomBackgroundRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[38] + mi := &file_proto_room_v1_room_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3222,7 +3347,7 @@ func (x *SetRoomBackgroundRequest) String() string { func (*SetRoomBackgroundRequest) ProtoMessage() {} func (x *SetRoomBackgroundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[38] + mi := &file_proto_room_v1_room_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3235,7 +3360,7 @@ func (x *SetRoomBackgroundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomBackgroundRequest.ProtoReflect.Descriptor instead. func (*SetRoomBackgroundRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{38} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{39} } func (x *SetRoomBackgroundRequest) GetMeta() *RequestMeta { @@ -3263,7 +3388,7 @@ type SetRoomBackgroundResponse struct { func (x *SetRoomBackgroundResponse) Reset() { *x = SetRoomBackgroundResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[39] + mi := &file_proto_room_v1_room_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3275,7 +3400,7 @@ func (x *SetRoomBackgroundResponse) String() string { func (*SetRoomBackgroundResponse) ProtoMessage() {} func (x *SetRoomBackgroundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[39] + mi := &file_proto_room_v1_room_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3288,7 +3413,7 @@ func (x *SetRoomBackgroundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomBackgroundResponse.ProtoReflect.Descriptor instead. func (*SetRoomBackgroundResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{39} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{40} } func (x *SetRoomBackgroundResponse) GetResult() *CommandResult { @@ -3338,7 +3463,7 @@ type CreateRoomRequest struct { func (x *CreateRoomRequest) Reset() { *x = CreateRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[40] + mi := &file_proto_room_v1_room_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3350,7 +3475,7 @@ func (x *CreateRoomRequest) String() string { func (*CreateRoomRequest) ProtoMessage() {} func (x *CreateRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[40] + mi := &file_proto_room_v1_room_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3363,7 +3488,7 @@ func (x *CreateRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRoomRequest.ProtoReflect.Descriptor instead. func (*CreateRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{40} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{41} } func (x *CreateRoomRequest) GetMeta() *RequestMeta { @@ -3433,7 +3558,7 @@ type CreateRoomResponse struct { func (x *CreateRoomResponse) Reset() { *x = CreateRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[41] + mi := &file_proto_room_v1_room_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3445,7 +3570,7 @@ func (x *CreateRoomResponse) String() string { func (*CreateRoomResponse) ProtoMessage() {} func (x *CreateRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[41] + mi := &file_proto_room_v1_room_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3458,7 +3583,7 @@ func (x *CreateRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRoomResponse.ProtoReflect.Descriptor instead. func (*CreateRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{41} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{42} } func (x *CreateRoomResponse) GetResult() *CommandResult { @@ -3490,7 +3615,7 @@ type UpdateRoomProfileRequest struct { func (x *UpdateRoomProfileRequest) Reset() { *x = UpdateRoomProfileRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[42] + mi := &file_proto_room_v1_room_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3502,7 +3627,7 @@ func (x *UpdateRoomProfileRequest) String() string { func (*UpdateRoomProfileRequest) ProtoMessage() {} func (x *UpdateRoomProfileRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[42] + mi := &file_proto_room_v1_room_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3515,7 +3640,7 @@ func (x *UpdateRoomProfileRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRoomProfileRequest.ProtoReflect.Descriptor instead. func (*UpdateRoomProfileRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{42} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{43} } func (x *UpdateRoomProfileRequest) GetMeta() *RequestMeta { @@ -3564,7 +3689,7 @@ type UpdateRoomProfileResponse struct { func (x *UpdateRoomProfileResponse) Reset() { *x = UpdateRoomProfileResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[43] + mi := &file_proto_room_v1_room_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3576,7 +3701,7 @@ func (x *UpdateRoomProfileResponse) String() string { func (*UpdateRoomProfileResponse) ProtoMessage() {} func (x *UpdateRoomProfileResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[43] + mi := &file_proto_room_v1_room_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3589,7 +3714,7 @@ func (x *UpdateRoomProfileResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRoomProfileResponse.ProtoReflect.Descriptor instead. func (*UpdateRoomProfileResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{43} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{44} } func (x *UpdateRoomProfileResponse) GetResult() *CommandResult { @@ -3624,7 +3749,7 @@ type RoomEntryVehicleSnapshot struct { func (x *RoomEntryVehicleSnapshot) Reset() { *x = RoomEntryVehicleSnapshot{} - mi := &file_proto_room_v1_room_proto_msgTypes[44] + mi := &file_proto_room_v1_room_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3636,7 +3761,7 @@ func (x *RoomEntryVehicleSnapshot) String() string { func (*RoomEntryVehicleSnapshot) ProtoMessage() {} func (x *RoomEntryVehicleSnapshot) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[44] + mi := &file_proto_room_v1_room_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3649,7 +3774,7 @@ func (x *RoomEntryVehicleSnapshot) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomEntryVehicleSnapshot.ProtoReflect.Descriptor instead. func (*RoomEntryVehicleSnapshot) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{44} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{45} } func (x *RoomEntryVehicleSnapshot) GetResourceId() int64 { @@ -3728,7 +3853,7 @@ type JoinRoomRequest struct { func (x *JoinRoomRequest) Reset() { *x = JoinRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[45] + mi := &file_proto_room_v1_room_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3740,7 +3865,7 @@ func (x *JoinRoomRequest) String() string { func (*JoinRoomRequest) ProtoMessage() {} func (x *JoinRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[45] + mi := &file_proto_room_v1_room_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3753,7 +3878,7 @@ func (x *JoinRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use JoinRoomRequest.ProtoReflect.Descriptor instead. func (*JoinRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{45} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{46} } func (x *JoinRoomRequest) GetMeta() *RequestMeta { @@ -3796,7 +3921,7 @@ type JoinRoomResponse struct { func (x *JoinRoomResponse) Reset() { *x = JoinRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[46] + mi := &file_proto_room_v1_room_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3808,7 +3933,7 @@ func (x *JoinRoomResponse) String() string { func (*JoinRoomResponse) ProtoMessage() {} func (x *JoinRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[46] + mi := &file_proto_room_v1_room_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3821,7 +3946,7 @@ func (x *JoinRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use JoinRoomResponse.ProtoReflect.Descriptor instead. func (*JoinRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{46} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{47} } func (x *JoinRoomResponse) GetResult() *CommandResult { @@ -3856,7 +3981,7 @@ type RoomHeartbeatRequest struct { func (x *RoomHeartbeatRequest) Reset() { *x = RoomHeartbeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[47] + mi := &file_proto_room_v1_room_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3868,7 +3993,7 @@ func (x *RoomHeartbeatRequest) String() string { func (*RoomHeartbeatRequest) ProtoMessage() {} func (x *RoomHeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[47] + mi := &file_proto_room_v1_room_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3881,7 +4006,7 @@ func (x *RoomHeartbeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomHeartbeatRequest.ProtoReflect.Descriptor instead. func (*RoomHeartbeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{47} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{48} } func (x *RoomHeartbeatRequest) GetMeta() *RequestMeta { @@ -3903,7 +4028,7 @@ type RoomHeartbeatResponse struct { func (x *RoomHeartbeatResponse) Reset() { *x = RoomHeartbeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[48] + mi := &file_proto_room_v1_room_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3915,7 +4040,7 @@ func (x *RoomHeartbeatResponse) String() string { func (*RoomHeartbeatResponse) ProtoMessage() {} func (x *RoomHeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[48] + mi := &file_proto_room_v1_room_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3928,7 +4053,7 @@ func (x *RoomHeartbeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomHeartbeatResponse.ProtoReflect.Descriptor instead. func (*RoomHeartbeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{48} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{49} } func (x *RoomHeartbeatResponse) GetResult() *CommandResult { @@ -3962,7 +4087,7 @@ type LeaveRoomRequest struct { func (x *LeaveRoomRequest) Reset() { *x = LeaveRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[49] + mi := &file_proto_room_v1_room_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3974,7 +4099,7 @@ func (x *LeaveRoomRequest) String() string { func (*LeaveRoomRequest) ProtoMessage() {} func (x *LeaveRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[49] + mi := &file_proto_room_v1_room_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3987,7 +4112,7 @@ func (x *LeaveRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LeaveRoomRequest.ProtoReflect.Descriptor instead. func (*LeaveRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{49} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{50} } func (x *LeaveRoomRequest) GetMeta() *RequestMeta { @@ -4008,7 +4133,7 @@ type LeaveRoomResponse struct { func (x *LeaveRoomResponse) Reset() { *x = LeaveRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[50] + mi := &file_proto_room_v1_room_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4020,7 +4145,7 @@ func (x *LeaveRoomResponse) String() string { func (*LeaveRoomResponse) ProtoMessage() {} func (x *LeaveRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[50] + mi := &file_proto_room_v1_room_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4033,7 +4158,7 @@ func (x *LeaveRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LeaveRoomResponse.ProtoReflect.Descriptor instead. func (*LeaveRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{50} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{51} } func (x *LeaveRoomResponse) GetResult() *CommandResult { @@ -4061,7 +4186,7 @@ type CloseRoomRequest struct { func (x *CloseRoomRequest) Reset() { *x = CloseRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[51] + mi := &file_proto_room_v1_room_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4073,7 +4198,7 @@ func (x *CloseRoomRequest) String() string { func (*CloseRoomRequest) ProtoMessage() {} func (x *CloseRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[51] + mi := &file_proto_room_v1_room_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4086,7 +4211,7 @@ func (x *CloseRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseRoomRequest.ProtoReflect.Descriptor instead. func (*CloseRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{51} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{52} } func (x *CloseRoomRequest) GetMeta() *RequestMeta { @@ -4114,7 +4239,7 @@ type CloseRoomResponse struct { func (x *CloseRoomResponse) Reset() { *x = CloseRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[52] + mi := &file_proto_room_v1_room_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4126,7 +4251,7 @@ func (x *CloseRoomResponse) String() string { func (*CloseRoomResponse) ProtoMessage() {} func (x *CloseRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[52] + mi := &file_proto_room_v1_room_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4139,7 +4264,7 @@ func (x *CloseRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CloseRoomResponse.ProtoReflect.Descriptor instead. func (*CloseRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{52} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{53} } func (x *CloseRoomResponse) GetResult() *CommandResult { @@ -4184,7 +4309,7 @@ type AdminRoomListItem struct { func (x *AdminRoomListItem) Reset() { *x = AdminRoomListItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[53] + mi := &file_proto_room_v1_room_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4196,7 +4321,7 @@ func (x *AdminRoomListItem) String() string { func (*AdminRoomListItem) ProtoMessage() {} func (x *AdminRoomListItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[53] + mi := &file_proto_room_v1_room_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4209,7 +4334,7 @@ func (x *AdminRoomListItem) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminRoomListItem.ProtoReflect.Descriptor instead. func (*AdminRoomListItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{53} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{54} } func (x *AdminRoomListItem) GetRoomId() string { @@ -4361,7 +4486,7 @@ type AdminListRoomsRequest struct { func (x *AdminListRoomsRequest) Reset() { *x = AdminListRoomsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[54] + mi := &file_proto_room_v1_room_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4373,7 +4498,7 @@ func (x *AdminListRoomsRequest) String() string { func (*AdminListRoomsRequest) ProtoMessage() {} func (x *AdminListRoomsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[54] + mi := &file_proto_room_v1_room_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4386,7 +4511,7 @@ func (x *AdminListRoomsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomsRequest.ProtoReflect.Descriptor instead. func (*AdminListRoomsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{54} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{55} } func (x *AdminListRoomsRequest) GetMeta() *RequestMeta { @@ -4456,7 +4581,7 @@ type AdminListRoomsResponse struct { func (x *AdminListRoomsResponse) Reset() { *x = AdminListRoomsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[55] + mi := &file_proto_room_v1_room_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4468,7 +4593,7 @@ func (x *AdminListRoomsResponse) String() string { func (*AdminListRoomsResponse) ProtoMessage() {} func (x *AdminListRoomsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[55] + mi := &file_proto_room_v1_room_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4481,7 +4606,7 @@ func (x *AdminListRoomsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminListRoomsResponse.ProtoReflect.Descriptor instead. func (*AdminListRoomsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{55} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{56} } func (x *AdminListRoomsResponse) GetRooms() []*AdminRoomListItem { @@ -4515,7 +4640,7 @@ type AdminGetRoomRequest struct { func (x *AdminGetRoomRequest) Reset() { *x = AdminGetRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[56] + mi := &file_proto_room_v1_room_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4527,7 +4652,7 @@ func (x *AdminGetRoomRequest) String() string { func (*AdminGetRoomRequest) ProtoMessage() {} func (x *AdminGetRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[56] + mi := &file_proto_room_v1_room_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4540,7 +4665,7 @@ func (x *AdminGetRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomRequest.ProtoReflect.Descriptor instead. func (*AdminGetRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{56} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{57} } func (x *AdminGetRoomRequest) GetMeta() *RequestMeta { @@ -4567,7 +4692,7 @@ type AdminGetRoomResponse struct { func (x *AdminGetRoomResponse) Reset() { *x = AdminGetRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[57] + mi := &file_proto_room_v1_room_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4579,7 +4704,7 @@ func (x *AdminGetRoomResponse) String() string { func (*AdminGetRoomResponse) ProtoMessage() {} func (x *AdminGetRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[57] + mi := &file_proto_room_v1_room_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4592,7 +4717,7 @@ func (x *AdminGetRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminGetRoomResponse.ProtoReflect.Descriptor instead. func (*AdminGetRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{57} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{58} } func (x *AdminGetRoomResponse) GetRoom() *AdminRoomListItem { @@ -4627,7 +4752,7 @@ type AdminUpdateRoomRequest struct { func (x *AdminUpdateRoomRequest) Reset() { *x = AdminUpdateRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[58] + mi := &file_proto_room_v1_room_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4639,7 +4764,7 @@ func (x *AdminUpdateRoomRequest) String() string { func (*AdminUpdateRoomRequest) ProtoMessage() {} func (x *AdminUpdateRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[58] + mi := &file_proto_room_v1_room_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4652,7 +4777,7 @@ func (x *AdminUpdateRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminUpdateRoomRequest.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{58} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{59} } func (x *AdminUpdateRoomRequest) GetMeta() *RequestMeta { @@ -4735,7 +4860,7 @@ type AdminUpdateRoomResponse struct { func (x *AdminUpdateRoomResponse) Reset() { *x = AdminUpdateRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[59] + mi := &file_proto_room_v1_room_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4747,7 +4872,7 @@ func (x *AdminUpdateRoomResponse) String() string { func (*AdminUpdateRoomResponse) ProtoMessage() {} func (x *AdminUpdateRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[59] + mi := &file_proto_room_v1_room_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4760,7 +4885,7 @@ func (x *AdminUpdateRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminUpdateRoomResponse.ProtoReflect.Descriptor instead. func (*AdminUpdateRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{59} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{60} } func (x *AdminUpdateRoomResponse) GetResult() *CommandResult { @@ -4788,7 +4913,7 @@ type AdminDeleteRoomRequest struct { func (x *AdminDeleteRoomRequest) Reset() { *x = AdminDeleteRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[60] + mi := &file_proto_room_v1_room_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4800,7 +4925,7 @@ func (x *AdminDeleteRoomRequest) String() string { func (*AdminDeleteRoomRequest) ProtoMessage() {} func (x *AdminDeleteRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[60] + mi := &file_proto_room_v1_room_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4813,7 +4938,7 @@ func (x *AdminDeleteRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminDeleteRoomRequest.ProtoReflect.Descriptor instead. func (*AdminDeleteRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{60} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{61} } func (x *AdminDeleteRoomRequest) GetMeta() *RequestMeta { @@ -4847,7 +4972,7 @@ type AdminDeleteRoomResponse struct { func (x *AdminDeleteRoomResponse) Reset() { *x = AdminDeleteRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[61] + mi := &file_proto_room_v1_room_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4859,7 +4984,7 @@ func (x *AdminDeleteRoomResponse) String() string { func (*AdminDeleteRoomResponse) ProtoMessage() {} func (x *AdminDeleteRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[61] + mi := &file_proto_room_v1_room_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4872,7 +4997,7 @@ func (x *AdminDeleteRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AdminDeleteRoomResponse.ProtoReflect.Descriptor instead. func (*AdminDeleteRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{61} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{62} } func (x *AdminDeleteRoomResponse) GetResult() *CommandResult { @@ -4900,7 +5025,7 @@ type MicUpRequest struct { func (x *MicUpRequest) Reset() { *x = MicUpRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[62] + mi := &file_proto_room_v1_room_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4912,7 +5037,7 @@ func (x *MicUpRequest) String() string { func (*MicUpRequest) ProtoMessage() {} func (x *MicUpRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[62] + mi := &file_proto_room_v1_room_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4925,7 +5050,7 @@ func (x *MicUpRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicUpRequest.ProtoReflect.Descriptor instead. func (*MicUpRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{62} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{63} } func (x *MicUpRequest) GetMeta() *RequestMeta { @@ -4956,7 +5081,7 @@ type MicUpResponse struct { func (x *MicUpResponse) Reset() { *x = MicUpResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[63] + mi := &file_proto_room_v1_room_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4968,7 +5093,7 @@ func (x *MicUpResponse) String() string { func (*MicUpResponse) ProtoMessage() {} func (x *MicUpResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[63] + mi := &file_proto_room_v1_room_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4981,7 +5106,7 @@ func (x *MicUpResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicUpResponse.ProtoReflect.Descriptor instead. func (*MicUpResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{63} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{64} } func (x *MicUpResponse) GetResult() *CommandResult { @@ -5032,7 +5157,7 @@ type MicDownRequest struct { func (x *MicDownRequest) Reset() { *x = MicDownRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[64] + mi := &file_proto_room_v1_room_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5044,7 +5169,7 @@ func (x *MicDownRequest) String() string { func (*MicDownRequest) ProtoMessage() {} func (x *MicDownRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[64] + mi := &file_proto_room_v1_room_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5057,7 +5182,7 @@ func (x *MicDownRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicDownRequest.ProtoReflect.Descriptor instead. func (*MicDownRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{64} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{65} } func (x *MicDownRequest) GetMeta() *RequestMeta { @@ -5093,7 +5218,7 @@ type MicDownResponse struct { func (x *MicDownResponse) Reset() { *x = MicDownResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[65] + mi := &file_proto_room_v1_room_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5105,7 +5230,7 @@ func (x *MicDownResponse) String() string { func (*MicDownResponse) ProtoMessage() {} func (x *MicDownResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[65] + mi := &file_proto_room_v1_room_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5118,7 +5243,7 @@ func (x *MicDownResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicDownResponse.ProtoReflect.Descriptor instead. func (*MicDownResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{65} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{66} } func (x *MicDownResponse) GetResult() *CommandResult { @@ -5154,7 +5279,7 @@ type ChangeMicSeatRequest struct { func (x *ChangeMicSeatRequest) Reset() { *x = ChangeMicSeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[66] + mi := &file_proto_room_v1_room_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5166,7 +5291,7 @@ func (x *ChangeMicSeatRequest) String() string { func (*ChangeMicSeatRequest) ProtoMessage() {} func (x *ChangeMicSeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[66] + mi := &file_proto_room_v1_room_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5179,7 +5304,7 @@ func (x *ChangeMicSeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeMicSeatRequest.ProtoReflect.Descriptor instead. func (*ChangeMicSeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{66} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{67} } func (x *ChangeMicSeatRequest) GetMeta() *RequestMeta { @@ -5214,7 +5339,7 @@ type ChangeMicSeatResponse struct { func (x *ChangeMicSeatResponse) Reset() { *x = ChangeMicSeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[67] + mi := &file_proto_room_v1_room_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5226,7 +5351,7 @@ func (x *ChangeMicSeatResponse) String() string { func (*ChangeMicSeatResponse) ProtoMessage() {} func (x *ChangeMicSeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[67] + mi := &file_proto_room_v1_room_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5239,7 +5364,7 @@ func (x *ChangeMicSeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeMicSeatResponse.ProtoReflect.Descriptor instead. func (*ChangeMicSeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{67} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{68} } func (x *ChangeMicSeatResponse) GetResult() *CommandResult { @@ -5273,7 +5398,7 @@ type ConfirmMicPublishingRequest struct { func (x *ConfirmMicPublishingRequest) Reset() { *x = ConfirmMicPublishingRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[68] + mi := &file_proto_room_v1_room_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5285,7 +5410,7 @@ func (x *ConfirmMicPublishingRequest) String() string { func (*ConfirmMicPublishingRequest) ProtoMessage() {} func (x *ConfirmMicPublishingRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[68] + mi := &file_proto_room_v1_room_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5298,7 +5423,7 @@ func (x *ConfirmMicPublishingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmMicPublishingRequest.ProtoReflect.Descriptor instead. func (*ConfirmMicPublishingRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{68} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{69} } func (x *ConfirmMicPublishingRequest) GetMeta() *RequestMeta { @@ -5355,7 +5480,7 @@ type ConfirmMicPublishingResponse struct { func (x *ConfirmMicPublishingResponse) Reset() { *x = ConfirmMicPublishingResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[69] + mi := &file_proto_room_v1_room_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5367,7 +5492,7 @@ func (x *ConfirmMicPublishingResponse) String() string { func (*ConfirmMicPublishingResponse) ProtoMessage() {} func (x *ConfirmMicPublishingResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[69] + mi := &file_proto_room_v1_room_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5380,7 +5505,7 @@ func (x *ConfirmMicPublishingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfirmMicPublishingResponse.ProtoReflect.Descriptor instead. func (*ConfirmMicPublishingResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{69} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} } func (x *ConfirmMicPublishingResponse) GetResult() *CommandResult { @@ -5418,7 +5543,7 @@ type MicHeartbeatRequest struct { func (x *MicHeartbeatRequest) Reset() { *x = MicHeartbeatRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5430,7 +5555,7 @@ func (x *MicHeartbeatRequest) String() string { func (*MicHeartbeatRequest) ProtoMessage() {} func (x *MicHeartbeatRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[70] + mi := &file_proto_room_v1_room_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5443,7 +5568,7 @@ func (x *MicHeartbeatRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MicHeartbeatRequest.ProtoReflect.Descriptor instead. func (*MicHeartbeatRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{70} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} } func (x *MicHeartbeatRequest) GetMeta() *RequestMeta { @@ -5480,7 +5605,7 @@ type MicHeartbeatResponse struct { func (x *MicHeartbeatResponse) Reset() { *x = MicHeartbeatResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5492,7 +5617,7 @@ func (x *MicHeartbeatResponse) String() string { func (*MicHeartbeatResponse) ProtoMessage() {} func (x *MicHeartbeatResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[71] + mi := &file_proto_room_v1_room_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5505,7 +5630,7 @@ func (x *MicHeartbeatResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MicHeartbeatResponse.ProtoReflect.Descriptor instead. func (*MicHeartbeatResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{71} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} } func (x *MicHeartbeatResponse) GetResult() *CommandResult { @@ -5549,7 +5674,7 @@ type SetMicMuteRequest struct { func (x *SetMicMuteRequest) Reset() { *x = SetMicMuteRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5561,7 +5686,7 @@ func (x *SetMicMuteRequest) String() string { func (*SetMicMuteRequest) ProtoMessage() {} func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[72] + mi := &file_proto_room_v1_room_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5574,7 +5699,7 @@ func (x *SetMicMuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteRequest.ProtoReflect.Descriptor instead. func (*SetMicMuteRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{72} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} } func (x *SetMicMuteRequest) GetMeta() *RequestMeta { @@ -5610,7 +5735,7 @@ type SetMicMuteResponse struct { func (x *SetMicMuteResponse) Reset() { *x = SetMicMuteResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5622,7 +5747,7 @@ func (x *SetMicMuteResponse) String() string { func (*SetMicMuteResponse) ProtoMessage() {} func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[73] + mi := &file_proto_room_v1_room_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5635,7 +5760,7 @@ func (x *SetMicMuteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicMuteResponse.ProtoReflect.Descriptor instead. func (*SetMicMuteResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{73} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} } func (x *SetMicMuteResponse) GetResult() *CommandResult { @@ -5676,7 +5801,7 @@ type ApplyRTCEventRequest struct { func (x *ApplyRTCEventRequest) Reset() { *x = ApplyRTCEventRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5688,7 +5813,7 @@ func (x *ApplyRTCEventRequest) String() string { func (*ApplyRTCEventRequest) ProtoMessage() {} func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[74] + mi := &file_proto_room_v1_room_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5701,7 +5826,7 @@ func (x *ApplyRTCEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventRequest.ProtoReflect.Descriptor instead. func (*ApplyRTCEventRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{74} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} } func (x *ApplyRTCEventRequest) GetMeta() *RequestMeta { @@ -5765,7 +5890,7 @@ type ApplyRTCEventResponse struct { func (x *ApplyRTCEventResponse) Reset() { *x = ApplyRTCEventResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5777,7 +5902,7 @@ func (x *ApplyRTCEventResponse) String() string { func (*ApplyRTCEventResponse) ProtoMessage() {} func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[75] + mi := &file_proto_room_v1_room_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5790,7 +5915,7 @@ func (x *ApplyRTCEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyRTCEventResponse.ProtoReflect.Descriptor instead. func (*ApplyRTCEventResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{75} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} } func (x *ApplyRTCEventResponse) GetResult() *CommandResult { @@ -5826,7 +5951,7 @@ type SetMicSeatLockRequest struct { func (x *SetMicSeatLockRequest) Reset() { *x = SetMicSeatLockRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5838,7 +5963,7 @@ func (x *SetMicSeatLockRequest) String() string { func (*SetMicSeatLockRequest) ProtoMessage() {} func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[76] + mi := &file_proto_room_v1_room_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5851,7 +5976,7 @@ func (x *SetMicSeatLockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockRequest.ProtoReflect.Descriptor instead. func (*SetMicSeatLockRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{76} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} } func (x *SetMicSeatLockRequest) GetMeta() *RequestMeta { @@ -5886,7 +6011,7 @@ type SetMicSeatLockResponse struct { func (x *SetMicSeatLockResponse) Reset() { *x = SetMicSeatLockResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5898,7 +6023,7 @@ func (x *SetMicSeatLockResponse) String() string { func (*SetMicSeatLockResponse) ProtoMessage() {} func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[77] + mi := &file_proto_room_v1_room_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5911,7 +6036,7 @@ func (x *SetMicSeatLockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetMicSeatLockResponse.ProtoReflect.Descriptor instead. func (*SetMicSeatLockResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{77} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} } func (x *SetMicSeatLockResponse) GetResult() *CommandResult { @@ -5939,7 +6064,7 @@ type SetChatEnabledRequest struct { func (x *SetChatEnabledRequest) Reset() { *x = SetChatEnabledRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5951,7 +6076,7 @@ func (x *SetChatEnabledRequest) String() string { func (*SetChatEnabledRequest) ProtoMessage() {} func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[78] + mi := &file_proto_room_v1_room_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5964,7 +6089,7 @@ func (x *SetChatEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledRequest.ProtoReflect.Descriptor instead. func (*SetChatEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{78} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} } func (x *SetChatEnabledRequest) GetMeta() *RequestMeta { @@ -5992,7 +6117,7 @@ type SetChatEnabledResponse struct { func (x *SetChatEnabledResponse) Reset() { *x = SetChatEnabledResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6004,7 +6129,7 @@ func (x *SetChatEnabledResponse) String() string { func (*SetChatEnabledResponse) ProtoMessage() {} func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[79] + mi := &file_proto_room_v1_room_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6017,7 +6142,7 @@ func (x *SetChatEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetChatEnabledResponse.ProtoReflect.Descriptor instead. func (*SetChatEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{79} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} } func (x *SetChatEnabledResponse) GetResult() *CommandResult { @@ -6047,7 +6172,7 @@ type SetRoomPasswordRequest struct { func (x *SetRoomPasswordRequest) Reset() { *x = SetRoomPasswordRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6059,7 +6184,7 @@ func (x *SetRoomPasswordRequest) String() string { func (*SetRoomPasswordRequest) ProtoMessage() {} func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[80] + mi := &file_proto_room_v1_room_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6072,7 +6197,7 @@ func (x *SetRoomPasswordRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordRequest.ProtoReflect.Descriptor instead. func (*SetRoomPasswordRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{80} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} } func (x *SetRoomPasswordRequest) GetMeta() *RequestMeta { @@ -6107,7 +6232,7 @@ type SetRoomPasswordResponse struct { func (x *SetRoomPasswordResponse) Reset() { *x = SetRoomPasswordResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6119,7 +6244,7 @@ func (x *SetRoomPasswordResponse) String() string { func (*SetRoomPasswordResponse) ProtoMessage() {} func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[81] + mi := &file_proto_room_v1_room_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6132,7 +6257,7 @@ func (x *SetRoomPasswordResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomPasswordResponse.ProtoReflect.Descriptor instead. func (*SetRoomPasswordResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{81} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} } func (x *SetRoomPasswordResponse) GetResult() *CommandResult { @@ -6161,7 +6286,7 @@ type SetRoomAdminRequest struct { func (x *SetRoomAdminRequest) Reset() { *x = SetRoomAdminRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6173,7 +6298,7 @@ func (x *SetRoomAdminRequest) String() string { func (*SetRoomAdminRequest) ProtoMessage() {} func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[82] + mi := &file_proto_room_v1_room_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6186,7 +6311,7 @@ func (x *SetRoomAdminRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminRequest.ProtoReflect.Descriptor instead. func (*SetRoomAdminRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{82} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} } func (x *SetRoomAdminRequest) GetMeta() *RequestMeta { @@ -6221,7 +6346,7 @@ type SetRoomAdminResponse struct { func (x *SetRoomAdminResponse) Reset() { *x = SetRoomAdminResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6233,7 +6358,7 @@ func (x *SetRoomAdminResponse) String() string { func (*SetRoomAdminResponse) ProtoMessage() {} func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[83] + mi := &file_proto_room_v1_room_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6246,7 +6371,7 @@ func (x *SetRoomAdminResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetRoomAdminResponse.ProtoReflect.Descriptor instead. func (*SetRoomAdminResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{83} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} } func (x *SetRoomAdminResponse) GetResult() *CommandResult { @@ -6275,7 +6400,7 @@ type MuteUserRequest struct { func (x *MuteUserRequest) Reset() { *x = MuteUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6287,7 +6412,7 @@ func (x *MuteUserRequest) String() string { func (*MuteUserRequest) ProtoMessage() {} func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[84] + mi := &file_proto_room_v1_room_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6300,7 +6425,7 @@ func (x *MuteUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserRequest.ProtoReflect.Descriptor instead. func (*MuteUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{84} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} } func (x *MuteUserRequest) GetMeta() *RequestMeta { @@ -6335,7 +6460,7 @@ type MuteUserResponse struct { func (x *MuteUserResponse) Reset() { *x = MuteUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6347,7 +6472,7 @@ func (x *MuteUserResponse) String() string { func (*MuteUserResponse) ProtoMessage() {} func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[85] + mi := &file_proto_room_v1_room_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6360,7 +6485,7 @@ func (x *MuteUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use MuteUserResponse.ProtoReflect.Descriptor instead. func (*MuteUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{85} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} } func (x *MuteUserResponse) GetResult() *CommandResult { @@ -6390,7 +6515,7 @@ type KickUserRequest struct { func (x *KickUserRequest) Reset() { *x = KickUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6402,7 +6527,7 @@ func (x *KickUserRequest) String() string { func (*KickUserRequest) ProtoMessage() {} func (x *KickUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[86] + mi := &file_proto_room_v1_room_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6415,7 +6540,7 @@ func (x *KickUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserRequest.ProtoReflect.Descriptor instead. func (*KickUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{86} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} } func (x *KickUserRequest) GetMeta() *RequestMeta { @@ -6454,7 +6579,7 @@ type KickUserResponse struct { func (x *KickUserResponse) Reset() { *x = KickUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6466,7 +6591,7 @@ func (x *KickUserResponse) String() string { func (*KickUserResponse) ProtoMessage() {} func (x *KickUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[87] + mi := &file_proto_room_v1_room_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6479,7 +6604,7 @@ func (x *KickUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use KickUserResponse.ProtoReflect.Descriptor instead. func (*KickUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{87} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} } func (x *KickUserResponse) GetResult() *CommandResult { @@ -6521,7 +6646,7 @@ type UnbanUserRequest struct { func (x *UnbanUserRequest) Reset() { *x = UnbanUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6533,7 +6658,7 @@ func (x *UnbanUserRequest) String() string { func (*UnbanUserRequest) ProtoMessage() {} func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[88] + mi := &file_proto_room_v1_room_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6546,7 +6671,7 @@ func (x *UnbanUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserRequest.ProtoReflect.Descriptor instead. func (*UnbanUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{88} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} } func (x *UnbanUserRequest) GetMeta() *RequestMeta { @@ -6574,7 +6699,7 @@ type UnbanUserResponse struct { func (x *UnbanUserResponse) Reset() { *x = UnbanUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6586,7 +6711,7 @@ func (x *UnbanUserResponse) String() string { func (*UnbanUserResponse) ProtoMessage() {} func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[89] + mi := &file_proto_room_v1_room_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6599,7 +6724,7 @@ func (x *UnbanUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnbanUserResponse.ProtoReflect.Descriptor instead. func (*UnbanUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{89} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} } func (x *UnbanUserResponse) GetResult() *CommandResult { @@ -6632,7 +6757,7 @@ type SystemEvictUserRequest struct { func (x *SystemEvictUserRequest) Reset() { *x = SystemEvictUserRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6644,7 +6769,7 @@ func (x *SystemEvictUserRequest) String() string { func (*SystemEvictUserRequest) ProtoMessage() {} func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[90] + mi := &file_proto_room_v1_room_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6657,7 +6782,7 @@ func (x *SystemEvictUserRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserRequest.ProtoReflect.Descriptor instead. func (*SystemEvictUserRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{90} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} } func (x *SystemEvictUserRequest) GetMeta() *RequestMeta { @@ -6710,7 +6835,7 @@ type SystemEvictUserResponse struct { func (x *SystemEvictUserResponse) Reset() { *x = SystemEvictUserResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6722,7 +6847,7 @@ func (x *SystemEvictUserResponse) String() string { func (*SystemEvictUserResponse) ProtoMessage() {} func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[91] + mi := &file_proto_room_v1_room_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6735,7 +6860,7 @@ func (x *SystemEvictUserResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SystemEvictUserResponse.ProtoReflect.Descriptor instead. func (*SystemEvictUserResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{91} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} } func (x *SystemEvictUserResponse) GetHadCurrentRoom() bool { @@ -6806,7 +6931,7 @@ type SendGiftRequest struct { func (x *SendGiftRequest) Reset() { *x = SendGiftRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6818,7 +6943,7 @@ func (x *SendGiftRequest) String() string { func (*SendGiftRequest) ProtoMessage() {} func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[92] + mi := &file_proto_room_v1_room_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6831,7 +6956,7 @@ func (x *SendGiftRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftRequest.ProtoReflect.Descriptor instead. func (*SendGiftRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{92} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} } func (x *SendGiftRequest) GetMeta() *RequestMeta { @@ -6919,7 +7044,7 @@ type SendGiftResponse struct { RoomHeat int64 `protobuf:"varint,3,opt,name=room_heat,json=roomHeat,proto3" json:"room_heat,omitempty"` GiftRank []*RankItem `protobuf:"bytes,4,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` Room *RoomSnapshot `protobuf:"bytes,5,opt,name=room,proto3" json:"room,omitempty"` - Treasure *RoomTreasureState `protobuf:"bytes,6,opt,name=treasure,proto3" json:"treasure,omitempty"` + Rocket *RoomRocketState `protobuf:"bytes,6,opt,name=rocket,proto3" json:"rocket,omitempty"` // lucky_gift 是本次送礼的聚合幸运礼物结果;多目标时倍率和返奖金额按所有目标累加。 LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,7,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` // lucky_gifts 是每个收礼目标的独立抽奖结果;多目标客户端用 target_user_id 对齐明细表现。 @@ -6930,7 +7055,7 @@ type SendGiftResponse struct { func (x *SendGiftResponse) Reset() { *x = SendGiftResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6942,7 +7067,7 @@ func (x *SendGiftResponse) String() string { func (*SendGiftResponse) ProtoMessage() {} func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[93] + mi := &file_proto_room_v1_room_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6955,7 +7080,7 @@ func (x *SendGiftResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SendGiftResponse.ProtoReflect.Descriptor instead. func (*SendGiftResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{93} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} } func (x *SendGiftResponse) GetResult() *CommandResult { @@ -6993,9 +7118,9 @@ func (x *SendGiftResponse) GetRoom() *RoomSnapshot { return nil } -func (x *SendGiftResponse) GetTreasure() *RoomTreasureState { +func (x *SendGiftResponse) GetRocket() *RoomRocketState { if x != nil { - return x.Treasure + return x.Rocket } return nil } @@ -7026,7 +7151,7 @@ type CheckSpeakPermissionRequest struct { func (x *CheckSpeakPermissionRequest) Reset() { *x = CheckSpeakPermissionRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7038,7 +7163,7 @@ func (x *CheckSpeakPermissionRequest) String() string { func (*CheckSpeakPermissionRequest) ProtoMessage() {} func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[94] + mi := &file_proto_room_v1_room_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7051,7 +7176,7 @@ func (x *CheckSpeakPermissionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionRequest.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{94} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} } func (x *CheckSpeakPermissionRequest) GetRoomId() string { @@ -7087,7 +7212,7 @@ type CheckSpeakPermissionResponse struct { func (x *CheckSpeakPermissionResponse) Reset() { *x = CheckSpeakPermissionResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7099,7 +7224,7 @@ func (x *CheckSpeakPermissionResponse) String() string { func (*CheckSpeakPermissionResponse) ProtoMessage() {} func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[95] + mi := &file_proto_room_v1_room_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7112,7 +7237,7 @@ func (x *CheckSpeakPermissionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CheckSpeakPermissionResponse.ProtoReflect.Descriptor instead. func (*CheckSpeakPermissionResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{95} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} } func (x *CheckSpeakPermissionResponse) GetAllowed() bool { @@ -7150,7 +7275,7 @@ type VerifyRoomPresenceRequest struct { func (x *VerifyRoomPresenceRequest) Reset() { *x = VerifyRoomPresenceRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7162,7 +7287,7 @@ func (x *VerifyRoomPresenceRequest) String() string { func (*VerifyRoomPresenceRequest) ProtoMessage() {} func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[96] + mi := &file_proto_room_v1_room_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7175,7 +7300,7 @@ func (x *VerifyRoomPresenceRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceRequest.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{96} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} } func (x *VerifyRoomPresenceRequest) GetRoomId() string { @@ -7225,7 +7350,7 @@ type VerifyRoomPresenceResponse struct { func (x *VerifyRoomPresenceResponse) Reset() { *x = VerifyRoomPresenceResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7237,7 +7362,7 @@ func (x *VerifyRoomPresenceResponse) String() string { func (*VerifyRoomPresenceResponse) ProtoMessage() {} func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[97] + mi := &file_proto_room_v1_room_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7250,7 +7375,7 @@ func (x *VerifyRoomPresenceResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRoomPresenceResponse.ProtoReflect.Descriptor instead. func (*VerifyRoomPresenceResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{97} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} } func (x *VerifyRoomPresenceResponse) GetPresent() bool { @@ -7291,7 +7416,7 @@ type ListRoomsRequest struct { func (x *ListRoomsRequest) Reset() { *x = ListRoomsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7303,7 +7428,7 @@ func (x *ListRoomsRequest) String() string { func (*ListRoomsRequest) ProtoMessage() {} func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[98] + mi := &file_proto_room_v1_room_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7316,7 +7441,7 @@ func (x *ListRoomsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsRequest.ProtoReflect.Descriptor instead. func (*ListRoomsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{98} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} } func (x *ListRoomsRequest) GetMeta() *RequestMeta { @@ -7387,7 +7512,7 @@ type ListRoomFeedsRequest struct { func (x *ListRoomFeedsRequest) Reset() { *x = ListRoomFeedsRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7399,7 +7524,7 @@ func (x *ListRoomFeedsRequest) String() string { func (*ListRoomFeedsRequest) ProtoMessage() {} func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[99] + mi := &file_proto_room_v1_room_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7412,7 +7537,7 @@ func (x *ListRoomFeedsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomFeedsRequest.ProtoReflect.Descriptor instead. func (*ListRoomFeedsRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{99} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} } func (x *ListRoomFeedsRequest) GetMeta() *RequestMeta { @@ -7484,7 +7609,7 @@ type ListRoomGiftLeaderboardRequest struct { func (x *ListRoomGiftLeaderboardRequest) Reset() { *x = ListRoomGiftLeaderboardRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7496,7 +7621,7 @@ func (x *ListRoomGiftLeaderboardRequest) String() string { func (*ListRoomGiftLeaderboardRequest) ProtoMessage() {} func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[100] + mi := &file_proto_room_v1_room_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7509,7 +7634,7 @@ func (x *ListRoomGiftLeaderboardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardRequest.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{100} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} } func (x *ListRoomGiftLeaderboardRequest) GetMeta() *RequestMeta { @@ -7551,7 +7676,7 @@ type RoomFeedRelatedUser struct { func (x *RoomFeedRelatedUser) Reset() { *x = RoomFeedRelatedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7563,7 +7688,7 @@ func (x *RoomFeedRelatedUser) String() string { func (*RoomFeedRelatedUser) ProtoMessage() {} func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[101] + mi := &file_proto_room_v1_room_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7576,7 +7701,7 @@ func (x *RoomFeedRelatedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomFeedRelatedUser.ProtoReflect.Descriptor instead. func (*RoomFeedRelatedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{101} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} } func (x *RoomFeedRelatedUser) GetUserId() int64 { @@ -7616,7 +7741,7 @@ type RoomListItem struct { func (x *RoomListItem) Reset() { *x = RoomListItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7628,7 +7753,7 @@ func (x *RoomListItem) String() string { func (*RoomListItem) ProtoMessage() {} func (x *RoomListItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[102] + mi := &file_proto_room_v1_room_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7641,7 +7766,7 @@ func (x *RoomListItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomListItem.ProtoReflect.Descriptor instead. func (*RoomListItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{102} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} } func (x *RoomListItem) GetRoomId() string { @@ -7753,7 +7878,7 @@ type ListRoomsResponse struct { func (x *ListRoomsResponse) Reset() { *x = ListRoomsResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7765,7 +7890,7 @@ func (x *ListRoomsResponse) String() string { func (*ListRoomsResponse) ProtoMessage() {} func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[103] + mi := &file_proto_room_v1_room_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7778,7 +7903,7 @@ func (x *ListRoomsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomsResponse.ProtoReflect.Descriptor instead. func (*ListRoomsResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{103} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} } func (x *ListRoomsResponse) GetRooms() []*RoomListItem { @@ -7808,7 +7933,7 @@ type RoomGiftLeaderboardItem struct { func (x *RoomGiftLeaderboardItem) Reset() { *x = RoomGiftLeaderboardItem{} - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7820,7 +7945,7 @@ func (x *RoomGiftLeaderboardItem) String() string { func (*RoomGiftLeaderboardItem) ProtoMessage() {} func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[104] + mi := &file_proto_room_v1_room_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7833,7 +7958,7 @@ func (x *RoomGiftLeaderboardItem) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomGiftLeaderboardItem.ProtoReflect.Descriptor instead. func (*RoomGiftLeaderboardItem) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{104} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} } func (x *RoomGiftLeaderboardItem) GetRank() int64 { @@ -7879,7 +8004,7 @@ type ListRoomGiftLeaderboardResponse struct { func (x *ListRoomGiftLeaderboardResponse) Reset() { *x = ListRoomGiftLeaderboardResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7891,7 +8016,7 @@ func (x *ListRoomGiftLeaderboardResponse) String() string { func (*ListRoomGiftLeaderboardResponse) ProtoMessage() {} func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[105] + mi := &file_proto_room_v1_room_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7904,7 +8029,7 @@ func (x *ListRoomGiftLeaderboardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomGiftLeaderboardResponse.ProtoReflect.Descriptor instead. func (*ListRoomGiftLeaderboardResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{105} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} } func (x *ListRoomGiftLeaderboardResponse) GetItems() []*RoomGiftLeaderboardItem { @@ -7961,7 +8086,7 @@ type GetMyRoomRequest struct { func (x *GetMyRoomRequest) Reset() { *x = GetMyRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7973,7 +8098,7 @@ func (x *GetMyRoomRequest) String() string { func (*GetMyRoomRequest) ProtoMessage() {} func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[106] + mi := &file_proto_room_v1_room_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7986,7 +8111,7 @@ func (x *GetMyRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomRequest.ProtoReflect.Descriptor instead. func (*GetMyRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{106} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} } func (x *GetMyRoomRequest) GetMeta() *RequestMeta { @@ -8016,7 +8141,7 @@ type GetMyRoomResponse struct { func (x *GetMyRoomResponse) Reset() { *x = GetMyRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8028,7 +8153,7 @@ func (x *GetMyRoomResponse) String() string { func (*GetMyRoomResponse) ProtoMessage() {} func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[107] + mi := &file_proto_room_v1_room_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8041,7 +8166,7 @@ func (x *GetMyRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyRoomResponse.ProtoReflect.Descriptor instead. func (*GetMyRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{107} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} } func (x *GetMyRoomResponse) GetHasRoom() bool { @@ -8077,7 +8202,7 @@ type GetCurrentRoomRequest struct { func (x *GetCurrentRoomRequest) Reset() { *x = GetCurrentRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8089,7 +8214,7 @@ func (x *GetCurrentRoomRequest) String() string { func (*GetCurrentRoomRequest) ProtoMessage() {} func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[108] + mi := &file_proto_room_v1_room_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8102,7 +8227,7 @@ func (x *GetCurrentRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomRequest.ProtoReflect.Descriptor instead. func (*GetCurrentRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{108} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} } func (x *GetCurrentRoomRequest) GetMeta() *RequestMeta { @@ -8138,7 +8263,7 @@ type GetCurrentRoomResponse struct { func (x *GetCurrentRoomResponse) Reset() { *x = GetCurrentRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8150,7 +8275,7 @@ func (x *GetCurrentRoomResponse) String() string { func (*GetCurrentRoomResponse) ProtoMessage() {} func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[109] + mi := &file_proto_room_v1_room_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8163,7 +8288,7 @@ func (x *GetCurrentRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCurrentRoomResponse.ProtoReflect.Descriptor instead. func (*GetCurrentRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{109} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} } func (x *GetCurrentRoomResponse) GetHasCurrentRoom() bool { @@ -8242,7 +8367,7 @@ type GetRoomSnapshotRequest struct { func (x *GetRoomSnapshotRequest) Reset() { *x = GetRoomSnapshotRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8254,7 +8379,7 @@ func (x *GetRoomSnapshotRequest) String() string { func (*GetRoomSnapshotRequest) ProtoMessage() {} func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[110] + mi := &file_proto_room_v1_room_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8267,7 +8392,7 @@ func (x *GetRoomSnapshotRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotRequest.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{110} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} } func (x *GetRoomSnapshotRequest) GetMeta() *RequestMeta { @@ -8304,7 +8429,7 @@ type GetRoomSnapshotResponse struct { func (x *GetRoomSnapshotResponse) Reset() { *x = GetRoomSnapshotResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8316,7 +8441,7 @@ func (x *GetRoomSnapshotResponse) String() string { func (*GetRoomSnapshotResponse) ProtoMessage() {} func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[111] + mi := &file_proto_room_v1_room_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8329,7 +8454,7 @@ func (x *GetRoomSnapshotResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRoomSnapshotResponse.ProtoReflect.Descriptor instead. func (*GetRoomSnapshotResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{111} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} } func (x *GetRoomSnapshotResponse) GetRoom() *RoomSnapshot { @@ -8353,9 +8478,9 @@ func (x *GetRoomSnapshotResponse) GetIsFollowed() bool { return false } -// GetRoomTreasureRequest 主动读取当前房间宝箱配置物料和进度状态。 +// GetRoomRocketRequest 主动读取当前房间火箭配置物料和进度状态。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 -type GetRoomTreasureRequest struct { +type GetRoomRocketRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` @@ -8364,21 +8489,21 @@ type GetRoomTreasureRequest struct { sizeCache protoimpl.SizeCache } -func (x *GetRoomTreasureRequest) Reset() { - *x = GetRoomTreasureRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[112] +func (x *GetRoomRocketRequest) Reset() { + *x = GetRoomRocketRequest{} + mi := &file_proto_room_v1_room_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *GetRoomTreasureRequest) String() string { +func (x *GetRoomRocketRequest) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetRoomTreasureRequest) ProtoMessage() {} +func (*GetRoomRocketRequest) ProtoMessage() {} -func (x *GetRoomTreasureRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[112] +func (x *GetRoomRocketRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8389,55 +8514,55 @@ func (x *GetRoomTreasureRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetRoomTreasureRequest.ProtoReflect.Descriptor instead. -func (*GetRoomTreasureRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{112} +// Deprecated: Use GetRoomRocketRequest.ProtoReflect.Descriptor instead. +func (*GetRoomRocketRequest) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} } -func (x *GetRoomTreasureRequest) GetMeta() *RequestMeta { +func (x *GetRoomRocketRequest) GetMeta() *RequestMeta { if x != nil { return x.Meta } return nil } -func (x *GetRoomTreasureRequest) GetRoomId() string { +func (x *GetRoomRocketRequest) GetRoomId() string { if x != nil { return x.RoomId } return "" } -func (x *GetRoomTreasureRequest) GetViewerUserId() int64 { +func (x *GetRoomRocketRequest) GetViewerUserId() int64 { if x != nil { return x.ViewerUserId } return 0 } -type GetRoomTreasureResponse struct { +type GetRoomRocketResponse struct { state protoimpl.MessageState `protogen:"open.v1"` - Treasure *RoomTreasureInfo `protobuf:"bytes,1,opt,name=treasure,proto3" json:"treasure,omitempty"` + Rocket *RoomRocketInfo `protobuf:"bytes,1,opt,name=rocket,proto3" json:"rocket,omitempty"` ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *GetRoomTreasureResponse) Reset() { - *x = GetRoomTreasureResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[113] +func (x *GetRoomRocketResponse) Reset() { + *x = GetRoomRocketResponse{} + mi := &file_proto_room_v1_room_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *GetRoomTreasureResponse) String() string { +func (x *GetRoomRocketResponse) String() string { return protoimpl.X.MessageStringOf(x) } -func (*GetRoomTreasureResponse) ProtoMessage() {} +func (*GetRoomRocketResponse) ProtoMessage() {} -func (x *GetRoomTreasureResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[113] +func (x *GetRoomRocketResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_room_v1_room_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8448,19 +8573,19 @@ func (x *GetRoomTreasureResponse) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use GetRoomTreasureResponse.ProtoReflect.Descriptor instead. -func (*GetRoomTreasureResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{113} +// Deprecated: Use GetRoomRocketResponse.ProtoReflect.Descriptor instead. +func (*GetRoomRocketResponse) Descriptor() ([]byte, []int) { + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} } -func (x *GetRoomTreasureResponse) GetTreasure() *RoomTreasureInfo { +func (x *GetRoomRocketResponse) GetRocket() *RoomRocketInfo { if x != nil { - return x.Treasure + return x.Rocket } return nil } -func (x *GetRoomTreasureResponse) GetServerTimeMs() int64 { +func (x *GetRoomRocketResponse) GetServerTimeMs() int64 { if x != nil { return x.ServerTimeMs } @@ -8482,7 +8607,7 @@ type ListRoomOnlineUsersRequest struct { func (x *ListRoomOnlineUsersRequest) Reset() { *x = ListRoomOnlineUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8494,7 +8619,7 @@ func (x *ListRoomOnlineUsersRequest) String() string { func (*ListRoomOnlineUsersRequest) ProtoMessage() {} func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[114] + mi := &file_proto_room_v1_room_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8507,7 +8632,7 @@ func (x *ListRoomOnlineUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{114} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} } func (x *ListRoomOnlineUsersRequest) GetMeta() *RequestMeta { @@ -8566,7 +8691,7 @@ type ListRoomOnlineUsersResponse struct { func (x *ListRoomOnlineUsersResponse) Reset() { *x = ListRoomOnlineUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8578,7 +8703,7 @@ func (x *ListRoomOnlineUsersResponse) String() string { func (*ListRoomOnlineUsersResponse) ProtoMessage() {} func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[115] + mi := &file_proto_room_v1_room_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8591,7 +8716,7 @@ func (x *ListRoomOnlineUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomOnlineUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomOnlineUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{115} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} } func (x *ListRoomOnlineUsersResponse) GetUsers() []*RoomUser { @@ -8652,7 +8777,7 @@ type RoomBannedUser struct { func (x *RoomBannedUser) Reset() { *x = RoomBannedUser{} - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8664,7 +8789,7 @@ func (x *RoomBannedUser) String() string { func (*RoomBannedUser) ProtoMessage() {} func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[116] + mi := &file_proto_room_v1_room_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8677,7 +8802,7 @@ func (x *RoomBannedUser) ProtoReflect() protoreflect.Message { // Deprecated: Use RoomBannedUser.ProtoReflect.Descriptor instead. func (*RoomBannedUser) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{116} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} } func (x *RoomBannedUser) GetUserId() int64 { @@ -8736,7 +8861,7 @@ type ListRoomBannedUsersRequest struct { func (x *ListRoomBannedUsersRequest) Reset() { *x = ListRoomBannedUsersRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8748,7 +8873,7 @@ func (x *ListRoomBannedUsersRequest) String() string { func (*ListRoomBannedUsersRequest) ProtoMessage() {} func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[117] + mi := &file_proto_room_v1_room_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8761,7 +8886,7 @@ func (x *ListRoomBannedUsersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersRequest.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{117} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} } func (x *ListRoomBannedUsersRequest) GetMeta() *RequestMeta { @@ -8812,7 +8937,7 @@ type ListRoomBannedUsersResponse struct { func (x *ListRoomBannedUsersResponse) Reset() { *x = ListRoomBannedUsersResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8824,7 +8949,7 @@ func (x *ListRoomBannedUsersResponse) String() string { func (*ListRoomBannedUsersResponse) ProtoMessage() {} func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[118] + mi := &file_proto_room_v1_room_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8837,7 +8962,7 @@ func (x *ListRoomBannedUsersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRoomBannedUsersResponse.ProtoReflect.Descriptor instead. func (*ListRoomBannedUsersResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{118} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} } func (x *ListRoomBannedUsersResponse) GetItems() []*RoomBannedUser { @@ -8888,7 +9013,7 @@ type FollowRoomRequest struct { func (x *FollowRoomRequest) Reset() { *x = FollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8900,7 +9025,7 @@ func (x *FollowRoomRequest) String() string { func (*FollowRoomRequest) ProtoMessage() {} func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[119] + mi := &file_proto_room_v1_room_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8913,7 +9038,7 @@ func (x *FollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomRequest.ProtoReflect.Descriptor instead. func (*FollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{119} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} } func (x *FollowRoomRequest) GetMeta() *RequestMeta { @@ -8949,7 +9074,7 @@ type FollowRoomResponse struct { func (x *FollowRoomResponse) Reset() { *x = FollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8961,7 +9086,7 @@ func (x *FollowRoomResponse) String() string { func (*FollowRoomResponse) ProtoMessage() {} func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[120] + mi := &file_proto_room_v1_room_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8974,7 +9099,7 @@ func (x *FollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FollowRoomResponse.ProtoReflect.Descriptor instead. func (*FollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{120} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{121} } func (x *FollowRoomResponse) GetRoomId() string { @@ -9017,7 +9142,7 @@ type UnfollowRoomRequest struct { func (x *UnfollowRoomRequest) Reset() { *x = UnfollowRoomRequest{} - mi := &file_proto_room_v1_room_proto_msgTypes[121] + mi := &file_proto_room_v1_room_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9029,7 +9154,7 @@ func (x *UnfollowRoomRequest) String() string { func (*UnfollowRoomRequest) ProtoMessage() {} func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[121] + mi := &file_proto_room_v1_room_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9042,7 +9167,7 @@ func (x *UnfollowRoomRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomRequest.ProtoReflect.Descriptor instead. func (*UnfollowRoomRequest) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{121} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{122} } func (x *UnfollowRoomRequest) GetMeta() *RequestMeta { @@ -9077,7 +9202,7 @@ type UnfollowRoomResponse struct { func (x *UnfollowRoomResponse) Reset() { *x = UnfollowRoomResponse{} - mi := &file_proto_room_v1_room_proto_msgTypes[122] + mi := &file_proto_room_v1_room_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9089,7 +9214,7 @@ func (x *UnfollowRoomResponse) String() string { func (*UnfollowRoomResponse) ProtoMessage() {} func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_room_v1_room_proto_msgTypes[122] + mi := &file_proto_room_v1_room_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9102,7 +9227,7 @@ func (x *UnfollowRoomResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnfollowRoomResponse.ProtoReflect.Descriptor instead. func (*UnfollowRoomResponse) Descriptor() ([]byte, []int) { - return file_proto_room_v1_room_proto_rawDescGZIP(), []int{122} + return file_proto_room_v1_room_proto_rawDescGZIP(), []int{123} } func (x *UnfollowRoomResponse) GetRoomId() string { @@ -9206,24 +9331,24 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\rcreated_at_ms\x18\x11 \x01(\x03R\vcreatedAtMs\x122\n" + "\x15wallet_transaction_id\x18\x12 \x01(\tR\x13walletTransactionId\x12,\n" + "\x12coin_balance_after\x18\x13 \x01(\x03R\x10coinBalanceAfter\x12$\n" + - "\x0etarget_user_id\x18\x14 \x01(\x03R\ftargetUserId\"\xc0\x01\n" + - "\x16RoomTreasureRewardItem\x12$\n" + + "\x0etarget_user_id\x18\x14 \x01(\x03R\ftargetUserId\"\xbe\x01\n" + + "\x14RoomRocketRewardItem\x12$\n" + "\x0ereward_item_id\x18\x01 \x01(\tR\frewardItemId\x12*\n" + "\x11resource_group_id\x18\x02 \x01(\x03R\x0fresourceGroupId\x12\x16\n" + "\x06weight\x18\x03 \x01(\x03R\x06weight\x12!\n" + "\fdisplay_name\x18\x04 \x01(\tR\vdisplayName\x12\x19\n" + - "\bicon_url\x18\x05 \x01(\tR\aiconUrl\"\xdd\x03\n" + - "\x11RoomTreasureLevel\x12\x14\n" + - "\x05level\x18\x01 \x01(\x05R\x05level\x12)\n" + - "\x10energy_threshold\x18\x02 \x01(\x03R\x0fenergyThreshold\x12\x1b\n" + + "\bicon_url\x18\x05 \x01(\tR\aiconUrl\"\xd3\x03\n" + + "\x0fRoomRocketLevel\x12\x14\n" + + "\x05level\x18\x01 \x01(\x05R\x05level\x12%\n" + + "\x0efuel_threshold\x18\x02 \x01(\x03R\rfuelThreshold\x12\x1b\n" + "\tcover_url\x18\x03 \x01(\tR\bcoverUrl\x12#\n" + - "\ranimation_url\x18\x04 \x01(\tR\fanimationUrl\x122\n" + - "\x15opening_animation_url\x18\x05 \x01(\tR\x13openingAnimationUrl\x12(\n" + - "\x10opened_image_url\x18\x06 \x01(\tR\x0eopenedImageUrl\x12M\n" + - "\x0fin_room_rewards\x18\a \x03(\v2%.hyapp.room.v1.RoomTreasureRewardItemR\rinRoomRewards\x12H\n" + - "\ftop1_rewards\x18\b \x03(\v2%.hyapp.room.v1.RoomTreasureRewardItemR\vtop1Rewards\x12N\n" + - "\x0figniter_rewards\x18\t \x03(\v2%.hyapp.room.v1.RoomTreasureRewardItemR\x0eigniterRewards\"\x96\x02\n" + - "\x17RoomTreasureRewardGrant\x12\x1f\n" + + "\ranimation_url\x18\x04 \x01(\tR\fanimationUrl\x120\n" + + "\x14launch_animation_url\x18\x05 \x01(\tR\x12launchAnimationUrl\x12,\n" + + "\x12launched_image_url\x18\x06 \x01(\tR\x10launchedImageUrl\x12K\n" + + "\x0fin_room_rewards\x18\a \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\rinRoomRewards\x12F\n" + + "\ftop1_rewards\x18\b \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\vtop1Rewards\x12L\n" + + "\x0figniter_rewards\x18\t \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\x0eigniterRewards\"\x94\x02\n" + + "\x15RoomRocketRewardGrant\x12\x1f\n" + "\vreward_role\x18\x01 \x01(\tR\n" + "rewardRole\x12\x17\n" + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + @@ -9232,68 +9357,84 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\fdisplay_name\x18\x05 \x01(\tR\vdisplayName\x12\x19\n" + "\bicon_url\x18\x06 \x01(\tR\aiconUrl\x12\x19\n" + "\bgrant_id\x18\a \x01(\tR\agrantId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\"\x90\x04\n" + - "\x11RoomTreasureState\x12#\n" + - "\rcurrent_level\x18\x01 \x01(\x05R\fcurrentLevel\x12)\n" + - "\x10current_progress\x18\x02 \x01(\x03R\x0fcurrentProgress\x12)\n" + - "\x10energy_threshold\x18\x03 \x01(\x03R\x0fenergyThreshold\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x125\n" + - "\x17countdown_started_at_ms\x18\x05 \x01(\x03R\x14countdownStartedAtMs\x12\x1c\n" + - "\n" + - "open_at_ms\x18\x06 \x01(\x03R\bopenAtMs\x12 \n" + - "\fopened_at_ms\x18\a \x01(\x03R\n" + - "openedAtMs\x12\x1e\n" + + "\x06status\x18\b \x01(\tR\x06status\"\xe7\x02\n" + + "\x17RoomRocketPendingLaunch\x12\x1b\n" + + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + + "\x05level\x18\x02 \x01(\x05R\x05level\x12%\n" + + "\x0efuel_threshold\x18\x03 \x01(\x03R\rfuelThreshold\x12\"\n" + + "\rignited_at_ms\x18\x04 \x01(\x03R\vignitedAtMs\x12 \n" + + "\flaunch_at_ms\x18\x05 \x01(\x03R\n" + + "launchAtMs\x12\x1e\n" + + "\vreset_at_ms\x18\x06 \x01(\x03R\tresetAtMs\x12 \n" + + "\ftop1_user_id\x18\a \x01(\x03R\n" + + "top1UserId\x12&\n" + + "\x0figniter_user_id\x18\b \x01(\x03R\rigniterUserId\x12%\n" + + "\x0econfig_version\x18\t \x01(\x03R\rconfigVersion\x12\x1b\n" + + "\tcover_url\x18\n" + + " \x01(\tR\bcoverUrl\"\xce\x04\n" + + "\x0fRoomRocketState\x12#\n" + + "\rcurrent_level\x18\x01 \x01(\x05R\fcurrentLevel\x12!\n" + + "\fcurrent_fuel\x18\x02 \x01(\x03R\vcurrentFuel\x12%\n" + + "\x0efuel_threshold\x18\x03 \x01(\x03R\rfuelThreshold\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12\"\n" + + "\rignited_at_ms\x18\x05 \x01(\x03R\vignitedAtMs\x12 \n" + + "\flaunch_at_ms\x18\x06 \x01(\x03R\n" + + "launchAtMs\x12$\n" + + "\x0elaunched_at_ms\x18\a \x01(\x03R\flaunchedAtMs\x12\x1e\n" + "\vreset_at_ms\x18\b \x01(\x03R\tresetAtMs\x12 \n" + "\ftop1_user_id\x18\t \x01(\x03R\n" + "top1UserId\x12&\n" + "\x0figniter_user_id\x18\n" + - " \x01(\x03R\rigniterUserId\x12\x15\n" + - "\x06box_id\x18\v \x01(\tR\x05boxId\x12%\n" + - "\x0econfig_version\x18\f \x01(\x03R\rconfigVersion\x12I\n" + - "\flast_rewards\x18\r \x03(\v2&.hyapp.room.v1.RoomTreasureRewardGrantR\vlastRewards\"\xef\x02\n" + - "\x10RoomTreasureInfo\x12\x18\n" + - "\aenabled\x18\x01 \x01(\bR\aenabled\x128\n" + - "\x06levels\x18\x02 \x03(\v2 .hyapp.room.v1.RoomTreasureLevelR\x06levels\x126\n" + - "\x05state\x18\x03 \x01(\v2 .hyapp.room.v1.RoomTreasureStateR\x05state\x12$\n" + + " \x01(\x03R\rigniterUserId\x12\x1b\n" + + "\trocket_id\x18\v \x01(\tR\brocketId\x12%\n" + + "\x0econfig_version\x18\f \x01(\x03R\rconfigVersion\x12G\n" + + "\flast_rewards\x18\r \x03(\v2$.hyapp.room.v1.RoomRocketRewardGrantR\vlastRewards\x12Q\n" + + "\x10pending_launches\x18\x0e \x03(\v2&.hyapp.room.v1.RoomRocketPendingLaunchR\x0fpendingLaunches\"\xed\x02\n" + + "\x0eRoomRocketInfo\x12\x18\n" + + "\aenabled\x18\x01 \x01(\bR\aenabled\x126\n" + + "\x06levels\x18\x02 \x03(\v2\x1e.hyapp.room.v1.RoomRocketLevelR\x06levels\x124\n" + + "\x05state\x18\x03 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x05state\x12$\n" + "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\x12'\n" + - "\x0fbroadcast_scope\x18\x05 \x01(\tR\x0ebroadcastScope\x12\"\n" + - "\ropen_delay_ms\x18\x06 \x01(\x03R\vopenDelayMs\x12,\n" + + "\x0fbroadcast_scope\x18\x05 \x01(\tR\x0ebroadcastScope\x12&\n" + + "\x0flaunch_delay_ms\x18\x06 \x01(\x03R\rlaunchDelayMs\x12,\n" + "\x12broadcast_delay_ms\x18\a \x01(\x03R\x10broadcastDelayMs\x12.\n" + - "\x13reward_stack_policy\x18\b \x01(\tR\x11rewardStackPolicy\"\xda\x01\n" + - "\x1aRoomTreasureGiftEnergyRule\x12\x17\n" + + "\x13reward_stack_policy\x18\b \x01(\tR\x11rewardStackPolicy\"\xd2\x01\n" + + "\x16RoomRocketGiftFuelRule\x12\x17\n" + "\arule_id\x18\x01 \x01(\tR\x06ruleId\x12\x17\n" + "\agift_id\x18\x02 \x01(\tR\x06giftId\x12$\n" + "\x0egift_type_code\x18\x03 \x01(\tR\fgiftTypeCode\x12%\n" + - "\x0emultiplier_ppm\x18\x04 \x01(\x03R\rmultiplierPpm\x12!\n" + - "\ffixed_energy\x18\x05 \x01(\x03R\vfixedEnergy\x12\x1a\n" + - "\bexcluded\x18\x06 \x01(\bR\bexcluded\"\xfa\x04\n" + - "\x17AdminRoomTreasureConfig\x12\x19\n" + + "\x0emultiplier_ppm\x18\x04 \x01(\x03R\rmultiplierPpm\x12\x1d\n" + + "\n" + + "fixed_fuel\x18\x05 \x01(\x03R\tfixedFuel\x12\x1a\n" + + "\bexcluded\x18\x06 \x01(\bR\bexcluded\"\xee\x04\n" + + "\x15AdminRoomRocketConfig\x12\x19\n" + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + "\aenabled\x18\x02 \x01(\bR\aenabled\x12%\n" + - "\x0econfig_version\x18\x03 \x01(\x03R\rconfigVersion\x12#\n" + - "\renergy_source\x18\x04 \x01(\tR\fenergySource\x12\"\n" + - "\ropen_delay_ms\x18\x05 \x01(\x03R\vopenDelayMs\x12+\n" + + "\x0econfig_version\x18\x03 \x01(\x03R\rconfigVersion\x12\x1f\n" + + "\vfuel_source\x18\x04 \x01(\tR\n" + + "fuelSource\x12&\n" + + "\x0flaunch_delay_ms\x18\x05 \x01(\x03R\rlaunchDelayMs\x12+\n" + "\x11broadcast_enabled\x18\x06 \x01(\bR\x10broadcastEnabled\x12'\n" + "\x0fbroadcast_scope\x18\a \x01(\tR\x0ebroadcastScope\x12,\n" + "\x12broadcast_delay_ms\x18\b \x01(\x03R\x10broadcastDelayMs\x12.\n" + - "\x13reward_stack_policy\x18\t \x01(\tR\x11rewardStackPolicy\x128\n" + + "\x13reward_stack_policy\x18\t \x01(\tR\x11rewardStackPolicy\x126\n" + "\x06levels\x18\n" + - " \x03(\v2 .hyapp.room.v1.RoomTreasureLevelR\x06levels\x12U\n" + - "\x11gift_energy_rules\x18\v \x03(\v2).hyapp.room.v1.RoomTreasureGiftEnergyRuleR\x0fgiftEnergyRules\x12-\n" + + " \x03(\v2\x1e.hyapp.room.v1.RoomRocketLevelR\x06levels\x12M\n" + + "\x0fgift_fuel_rules\x18\v \x03(\v2%.hyapp.room.v1.RoomRocketGiftFuelRuleR\rgiftFuelRules\x12-\n" + "\x13updated_by_admin_id\x18\f \x01(\x03R\x10updatedByAdminId\x12\"\n" + "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\"S\n" + - "!AdminGetRoomTreasureConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\x8a\x01\n" + - "\"AdminGetRoomTreasureConfigResponse\x12>\n" + - "\x06config\x18\x01 \x01(\v2&.hyapp.room.v1.AdminRoomTreasureConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xb1\x01\n" + - "$AdminUpdateRoomTreasureConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12>\n" + - "\x06config\x18\x02 \x01(\v2&.hyapp.room.v1.AdminRoomTreasureConfigR\x06config\x12\x19\n" + - "\badmin_id\x18\x03 \x01(\x03R\aadminId\"\x8d\x01\n" + - "%AdminUpdateRoomTreasureConfigResponse\x12>\n" + - "\x06config\x18\x01 \x01(\v2&.hyapp.room.v1.AdminRoomTreasureConfigR\x06config\x12$\n" + + "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\"Q\n" + + "\x1fAdminGetRoomRocketConfigRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\x86\x01\n" + + " AdminGetRoomRocketConfigResponse\x12<\n" + + "\x06config\x18\x01 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xad\x01\n" + + "\"AdminUpdateRoomRocketConfigRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12<\n" + + "\x06config\x18\x02 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12\x19\n" + + "\badmin_id\x18\x03 \x01(\x03R\aadminId\"\x89\x01\n" + + "#AdminUpdateRoomRocketConfigResponse\x12<\n" + + "\x06config\x18\x01 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12$\n" + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xcb\x01\n" + "\x13AdminRoomSeatConfig\x122\n" + "\x15candidate_seat_counts\x18\x01 \x03(\x05R\x13candidateSeatCounts\x12.\n" + @@ -9367,7 +9508,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\"\n" + "\ractor_user_id\x18\x02 \x01(\x03R\vactorUserId\x12\"\n" + "\rcreated_at_ms\x18\x03 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rexpires_at_ms\x18\x04 \x01(\x03R\vexpiresAtMs\"\xdb\x06\n" + + "\rexpires_at_ms\x18\x04 \x01(\x03R\vexpiresAtMs\"\xd5\x06\n" + "\fRoomSnapshot\x12\x17\n" + "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\"\n" + "\rowner_user_id\x18\x02 \x01(\x03R\vownerUserId\x12\x12\n" + @@ -9388,8 +9529,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\bapp_code\x18\x10 \x01(\tR\aappCode\x12\"\n" + "\rroom_short_id\x18\x11 \x01(\tR\vroomShortId\x12*\n" + "\x11visible_region_id\x18\x12 \x01(\x03R\x0fvisibleRegionId\x12\x16\n" + - "\x06locked\x18\x13 \x01(\bR\x06locked\x12<\n" + - "\btreasure\x18\x14 \x01(\v2 .hyapp.room.v1.RoomTreasureStateR\btreasure\x12:\n" + + "\x06locked\x18\x13 \x01(\bR\x06locked\x126\n" + + "\x06rocket\x18\x14 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x06rocket\x12:\n" + "\n" + "ban_states\x18\x15 \x03(\v2\x1b.hyapp.room.v1.RoomBanStateR\tbanStates\x1a:\n" + "\fRoomExtEntry\x12\x10\n" + @@ -9714,14 +9855,14 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x15target_host_region_id\x18\t \x01(\x03R\x12targetHostRegionId\x12<\n" + "\x1btarget_agency_owner_user_id\x18\n" + " \x01(\x03R\x17targetAgencyOwnerUserId\x12(\n" + - "\x10sender_region_id\x18\v \x01(\x03R\x0esenderRegionId\"\xc0\x03\n" + + "\x10sender_region_id\x18\v \x01(\x03R\x0esenderRegionId\"\xba\x03\n" + "\x10SendGiftResponse\x124\n" + "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12,\n" + "\x12billing_receipt_id\x18\x02 \x01(\tR\x10billingReceiptId\x12\x1b\n" + "\troom_heat\x18\x03 \x01(\x03R\broomHeat\x124\n" + "\tgift_rank\x18\x04 \x03(\v2\x17.hyapp.room.v1.RankItemR\bgiftRank\x12/\n" + - "\x04room\x18\x05 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12<\n" + - "\btreasure\x18\x06 \x01(\v2 .hyapp.room.v1.RoomTreasureStateR\btreasure\x12A\n" + + "\x04room\x18\x05 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x126\n" + + "\x06rocket\x18\x06 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x06rocket\x12A\n" + "\n" + "lucky_gift\x18\a \x01(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\tluckyGift\x12C\n" + "\vlucky_gifts\x18\b \x03(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\n" + @@ -9833,13 +9974,13 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x04room\x18\x01 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12$\n" + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\x12\x1f\n" + "\vis_followed\x18\x03 \x01(\bR\n" + - "isFollowed\"\x87\x01\n" + - "\x16GetRoomTreasureRequest\x12.\n" + + "isFollowed\"\x85\x01\n" + + "\x14GetRoomRocketRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\"|\n" + - "\x17GetRoomTreasureResponse\x12;\n" + - "\btreasure\x18\x01 \x01(\v2\x1f.hyapp.room.v1.RoomTreasureInfoR\btreasure\x12$\n" + + "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\"t\n" + + "\x15GetRoomRocketResponse\x125\n" + + "\x06rocket\x18\x01 \x01(\v2\x1d.hyapp.room.v1.RoomRocketInfoR\x06rocket\x12$\n" + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xd0\x01\n" + "\x1aListRoomOnlineUsersRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + @@ -9890,7 +10031,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x14UnfollowRoomResponse\x12\x17\n" + "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x1a\n" + "\bfollowed\x18\x02 \x01(\bR\bfollowed\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs2\xb3\x17\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs2\xad\x17\n" + "\x12RoomCommandService\x12Q\n" + "\n" + "CreateRoom\x12 .hyapp.room.v1.CreateRoomRequest\x1a!.hyapp.room.v1.CreateRoomResponse\x12f\n" + @@ -9902,8 +10043,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\tLeaveRoom\x12\x1f.hyapp.room.v1.LeaveRoomRequest\x1a .hyapp.room.v1.LeaveRoomResponse\x12N\n" + "\tCloseRoom\x12\x1f.hyapp.room.v1.CloseRoomRequest\x1a .hyapp.room.v1.CloseRoomResponse\x12`\n" + "\x0fAdminUpdateRoom\x12%.hyapp.room.v1.AdminUpdateRoomRequest\x1a&.hyapp.room.v1.AdminUpdateRoomResponse\x12`\n" + - "\x0fAdminDeleteRoom\x12%.hyapp.room.v1.AdminDeleteRoomRequest\x1a&.hyapp.room.v1.AdminDeleteRoomResponse\x12\x8a\x01\n" + - "\x1dAdminUpdateRoomTreasureConfig\x123.hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest\x1a4.hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse\x12~\n" + + "\x0fAdminDeleteRoom\x12%.hyapp.room.v1.AdminDeleteRoomRequest\x1a&.hyapp.room.v1.AdminDeleteRoomResponse\x12\x84\x01\n" + + "\x1bAdminUpdateRoomRocketConfig\x121.hyapp.room.v1.AdminUpdateRoomRocketConfigRequest\x1a2.hyapp.room.v1.AdminUpdateRoomRocketConfigResponse\x12~\n" + "\x19AdminUpdateRoomSeatConfig\x12/.hyapp.room.v1.AdminUpdateRoomSeatConfigRequest\x1a0.hyapp.room.v1.AdminUpdateRoomSeatConfigResponse\x12i\n" + "\x12AdminCreateRoomPin\x12(.hyapp.room.v1.AdminCreateRoomPinRequest\x1a).hyapp.room.v1.AdminCreateRoomPinResponse\x12i\n" + "\x12AdminCancelRoomPin\x12(.hyapp.room.v1.AdminCancelRoomPinRequest\x1a).hyapp.room.v1.AdminCancelRoomPinResponse\x12B\n" + @@ -9929,11 +10070,11 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\fUnfollowRoom\x12\".hyapp.room.v1.UnfollowRoomRequest\x1a#.hyapp.room.v1.UnfollowRoomResponse2\xee\x01\n" + "\x10RoomGuardService\x12o\n" + "\x14CheckSpeakPermission\x12*.hyapp.room.v1.CheckSpeakPermissionRequest\x1a+.hyapp.room.v1.CheckSpeakPermissionResponse\x12i\n" + - "\x12VerifyRoomPresence\x12(.hyapp.room.v1.VerifyRoomPresenceRequest\x1a).hyapp.room.v1.VerifyRoomPresenceResponse2\x8c\f\n" + + "\x12VerifyRoomPresence\x12(.hyapp.room.v1.VerifyRoomPresenceRequest\x1a).hyapp.room.v1.VerifyRoomPresenceResponse2\xff\v\n" + "\x10RoomQueryService\x12]\n" + "\x0eAdminListRooms\x12$.hyapp.room.v1.AdminListRoomsRequest\x1a%.hyapp.room.v1.AdminListRoomsResponse\x12W\n" + - "\fAdminGetRoom\x12\".hyapp.room.v1.AdminGetRoomRequest\x1a#.hyapp.room.v1.AdminGetRoomResponse\x12\x81\x01\n" + - "\x1aAdminGetRoomTreasureConfig\x120.hyapp.room.v1.AdminGetRoomTreasureConfigRequest\x1a1.hyapp.room.v1.AdminGetRoomTreasureConfigResponse\x12u\n" + + "\fAdminGetRoom\x12\".hyapp.room.v1.AdminGetRoomRequest\x1a#.hyapp.room.v1.AdminGetRoomResponse\x12{\n" + + "\x18AdminGetRoomRocketConfig\x12..hyapp.room.v1.AdminGetRoomRocketConfigRequest\x1a/.hyapp.room.v1.AdminGetRoomRocketConfigResponse\x12u\n" + "\x16AdminGetRoomSeatConfig\x12,.hyapp.room.v1.AdminGetRoomSeatConfigRequest\x1a-.hyapp.room.v1.AdminGetRoomSeatConfigResponse\x12f\n" + "\x11AdminListRoomPins\x12'.hyapp.room.v1.AdminListRoomPinsRequest\x1a(.hyapp.room.v1.AdminListRoomPinsResponse\x12N\n" + "\tListRooms\x12\x1f.hyapp.room.v1.ListRoomsRequest\x1a .hyapp.room.v1.ListRoomsResponse\x12V\n" + @@ -9942,8 +10083,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\tGetMyRoom\x12\x1f.hyapp.room.v1.GetMyRoomRequest\x1a .hyapp.room.v1.GetMyRoomResponse\x12]\n" + "\x0eGetCurrentRoom\x12$.hyapp.room.v1.GetCurrentRoomRequest\x1a%.hyapp.room.v1.GetCurrentRoomResponse\x12`\n" + "\x0fGetRoomSnapshot\x12%.hyapp.room.v1.GetRoomSnapshotRequest\x1a&.hyapp.room.v1.GetRoomSnapshotResponse\x12l\n" + - "\x13ListRoomBackgrounds\x12).hyapp.room.v1.ListRoomBackgroundsRequest\x1a*.hyapp.room.v1.ListRoomBackgroundsResponse\x12`\n" + - "\x0fGetRoomTreasure\x12%.hyapp.room.v1.GetRoomTreasureRequest\x1a&.hyapp.room.v1.GetRoomTreasureResponse\x12l\n" + + "\x13ListRoomBackgrounds\x12).hyapp.room.v1.ListRoomBackgroundsRequest\x1a*.hyapp.room.v1.ListRoomBackgroundsResponse\x12Z\n" + + "\rGetRoomRocket\x12#.hyapp.room.v1.GetRoomRocketRequest\x1a$.hyapp.room.v1.GetRoomRocketResponse\x12l\n" + "\x13ListRoomOnlineUsers\x12).hyapp.room.v1.ListRoomOnlineUsersRequest\x1a*.hyapp.room.v1.ListRoomOnlineUsersResponse\x12l\n" + "\x13ListRoomBannedUsers\x12).hyapp.room.v1.ListRoomBannedUsersRequest\x1a*.hyapp.room.v1.ListRoomBannedUsersResponseB&Z$hyapp.local/api/proto/room/v1;roomv1b\x06proto3" @@ -9959,379 +10100,381 @@ func file_proto_room_v1_room_proto_rawDescGZIP() []byte { return file_proto_room_v1_room_proto_rawDescData } -var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 124) +var file_proto_room_v1_room_proto_msgTypes = make([]protoimpl.MessageInfo, 125) var file_proto_room_v1_room_proto_goTypes = []any{ - (*RequestMeta)(nil), // 0: hyapp.room.v1.RequestMeta - (*CommandResult)(nil), // 1: hyapp.room.v1.CommandResult - (*RoomUser)(nil), // 2: hyapp.room.v1.RoomUser - (*RoomOnlineUser)(nil), // 3: hyapp.room.v1.RoomOnlineUser - (*SeatState)(nil), // 4: hyapp.room.v1.SeatState - (*RankItem)(nil), // 5: hyapp.room.v1.RankItem - (*LuckyGiftDrawResult)(nil), // 6: hyapp.room.v1.LuckyGiftDrawResult - (*RoomTreasureRewardItem)(nil), // 7: hyapp.room.v1.RoomTreasureRewardItem - (*RoomTreasureLevel)(nil), // 8: hyapp.room.v1.RoomTreasureLevel - (*RoomTreasureRewardGrant)(nil), // 9: hyapp.room.v1.RoomTreasureRewardGrant - (*RoomTreasureState)(nil), // 10: hyapp.room.v1.RoomTreasureState - (*RoomTreasureInfo)(nil), // 11: hyapp.room.v1.RoomTreasureInfo - (*RoomTreasureGiftEnergyRule)(nil), // 12: hyapp.room.v1.RoomTreasureGiftEnergyRule - (*AdminRoomTreasureConfig)(nil), // 13: hyapp.room.v1.AdminRoomTreasureConfig - (*AdminGetRoomTreasureConfigRequest)(nil), // 14: hyapp.room.v1.AdminGetRoomTreasureConfigRequest - (*AdminGetRoomTreasureConfigResponse)(nil), // 15: hyapp.room.v1.AdminGetRoomTreasureConfigResponse - (*AdminUpdateRoomTreasureConfigRequest)(nil), // 16: hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest - (*AdminUpdateRoomTreasureConfigResponse)(nil), // 17: hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse - (*AdminRoomSeatConfig)(nil), // 18: hyapp.room.v1.AdminRoomSeatConfig - (*AdminGetRoomSeatConfigRequest)(nil), // 19: hyapp.room.v1.AdminGetRoomSeatConfigRequest - (*AdminGetRoomSeatConfigResponse)(nil), // 20: hyapp.room.v1.AdminGetRoomSeatConfigResponse - (*AdminUpdateRoomSeatConfigRequest)(nil), // 21: hyapp.room.v1.AdminUpdateRoomSeatConfigRequest - (*AdminUpdateRoomSeatConfigResponse)(nil), // 22: hyapp.room.v1.AdminUpdateRoomSeatConfigResponse - (*AdminRoomPinRoom)(nil), // 23: hyapp.room.v1.AdminRoomPinRoom - (*AdminRoomPin)(nil), // 24: hyapp.room.v1.AdminRoomPin - (*AdminListRoomPinsRequest)(nil), // 25: hyapp.room.v1.AdminListRoomPinsRequest - (*AdminListRoomPinsResponse)(nil), // 26: hyapp.room.v1.AdminListRoomPinsResponse - (*AdminCreateRoomPinRequest)(nil), // 27: hyapp.room.v1.AdminCreateRoomPinRequest - (*AdminCreateRoomPinResponse)(nil), // 28: hyapp.room.v1.AdminCreateRoomPinResponse - (*AdminCancelRoomPinRequest)(nil), // 29: hyapp.room.v1.AdminCancelRoomPinRequest - (*AdminCancelRoomPinResponse)(nil), // 30: hyapp.room.v1.AdminCancelRoomPinResponse - (*RoomBanState)(nil), // 31: hyapp.room.v1.RoomBanState - (*RoomSnapshot)(nil), // 32: hyapp.room.v1.RoomSnapshot - (*RoomBackgroundImage)(nil), // 33: hyapp.room.v1.RoomBackgroundImage - (*SaveRoomBackgroundRequest)(nil), // 34: hyapp.room.v1.SaveRoomBackgroundRequest - (*SaveRoomBackgroundResponse)(nil), // 35: hyapp.room.v1.SaveRoomBackgroundResponse - (*ListRoomBackgroundsRequest)(nil), // 36: hyapp.room.v1.ListRoomBackgroundsRequest - (*ListRoomBackgroundsResponse)(nil), // 37: hyapp.room.v1.ListRoomBackgroundsResponse - (*SetRoomBackgroundRequest)(nil), // 38: hyapp.room.v1.SetRoomBackgroundRequest - (*SetRoomBackgroundResponse)(nil), // 39: hyapp.room.v1.SetRoomBackgroundResponse - (*CreateRoomRequest)(nil), // 40: hyapp.room.v1.CreateRoomRequest - (*CreateRoomResponse)(nil), // 41: hyapp.room.v1.CreateRoomResponse - (*UpdateRoomProfileRequest)(nil), // 42: hyapp.room.v1.UpdateRoomProfileRequest - (*UpdateRoomProfileResponse)(nil), // 43: hyapp.room.v1.UpdateRoomProfileResponse - (*RoomEntryVehicleSnapshot)(nil), // 44: hyapp.room.v1.RoomEntryVehicleSnapshot - (*JoinRoomRequest)(nil), // 45: hyapp.room.v1.JoinRoomRequest - (*JoinRoomResponse)(nil), // 46: hyapp.room.v1.JoinRoomResponse - (*RoomHeartbeatRequest)(nil), // 47: hyapp.room.v1.RoomHeartbeatRequest - (*RoomHeartbeatResponse)(nil), // 48: hyapp.room.v1.RoomHeartbeatResponse - (*LeaveRoomRequest)(nil), // 49: hyapp.room.v1.LeaveRoomRequest - (*LeaveRoomResponse)(nil), // 50: hyapp.room.v1.LeaveRoomResponse - (*CloseRoomRequest)(nil), // 51: hyapp.room.v1.CloseRoomRequest - (*CloseRoomResponse)(nil), // 52: hyapp.room.v1.CloseRoomResponse - (*AdminRoomListItem)(nil), // 53: hyapp.room.v1.AdminRoomListItem - (*AdminListRoomsRequest)(nil), // 54: hyapp.room.v1.AdminListRoomsRequest - (*AdminListRoomsResponse)(nil), // 55: hyapp.room.v1.AdminListRoomsResponse - (*AdminGetRoomRequest)(nil), // 56: hyapp.room.v1.AdminGetRoomRequest - (*AdminGetRoomResponse)(nil), // 57: hyapp.room.v1.AdminGetRoomResponse - (*AdminUpdateRoomRequest)(nil), // 58: hyapp.room.v1.AdminUpdateRoomRequest - (*AdminUpdateRoomResponse)(nil), // 59: hyapp.room.v1.AdminUpdateRoomResponse - (*AdminDeleteRoomRequest)(nil), // 60: hyapp.room.v1.AdminDeleteRoomRequest - (*AdminDeleteRoomResponse)(nil), // 61: hyapp.room.v1.AdminDeleteRoomResponse - (*MicUpRequest)(nil), // 62: hyapp.room.v1.MicUpRequest - (*MicUpResponse)(nil), // 63: hyapp.room.v1.MicUpResponse - (*MicDownRequest)(nil), // 64: hyapp.room.v1.MicDownRequest - (*MicDownResponse)(nil), // 65: hyapp.room.v1.MicDownResponse - (*ChangeMicSeatRequest)(nil), // 66: hyapp.room.v1.ChangeMicSeatRequest - (*ChangeMicSeatResponse)(nil), // 67: hyapp.room.v1.ChangeMicSeatResponse - (*ConfirmMicPublishingRequest)(nil), // 68: hyapp.room.v1.ConfirmMicPublishingRequest - (*ConfirmMicPublishingResponse)(nil), // 69: hyapp.room.v1.ConfirmMicPublishingResponse - (*MicHeartbeatRequest)(nil), // 70: hyapp.room.v1.MicHeartbeatRequest - (*MicHeartbeatResponse)(nil), // 71: hyapp.room.v1.MicHeartbeatResponse - (*SetMicMuteRequest)(nil), // 72: hyapp.room.v1.SetMicMuteRequest - (*SetMicMuteResponse)(nil), // 73: hyapp.room.v1.SetMicMuteResponse - (*ApplyRTCEventRequest)(nil), // 74: hyapp.room.v1.ApplyRTCEventRequest - (*ApplyRTCEventResponse)(nil), // 75: hyapp.room.v1.ApplyRTCEventResponse - (*SetMicSeatLockRequest)(nil), // 76: hyapp.room.v1.SetMicSeatLockRequest - (*SetMicSeatLockResponse)(nil), // 77: hyapp.room.v1.SetMicSeatLockResponse - (*SetChatEnabledRequest)(nil), // 78: hyapp.room.v1.SetChatEnabledRequest - (*SetChatEnabledResponse)(nil), // 79: hyapp.room.v1.SetChatEnabledResponse - (*SetRoomPasswordRequest)(nil), // 80: hyapp.room.v1.SetRoomPasswordRequest - (*SetRoomPasswordResponse)(nil), // 81: hyapp.room.v1.SetRoomPasswordResponse - (*SetRoomAdminRequest)(nil), // 82: hyapp.room.v1.SetRoomAdminRequest - (*SetRoomAdminResponse)(nil), // 83: hyapp.room.v1.SetRoomAdminResponse - (*MuteUserRequest)(nil), // 84: hyapp.room.v1.MuteUserRequest - (*MuteUserResponse)(nil), // 85: hyapp.room.v1.MuteUserResponse - (*KickUserRequest)(nil), // 86: hyapp.room.v1.KickUserRequest - (*KickUserResponse)(nil), // 87: hyapp.room.v1.KickUserResponse - (*UnbanUserRequest)(nil), // 88: hyapp.room.v1.UnbanUserRequest - (*UnbanUserResponse)(nil), // 89: hyapp.room.v1.UnbanUserResponse - (*SystemEvictUserRequest)(nil), // 90: hyapp.room.v1.SystemEvictUserRequest - (*SystemEvictUserResponse)(nil), // 91: hyapp.room.v1.SystemEvictUserResponse - (*SendGiftRequest)(nil), // 92: hyapp.room.v1.SendGiftRequest - (*SendGiftResponse)(nil), // 93: hyapp.room.v1.SendGiftResponse - (*CheckSpeakPermissionRequest)(nil), // 94: hyapp.room.v1.CheckSpeakPermissionRequest - (*CheckSpeakPermissionResponse)(nil), // 95: hyapp.room.v1.CheckSpeakPermissionResponse - (*VerifyRoomPresenceRequest)(nil), // 96: hyapp.room.v1.VerifyRoomPresenceRequest - (*VerifyRoomPresenceResponse)(nil), // 97: hyapp.room.v1.VerifyRoomPresenceResponse - (*ListRoomsRequest)(nil), // 98: hyapp.room.v1.ListRoomsRequest - (*ListRoomFeedsRequest)(nil), // 99: hyapp.room.v1.ListRoomFeedsRequest - (*ListRoomGiftLeaderboardRequest)(nil), // 100: hyapp.room.v1.ListRoomGiftLeaderboardRequest - (*RoomFeedRelatedUser)(nil), // 101: hyapp.room.v1.RoomFeedRelatedUser - (*RoomListItem)(nil), // 102: hyapp.room.v1.RoomListItem - (*ListRoomsResponse)(nil), // 103: hyapp.room.v1.ListRoomsResponse - (*RoomGiftLeaderboardItem)(nil), // 104: hyapp.room.v1.RoomGiftLeaderboardItem - (*ListRoomGiftLeaderboardResponse)(nil), // 105: hyapp.room.v1.ListRoomGiftLeaderboardResponse - (*GetMyRoomRequest)(nil), // 106: hyapp.room.v1.GetMyRoomRequest - (*GetMyRoomResponse)(nil), // 107: hyapp.room.v1.GetMyRoomResponse - (*GetCurrentRoomRequest)(nil), // 108: hyapp.room.v1.GetCurrentRoomRequest - (*GetCurrentRoomResponse)(nil), // 109: hyapp.room.v1.GetCurrentRoomResponse - (*GetRoomSnapshotRequest)(nil), // 110: hyapp.room.v1.GetRoomSnapshotRequest - (*GetRoomSnapshotResponse)(nil), // 111: hyapp.room.v1.GetRoomSnapshotResponse - (*GetRoomTreasureRequest)(nil), // 112: hyapp.room.v1.GetRoomTreasureRequest - (*GetRoomTreasureResponse)(nil), // 113: hyapp.room.v1.GetRoomTreasureResponse - (*ListRoomOnlineUsersRequest)(nil), // 114: hyapp.room.v1.ListRoomOnlineUsersRequest - (*ListRoomOnlineUsersResponse)(nil), // 115: hyapp.room.v1.ListRoomOnlineUsersResponse - (*RoomBannedUser)(nil), // 116: hyapp.room.v1.RoomBannedUser - (*ListRoomBannedUsersRequest)(nil), // 117: hyapp.room.v1.ListRoomBannedUsersRequest - (*ListRoomBannedUsersResponse)(nil), // 118: hyapp.room.v1.ListRoomBannedUsersResponse - (*FollowRoomRequest)(nil), // 119: hyapp.room.v1.FollowRoomRequest - (*FollowRoomResponse)(nil), // 120: hyapp.room.v1.FollowRoomResponse - (*UnfollowRoomRequest)(nil), // 121: hyapp.room.v1.UnfollowRoomRequest - (*UnfollowRoomResponse)(nil), // 122: hyapp.room.v1.UnfollowRoomResponse - nil, // 123: hyapp.room.v1.RoomSnapshot.RoomExtEntry + (*RequestMeta)(nil), // 0: hyapp.room.v1.RequestMeta + (*CommandResult)(nil), // 1: hyapp.room.v1.CommandResult + (*RoomUser)(nil), // 2: hyapp.room.v1.RoomUser + (*RoomOnlineUser)(nil), // 3: hyapp.room.v1.RoomOnlineUser + (*SeatState)(nil), // 4: hyapp.room.v1.SeatState + (*RankItem)(nil), // 5: hyapp.room.v1.RankItem + (*LuckyGiftDrawResult)(nil), // 6: hyapp.room.v1.LuckyGiftDrawResult + (*RoomRocketRewardItem)(nil), // 7: hyapp.room.v1.RoomRocketRewardItem + (*RoomRocketLevel)(nil), // 8: hyapp.room.v1.RoomRocketLevel + (*RoomRocketRewardGrant)(nil), // 9: hyapp.room.v1.RoomRocketRewardGrant + (*RoomRocketPendingLaunch)(nil), // 10: hyapp.room.v1.RoomRocketPendingLaunch + (*RoomRocketState)(nil), // 11: hyapp.room.v1.RoomRocketState + (*RoomRocketInfo)(nil), // 12: hyapp.room.v1.RoomRocketInfo + (*RoomRocketGiftFuelRule)(nil), // 13: hyapp.room.v1.RoomRocketGiftFuelRule + (*AdminRoomRocketConfig)(nil), // 14: hyapp.room.v1.AdminRoomRocketConfig + (*AdminGetRoomRocketConfigRequest)(nil), // 15: hyapp.room.v1.AdminGetRoomRocketConfigRequest + (*AdminGetRoomRocketConfigResponse)(nil), // 16: hyapp.room.v1.AdminGetRoomRocketConfigResponse + (*AdminUpdateRoomRocketConfigRequest)(nil), // 17: hyapp.room.v1.AdminUpdateRoomRocketConfigRequest + (*AdminUpdateRoomRocketConfigResponse)(nil), // 18: hyapp.room.v1.AdminUpdateRoomRocketConfigResponse + (*AdminRoomSeatConfig)(nil), // 19: hyapp.room.v1.AdminRoomSeatConfig + (*AdminGetRoomSeatConfigRequest)(nil), // 20: hyapp.room.v1.AdminGetRoomSeatConfigRequest + (*AdminGetRoomSeatConfigResponse)(nil), // 21: hyapp.room.v1.AdminGetRoomSeatConfigResponse + (*AdminUpdateRoomSeatConfigRequest)(nil), // 22: hyapp.room.v1.AdminUpdateRoomSeatConfigRequest + (*AdminUpdateRoomSeatConfigResponse)(nil), // 23: hyapp.room.v1.AdminUpdateRoomSeatConfigResponse + (*AdminRoomPinRoom)(nil), // 24: hyapp.room.v1.AdminRoomPinRoom + (*AdminRoomPin)(nil), // 25: hyapp.room.v1.AdminRoomPin + (*AdminListRoomPinsRequest)(nil), // 26: hyapp.room.v1.AdminListRoomPinsRequest + (*AdminListRoomPinsResponse)(nil), // 27: hyapp.room.v1.AdminListRoomPinsResponse + (*AdminCreateRoomPinRequest)(nil), // 28: hyapp.room.v1.AdminCreateRoomPinRequest + (*AdminCreateRoomPinResponse)(nil), // 29: hyapp.room.v1.AdminCreateRoomPinResponse + (*AdminCancelRoomPinRequest)(nil), // 30: hyapp.room.v1.AdminCancelRoomPinRequest + (*AdminCancelRoomPinResponse)(nil), // 31: hyapp.room.v1.AdminCancelRoomPinResponse + (*RoomBanState)(nil), // 32: hyapp.room.v1.RoomBanState + (*RoomSnapshot)(nil), // 33: hyapp.room.v1.RoomSnapshot + (*RoomBackgroundImage)(nil), // 34: hyapp.room.v1.RoomBackgroundImage + (*SaveRoomBackgroundRequest)(nil), // 35: hyapp.room.v1.SaveRoomBackgroundRequest + (*SaveRoomBackgroundResponse)(nil), // 36: hyapp.room.v1.SaveRoomBackgroundResponse + (*ListRoomBackgroundsRequest)(nil), // 37: hyapp.room.v1.ListRoomBackgroundsRequest + (*ListRoomBackgroundsResponse)(nil), // 38: hyapp.room.v1.ListRoomBackgroundsResponse + (*SetRoomBackgroundRequest)(nil), // 39: hyapp.room.v1.SetRoomBackgroundRequest + (*SetRoomBackgroundResponse)(nil), // 40: hyapp.room.v1.SetRoomBackgroundResponse + (*CreateRoomRequest)(nil), // 41: hyapp.room.v1.CreateRoomRequest + (*CreateRoomResponse)(nil), // 42: hyapp.room.v1.CreateRoomResponse + (*UpdateRoomProfileRequest)(nil), // 43: hyapp.room.v1.UpdateRoomProfileRequest + (*UpdateRoomProfileResponse)(nil), // 44: hyapp.room.v1.UpdateRoomProfileResponse + (*RoomEntryVehicleSnapshot)(nil), // 45: hyapp.room.v1.RoomEntryVehicleSnapshot + (*JoinRoomRequest)(nil), // 46: hyapp.room.v1.JoinRoomRequest + (*JoinRoomResponse)(nil), // 47: hyapp.room.v1.JoinRoomResponse + (*RoomHeartbeatRequest)(nil), // 48: hyapp.room.v1.RoomHeartbeatRequest + (*RoomHeartbeatResponse)(nil), // 49: hyapp.room.v1.RoomHeartbeatResponse + (*LeaveRoomRequest)(nil), // 50: hyapp.room.v1.LeaveRoomRequest + (*LeaveRoomResponse)(nil), // 51: hyapp.room.v1.LeaveRoomResponse + (*CloseRoomRequest)(nil), // 52: hyapp.room.v1.CloseRoomRequest + (*CloseRoomResponse)(nil), // 53: hyapp.room.v1.CloseRoomResponse + (*AdminRoomListItem)(nil), // 54: hyapp.room.v1.AdminRoomListItem + (*AdminListRoomsRequest)(nil), // 55: hyapp.room.v1.AdminListRoomsRequest + (*AdminListRoomsResponse)(nil), // 56: hyapp.room.v1.AdminListRoomsResponse + (*AdminGetRoomRequest)(nil), // 57: hyapp.room.v1.AdminGetRoomRequest + (*AdminGetRoomResponse)(nil), // 58: hyapp.room.v1.AdminGetRoomResponse + (*AdminUpdateRoomRequest)(nil), // 59: hyapp.room.v1.AdminUpdateRoomRequest + (*AdminUpdateRoomResponse)(nil), // 60: hyapp.room.v1.AdminUpdateRoomResponse + (*AdminDeleteRoomRequest)(nil), // 61: hyapp.room.v1.AdminDeleteRoomRequest + (*AdminDeleteRoomResponse)(nil), // 62: hyapp.room.v1.AdminDeleteRoomResponse + (*MicUpRequest)(nil), // 63: hyapp.room.v1.MicUpRequest + (*MicUpResponse)(nil), // 64: hyapp.room.v1.MicUpResponse + (*MicDownRequest)(nil), // 65: hyapp.room.v1.MicDownRequest + (*MicDownResponse)(nil), // 66: hyapp.room.v1.MicDownResponse + (*ChangeMicSeatRequest)(nil), // 67: hyapp.room.v1.ChangeMicSeatRequest + (*ChangeMicSeatResponse)(nil), // 68: hyapp.room.v1.ChangeMicSeatResponse + (*ConfirmMicPublishingRequest)(nil), // 69: hyapp.room.v1.ConfirmMicPublishingRequest + (*ConfirmMicPublishingResponse)(nil), // 70: hyapp.room.v1.ConfirmMicPublishingResponse + (*MicHeartbeatRequest)(nil), // 71: hyapp.room.v1.MicHeartbeatRequest + (*MicHeartbeatResponse)(nil), // 72: hyapp.room.v1.MicHeartbeatResponse + (*SetMicMuteRequest)(nil), // 73: hyapp.room.v1.SetMicMuteRequest + (*SetMicMuteResponse)(nil), // 74: hyapp.room.v1.SetMicMuteResponse + (*ApplyRTCEventRequest)(nil), // 75: hyapp.room.v1.ApplyRTCEventRequest + (*ApplyRTCEventResponse)(nil), // 76: hyapp.room.v1.ApplyRTCEventResponse + (*SetMicSeatLockRequest)(nil), // 77: hyapp.room.v1.SetMicSeatLockRequest + (*SetMicSeatLockResponse)(nil), // 78: hyapp.room.v1.SetMicSeatLockResponse + (*SetChatEnabledRequest)(nil), // 79: hyapp.room.v1.SetChatEnabledRequest + (*SetChatEnabledResponse)(nil), // 80: hyapp.room.v1.SetChatEnabledResponse + (*SetRoomPasswordRequest)(nil), // 81: hyapp.room.v1.SetRoomPasswordRequest + (*SetRoomPasswordResponse)(nil), // 82: hyapp.room.v1.SetRoomPasswordResponse + (*SetRoomAdminRequest)(nil), // 83: hyapp.room.v1.SetRoomAdminRequest + (*SetRoomAdminResponse)(nil), // 84: hyapp.room.v1.SetRoomAdminResponse + (*MuteUserRequest)(nil), // 85: hyapp.room.v1.MuteUserRequest + (*MuteUserResponse)(nil), // 86: hyapp.room.v1.MuteUserResponse + (*KickUserRequest)(nil), // 87: hyapp.room.v1.KickUserRequest + (*KickUserResponse)(nil), // 88: hyapp.room.v1.KickUserResponse + (*UnbanUserRequest)(nil), // 89: hyapp.room.v1.UnbanUserRequest + (*UnbanUserResponse)(nil), // 90: hyapp.room.v1.UnbanUserResponse + (*SystemEvictUserRequest)(nil), // 91: hyapp.room.v1.SystemEvictUserRequest + (*SystemEvictUserResponse)(nil), // 92: hyapp.room.v1.SystemEvictUserResponse + (*SendGiftRequest)(nil), // 93: hyapp.room.v1.SendGiftRequest + (*SendGiftResponse)(nil), // 94: hyapp.room.v1.SendGiftResponse + (*CheckSpeakPermissionRequest)(nil), // 95: hyapp.room.v1.CheckSpeakPermissionRequest + (*CheckSpeakPermissionResponse)(nil), // 96: hyapp.room.v1.CheckSpeakPermissionResponse + (*VerifyRoomPresenceRequest)(nil), // 97: hyapp.room.v1.VerifyRoomPresenceRequest + (*VerifyRoomPresenceResponse)(nil), // 98: hyapp.room.v1.VerifyRoomPresenceResponse + (*ListRoomsRequest)(nil), // 99: hyapp.room.v1.ListRoomsRequest + (*ListRoomFeedsRequest)(nil), // 100: hyapp.room.v1.ListRoomFeedsRequest + (*ListRoomGiftLeaderboardRequest)(nil), // 101: hyapp.room.v1.ListRoomGiftLeaderboardRequest + (*RoomFeedRelatedUser)(nil), // 102: hyapp.room.v1.RoomFeedRelatedUser + (*RoomListItem)(nil), // 103: hyapp.room.v1.RoomListItem + (*ListRoomsResponse)(nil), // 104: hyapp.room.v1.ListRoomsResponse + (*RoomGiftLeaderboardItem)(nil), // 105: hyapp.room.v1.RoomGiftLeaderboardItem + (*ListRoomGiftLeaderboardResponse)(nil), // 106: hyapp.room.v1.ListRoomGiftLeaderboardResponse + (*GetMyRoomRequest)(nil), // 107: hyapp.room.v1.GetMyRoomRequest + (*GetMyRoomResponse)(nil), // 108: hyapp.room.v1.GetMyRoomResponse + (*GetCurrentRoomRequest)(nil), // 109: hyapp.room.v1.GetCurrentRoomRequest + (*GetCurrentRoomResponse)(nil), // 110: hyapp.room.v1.GetCurrentRoomResponse + (*GetRoomSnapshotRequest)(nil), // 111: hyapp.room.v1.GetRoomSnapshotRequest + (*GetRoomSnapshotResponse)(nil), // 112: hyapp.room.v1.GetRoomSnapshotResponse + (*GetRoomRocketRequest)(nil), // 113: hyapp.room.v1.GetRoomRocketRequest + (*GetRoomRocketResponse)(nil), // 114: hyapp.room.v1.GetRoomRocketResponse + (*ListRoomOnlineUsersRequest)(nil), // 115: hyapp.room.v1.ListRoomOnlineUsersRequest + (*ListRoomOnlineUsersResponse)(nil), // 116: hyapp.room.v1.ListRoomOnlineUsersResponse + (*RoomBannedUser)(nil), // 117: hyapp.room.v1.RoomBannedUser + (*ListRoomBannedUsersRequest)(nil), // 118: hyapp.room.v1.ListRoomBannedUsersRequest + (*ListRoomBannedUsersResponse)(nil), // 119: hyapp.room.v1.ListRoomBannedUsersResponse + (*FollowRoomRequest)(nil), // 120: hyapp.room.v1.FollowRoomRequest + (*FollowRoomResponse)(nil), // 121: hyapp.room.v1.FollowRoomResponse + (*UnfollowRoomRequest)(nil), // 122: hyapp.room.v1.UnfollowRoomRequest + (*UnfollowRoomResponse)(nil), // 123: hyapp.room.v1.UnfollowRoomResponse + nil, // 124: hyapp.room.v1.RoomSnapshot.RoomExtEntry } var file_proto_room_v1_room_proto_depIdxs = []int32{ - 7, // 0: hyapp.room.v1.RoomTreasureLevel.in_room_rewards:type_name -> hyapp.room.v1.RoomTreasureRewardItem - 7, // 1: hyapp.room.v1.RoomTreasureLevel.top1_rewards:type_name -> hyapp.room.v1.RoomTreasureRewardItem - 7, // 2: hyapp.room.v1.RoomTreasureLevel.igniter_rewards:type_name -> hyapp.room.v1.RoomTreasureRewardItem - 9, // 3: hyapp.room.v1.RoomTreasureState.last_rewards:type_name -> hyapp.room.v1.RoomTreasureRewardGrant - 8, // 4: hyapp.room.v1.RoomTreasureInfo.levels:type_name -> hyapp.room.v1.RoomTreasureLevel - 10, // 5: hyapp.room.v1.RoomTreasureInfo.state:type_name -> hyapp.room.v1.RoomTreasureState - 8, // 6: hyapp.room.v1.AdminRoomTreasureConfig.levels:type_name -> hyapp.room.v1.RoomTreasureLevel - 12, // 7: hyapp.room.v1.AdminRoomTreasureConfig.gift_energy_rules:type_name -> hyapp.room.v1.RoomTreasureGiftEnergyRule - 0, // 8: hyapp.room.v1.AdminGetRoomTreasureConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 13, // 9: hyapp.room.v1.AdminGetRoomTreasureConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomTreasureConfig - 0, // 10: hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 13, // 11: hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest.config:type_name -> hyapp.room.v1.AdminRoomTreasureConfig - 13, // 12: hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomTreasureConfig - 0, // 13: hyapp.room.v1.AdminGetRoomSeatConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 18, // 14: hyapp.room.v1.AdminGetRoomSeatConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomSeatConfig - 0, // 15: hyapp.room.v1.AdminUpdateRoomSeatConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 18, // 16: hyapp.room.v1.AdminUpdateRoomSeatConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomSeatConfig - 23, // 17: hyapp.room.v1.AdminRoomPin.room:type_name -> hyapp.room.v1.AdminRoomPinRoom - 0, // 18: hyapp.room.v1.AdminListRoomPinsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 24, // 19: hyapp.room.v1.AdminListRoomPinsResponse.pins:type_name -> hyapp.room.v1.AdminRoomPin - 0, // 20: hyapp.room.v1.AdminCreateRoomPinRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 24, // 21: hyapp.room.v1.AdminCreateRoomPinResponse.pin:type_name -> hyapp.room.v1.AdminRoomPin - 0, // 22: hyapp.room.v1.AdminCancelRoomPinRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 24, // 23: hyapp.room.v1.AdminCancelRoomPinResponse.pin:type_name -> hyapp.room.v1.AdminRoomPin - 4, // 24: hyapp.room.v1.RoomSnapshot.mic_seats:type_name -> hyapp.room.v1.SeatState - 2, // 25: hyapp.room.v1.RoomSnapshot.online_users:type_name -> hyapp.room.v1.RoomUser - 5, // 26: hyapp.room.v1.RoomSnapshot.gift_rank:type_name -> hyapp.room.v1.RankItem - 123, // 27: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry - 10, // 28: hyapp.room.v1.RoomSnapshot.treasure:type_name -> hyapp.room.v1.RoomTreasureState - 31, // 29: hyapp.room.v1.RoomSnapshot.ban_states:type_name -> hyapp.room.v1.RoomBanState - 0, // 30: hyapp.room.v1.SaveRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 33, // 31: hyapp.room.v1.SaveRoomBackgroundResponse.background:type_name -> hyapp.room.v1.RoomBackgroundImage - 0, // 32: hyapp.room.v1.ListRoomBackgroundsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 33, // 33: hyapp.room.v1.ListRoomBackgroundsResponse.backgrounds:type_name -> hyapp.room.v1.RoomBackgroundImage - 0, // 34: hyapp.room.v1.SetRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 35: hyapp.room.v1.SetRoomBackgroundResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 36: hyapp.room.v1.SetRoomBackgroundResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 33, // 37: hyapp.room.v1.SetRoomBackgroundResponse.background:type_name -> hyapp.room.v1.RoomBackgroundImage - 0, // 38: hyapp.room.v1.CreateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 39: hyapp.room.v1.CreateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 40: hyapp.room.v1.CreateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 41: hyapp.room.v1.UpdateRoomProfileRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 42: hyapp.room.v1.UpdateRoomProfileResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 43: hyapp.room.v1.UpdateRoomProfileResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 44: hyapp.room.v1.JoinRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 44, // 45: hyapp.room.v1.JoinRoomRequest.entry_vehicle:type_name -> hyapp.room.v1.RoomEntryVehicleSnapshot - 1, // 46: hyapp.room.v1.JoinRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 2, // 47: hyapp.room.v1.JoinRoomResponse.user:type_name -> hyapp.room.v1.RoomUser - 32, // 48: hyapp.room.v1.JoinRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 49: hyapp.room.v1.RoomHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 50: hyapp.room.v1.RoomHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 2, // 51: hyapp.room.v1.RoomHeartbeatResponse.user:type_name -> hyapp.room.v1.RoomUser - 32, // 52: hyapp.room.v1.RoomHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 53: hyapp.room.v1.LeaveRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 54: hyapp.room.v1.LeaveRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 55: hyapp.room.v1.LeaveRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 56: hyapp.room.v1.CloseRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 57: hyapp.room.v1.CloseRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 58: hyapp.room.v1.CloseRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 59: hyapp.room.v1.AdminListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 53, // 60: hyapp.room.v1.AdminListRoomsResponse.rooms:type_name -> hyapp.room.v1.AdminRoomListItem - 0, // 61: hyapp.room.v1.AdminGetRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 53, // 62: hyapp.room.v1.AdminGetRoomResponse.room:type_name -> hyapp.room.v1.AdminRoomListItem - 0, // 63: hyapp.room.v1.AdminUpdateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 64: hyapp.room.v1.AdminUpdateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 65: hyapp.room.v1.AdminUpdateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 66: hyapp.room.v1.AdminDeleteRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 67: hyapp.room.v1.AdminDeleteRoomResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 68: hyapp.room.v1.AdminDeleteRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 69: hyapp.room.v1.MicUpRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 70: hyapp.room.v1.MicUpResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 71: hyapp.room.v1.MicUpResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 72: hyapp.room.v1.MicDownRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 73: hyapp.room.v1.MicDownResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 74: hyapp.room.v1.MicDownResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 75: hyapp.room.v1.ChangeMicSeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 76: hyapp.room.v1.ChangeMicSeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 77: hyapp.room.v1.ChangeMicSeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 78: hyapp.room.v1.ConfirmMicPublishingRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 79: hyapp.room.v1.ConfirmMicPublishingResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 80: hyapp.room.v1.ConfirmMicPublishingResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 81: hyapp.room.v1.MicHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 82: hyapp.room.v1.MicHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 83: hyapp.room.v1.MicHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 84: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 85: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 86: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 87: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 88: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 89: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 90: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 91: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 92: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 93: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 94: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 95: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 96: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 97: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 98: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 99: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 100: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 101: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 102: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 103: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 104: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 105: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 106: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 107: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 108: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 109: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 110: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 111: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 112: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult - 32, // 113: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 114: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 1, // 115: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult - 5, // 116: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem - 32, // 117: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 10, // 118: hyapp.room.v1.SendGiftResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureState - 6, // 119: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 6, // 120: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult - 0, // 121: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 122: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 101, // 123: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser - 0, // 124: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 102, // 125: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem - 102, // 126: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem - 104, // 127: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem - 0, // 128: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 102, // 129: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem - 0, // 130: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 131: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 32, // 132: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot - 0, // 133: hyapp.room.v1.GetRoomTreasureRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 11, // 134: hyapp.room.v1.GetRoomTreasureResponse.treasure:type_name -> hyapp.room.v1.RoomTreasureInfo - 0, // 135: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 2, // 136: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser - 3, // 137: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser - 0, // 138: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 116, // 139: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser - 0, // 140: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 0, // 141: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta - 40, // 142: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest - 42, // 143: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest - 34, // 144: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest - 38, // 145: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest - 45, // 146: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest - 47, // 147: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest - 49, // 148: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest - 51, // 149: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest - 58, // 150: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest - 60, // 151: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest - 16, // 152: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:input_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigRequest - 21, // 153: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest - 27, // 154: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest - 29, // 155: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest - 62, // 156: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest - 64, // 157: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest - 66, // 158: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest - 68, // 159: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest - 70, // 160: hyapp.room.v1.RoomCommandService.MicHeartbeat:input_type -> hyapp.room.v1.MicHeartbeatRequest - 72, // 161: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest - 74, // 162: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest - 76, // 163: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest - 78, // 164: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest - 80, // 165: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest - 82, // 166: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest - 84, // 167: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest - 86, // 168: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest - 88, // 169: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest - 90, // 170: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest - 92, // 171: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest - 119, // 172: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest - 121, // 173: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest - 94, // 174: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest - 96, // 175: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest - 54, // 176: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest - 56, // 177: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest - 14, // 178: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:input_type -> hyapp.room.v1.AdminGetRoomTreasureConfigRequest - 19, // 179: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest - 25, // 180: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest - 98, // 181: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest - 99, // 182: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest - 100, // 183: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest - 106, // 184: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest - 108, // 185: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest - 110, // 186: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest - 36, // 187: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest - 112, // 188: hyapp.room.v1.RoomQueryService.GetRoomTreasure:input_type -> hyapp.room.v1.GetRoomTreasureRequest - 114, // 189: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest - 117, // 190: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest - 41, // 191: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse - 43, // 192: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse - 35, // 193: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse - 39, // 194: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse - 46, // 195: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse - 48, // 196: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse - 50, // 197: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse - 52, // 198: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse - 59, // 199: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse - 61, // 200: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse - 17, // 201: hyapp.room.v1.RoomCommandService.AdminUpdateRoomTreasureConfig:output_type -> hyapp.room.v1.AdminUpdateRoomTreasureConfigResponse - 22, // 202: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse - 28, // 203: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse - 30, // 204: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse - 63, // 205: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse - 65, // 206: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse - 67, // 207: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse - 69, // 208: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse - 71, // 209: hyapp.room.v1.RoomCommandService.MicHeartbeat:output_type -> hyapp.room.v1.MicHeartbeatResponse - 73, // 210: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse - 75, // 211: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse - 77, // 212: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse - 79, // 213: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse - 81, // 214: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse - 83, // 215: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse - 85, // 216: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse - 87, // 217: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse - 89, // 218: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse - 91, // 219: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse - 93, // 220: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse - 120, // 221: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse - 122, // 222: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse - 95, // 223: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse - 97, // 224: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse - 55, // 225: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse - 57, // 226: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse - 15, // 227: hyapp.room.v1.RoomQueryService.AdminGetRoomTreasureConfig:output_type -> hyapp.room.v1.AdminGetRoomTreasureConfigResponse - 20, // 228: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse - 26, // 229: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse - 103, // 230: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse - 103, // 231: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse - 105, // 232: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse - 107, // 233: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse - 109, // 234: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse - 111, // 235: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse - 37, // 236: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse - 113, // 237: hyapp.room.v1.RoomQueryService.GetRoomTreasure:output_type -> hyapp.room.v1.GetRoomTreasureResponse - 115, // 238: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse - 118, // 239: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse - 191, // [191:240] is the sub-list for method output_type - 142, // [142:191] is the sub-list for method input_type - 142, // [142:142] is the sub-list for extension type_name - 142, // [142:142] is the sub-list for extension extendee - 0, // [0:142] is the sub-list for field type_name + 7, // 0: hyapp.room.v1.RoomRocketLevel.in_room_rewards:type_name -> hyapp.room.v1.RoomRocketRewardItem + 7, // 1: hyapp.room.v1.RoomRocketLevel.top1_rewards:type_name -> hyapp.room.v1.RoomRocketRewardItem + 7, // 2: hyapp.room.v1.RoomRocketLevel.igniter_rewards:type_name -> hyapp.room.v1.RoomRocketRewardItem + 9, // 3: hyapp.room.v1.RoomRocketState.last_rewards:type_name -> hyapp.room.v1.RoomRocketRewardGrant + 10, // 4: hyapp.room.v1.RoomRocketState.pending_launches:type_name -> hyapp.room.v1.RoomRocketPendingLaunch + 8, // 5: hyapp.room.v1.RoomRocketInfo.levels:type_name -> hyapp.room.v1.RoomRocketLevel + 11, // 6: hyapp.room.v1.RoomRocketInfo.state:type_name -> hyapp.room.v1.RoomRocketState + 8, // 7: hyapp.room.v1.AdminRoomRocketConfig.levels:type_name -> hyapp.room.v1.RoomRocketLevel + 13, // 8: hyapp.room.v1.AdminRoomRocketConfig.gift_fuel_rules:type_name -> hyapp.room.v1.RoomRocketGiftFuelRule + 0, // 9: hyapp.room.v1.AdminGetRoomRocketConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 14, // 10: hyapp.room.v1.AdminGetRoomRocketConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomRocketConfig + 0, // 11: hyapp.room.v1.AdminUpdateRoomRocketConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 14, // 12: hyapp.room.v1.AdminUpdateRoomRocketConfigRequest.config:type_name -> hyapp.room.v1.AdminRoomRocketConfig + 14, // 13: hyapp.room.v1.AdminUpdateRoomRocketConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomRocketConfig + 0, // 14: hyapp.room.v1.AdminGetRoomSeatConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 19, // 15: hyapp.room.v1.AdminGetRoomSeatConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomSeatConfig + 0, // 16: hyapp.room.v1.AdminUpdateRoomSeatConfigRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 19, // 17: hyapp.room.v1.AdminUpdateRoomSeatConfigResponse.config:type_name -> hyapp.room.v1.AdminRoomSeatConfig + 24, // 18: hyapp.room.v1.AdminRoomPin.room:type_name -> hyapp.room.v1.AdminRoomPinRoom + 0, // 19: hyapp.room.v1.AdminListRoomPinsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 25, // 20: hyapp.room.v1.AdminListRoomPinsResponse.pins:type_name -> hyapp.room.v1.AdminRoomPin + 0, // 21: hyapp.room.v1.AdminCreateRoomPinRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 25, // 22: hyapp.room.v1.AdminCreateRoomPinResponse.pin:type_name -> hyapp.room.v1.AdminRoomPin + 0, // 23: hyapp.room.v1.AdminCancelRoomPinRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 25, // 24: hyapp.room.v1.AdminCancelRoomPinResponse.pin:type_name -> hyapp.room.v1.AdminRoomPin + 4, // 25: hyapp.room.v1.RoomSnapshot.mic_seats:type_name -> hyapp.room.v1.SeatState + 2, // 26: hyapp.room.v1.RoomSnapshot.online_users:type_name -> hyapp.room.v1.RoomUser + 5, // 27: hyapp.room.v1.RoomSnapshot.gift_rank:type_name -> hyapp.room.v1.RankItem + 124, // 28: hyapp.room.v1.RoomSnapshot.room_ext:type_name -> hyapp.room.v1.RoomSnapshot.RoomExtEntry + 11, // 29: hyapp.room.v1.RoomSnapshot.rocket:type_name -> hyapp.room.v1.RoomRocketState + 32, // 30: hyapp.room.v1.RoomSnapshot.ban_states:type_name -> hyapp.room.v1.RoomBanState + 0, // 31: hyapp.room.v1.SaveRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 34, // 32: hyapp.room.v1.SaveRoomBackgroundResponse.background:type_name -> hyapp.room.v1.RoomBackgroundImage + 0, // 33: hyapp.room.v1.ListRoomBackgroundsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 34, // 34: hyapp.room.v1.ListRoomBackgroundsResponse.backgrounds:type_name -> hyapp.room.v1.RoomBackgroundImage + 0, // 35: hyapp.room.v1.SetRoomBackgroundRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 36: hyapp.room.v1.SetRoomBackgroundResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 37: hyapp.room.v1.SetRoomBackgroundResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 34, // 38: hyapp.room.v1.SetRoomBackgroundResponse.background:type_name -> hyapp.room.v1.RoomBackgroundImage + 0, // 39: hyapp.room.v1.CreateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 40: hyapp.room.v1.CreateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 41: hyapp.room.v1.CreateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 42: hyapp.room.v1.UpdateRoomProfileRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 43: hyapp.room.v1.UpdateRoomProfileResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 44: hyapp.room.v1.UpdateRoomProfileResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 45: hyapp.room.v1.JoinRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 45, // 46: hyapp.room.v1.JoinRoomRequest.entry_vehicle:type_name -> hyapp.room.v1.RoomEntryVehicleSnapshot + 1, // 47: hyapp.room.v1.JoinRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 2, // 48: hyapp.room.v1.JoinRoomResponse.user:type_name -> hyapp.room.v1.RoomUser + 33, // 49: hyapp.room.v1.JoinRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 50: hyapp.room.v1.RoomHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 51: hyapp.room.v1.RoomHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 2, // 52: hyapp.room.v1.RoomHeartbeatResponse.user:type_name -> hyapp.room.v1.RoomUser + 33, // 53: hyapp.room.v1.RoomHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 54: hyapp.room.v1.LeaveRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 55: hyapp.room.v1.LeaveRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 56: hyapp.room.v1.LeaveRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 57: hyapp.room.v1.CloseRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 58: hyapp.room.v1.CloseRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 59: hyapp.room.v1.CloseRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 60: hyapp.room.v1.AdminListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 54, // 61: hyapp.room.v1.AdminListRoomsResponse.rooms:type_name -> hyapp.room.v1.AdminRoomListItem + 0, // 62: hyapp.room.v1.AdminGetRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 54, // 63: hyapp.room.v1.AdminGetRoomResponse.room:type_name -> hyapp.room.v1.AdminRoomListItem + 0, // 64: hyapp.room.v1.AdminUpdateRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 65: hyapp.room.v1.AdminUpdateRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 66: hyapp.room.v1.AdminUpdateRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 67: hyapp.room.v1.AdminDeleteRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 68: hyapp.room.v1.AdminDeleteRoomResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 69: hyapp.room.v1.AdminDeleteRoomResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 70: hyapp.room.v1.MicUpRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 71: hyapp.room.v1.MicUpResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 72: hyapp.room.v1.MicUpResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 73: hyapp.room.v1.MicDownRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 74: hyapp.room.v1.MicDownResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 75: hyapp.room.v1.MicDownResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 76: hyapp.room.v1.ChangeMicSeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 77: hyapp.room.v1.ChangeMicSeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 78: hyapp.room.v1.ChangeMicSeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 79: hyapp.room.v1.ConfirmMicPublishingRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 80: hyapp.room.v1.ConfirmMicPublishingResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 81: hyapp.room.v1.ConfirmMicPublishingResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 82: hyapp.room.v1.MicHeartbeatRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 83: hyapp.room.v1.MicHeartbeatResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 84: hyapp.room.v1.MicHeartbeatResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 85: hyapp.room.v1.SetMicMuteRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 86: hyapp.room.v1.SetMicMuteResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 87: hyapp.room.v1.SetMicMuteResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 88: hyapp.room.v1.ApplyRTCEventRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 89: hyapp.room.v1.ApplyRTCEventResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 90: hyapp.room.v1.ApplyRTCEventResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 91: hyapp.room.v1.SetMicSeatLockRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 92: hyapp.room.v1.SetMicSeatLockResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 93: hyapp.room.v1.SetMicSeatLockResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 94: hyapp.room.v1.SetChatEnabledRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 95: hyapp.room.v1.SetChatEnabledResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 96: hyapp.room.v1.SetChatEnabledResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 97: hyapp.room.v1.SetRoomPasswordRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 98: hyapp.room.v1.SetRoomPasswordResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 99: hyapp.room.v1.SetRoomPasswordResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 100: hyapp.room.v1.SetRoomAdminRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 101: hyapp.room.v1.SetRoomAdminResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 102: hyapp.room.v1.SetRoomAdminResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 103: hyapp.room.v1.MuteUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 104: hyapp.room.v1.MuteUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 105: hyapp.room.v1.MuteUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 106: hyapp.room.v1.KickUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 107: hyapp.room.v1.KickUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 108: hyapp.room.v1.KickUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 109: hyapp.room.v1.UnbanUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 110: hyapp.room.v1.UnbanUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 111: hyapp.room.v1.UnbanUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 112: hyapp.room.v1.SystemEvictUserRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 113: hyapp.room.v1.SystemEvictUserResponse.result:type_name -> hyapp.room.v1.CommandResult + 33, // 114: hyapp.room.v1.SystemEvictUserResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 115: hyapp.room.v1.SendGiftRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 1, // 116: hyapp.room.v1.SendGiftResponse.result:type_name -> hyapp.room.v1.CommandResult + 5, // 117: hyapp.room.v1.SendGiftResponse.gift_rank:type_name -> hyapp.room.v1.RankItem + 33, // 118: hyapp.room.v1.SendGiftResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 11, // 119: hyapp.room.v1.SendGiftResponse.rocket:type_name -> hyapp.room.v1.RoomRocketState + 6, // 120: hyapp.room.v1.SendGiftResponse.lucky_gift:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 6, // 121: hyapp.room.v1.SendGiftResponse.lucky_gifts:type_name -> hyapp.room.v1.LuckyGiftDrawResult + 0, // 122: hyapp.room.v1.ListRoomsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 123: hyapp.room.v1.ListRoomFeedsRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 102, // 124: hyapp.room.v1.ListRoomFeedsRequest.related_users:type_name -> hyapp.room.v1.RoomFeedRelatedUser + 0, // 125: hyapp.room.v1.ListRoomGiftLeaderboardRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 103, // 126: hyapp.room.v1.ListRoomsResponse.rooms:type_name -> hyapp.room.v1.RoomListItem + 103, // 127: hyapp.room.v1.RoomGiftLeaderboardItem.room:type_name -> hyapp.room.v1.RoomListItem + 105, // 128: hyapp.room.v1.ListRoomGiftLeaderboardResponse.items:type_name -> hyapp.room.v1.RoomGiftLeaderboardItem + 0, // 129: hyapp.room.v1.GetMyRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 103, // 130: hyapp.room.v1.GetMyRoomResponse.room:type_name -> hyapp.room.v1.RoomListItem + 0, // 131: hyapp.room.v1.GetCurrentRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 132: hyapp.room.v1.GetRoomSnapshotRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 33, // 133: hyapp.room.v1.GetRoomSnapshotResponse.room:type_name -> hyapp.room.v1.RoomSnapshot + 0, // 134: hyapp.room.v1.GetRoomRocketRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 12, // 135: hyapp.room.v1.GetRoomRocketResponse.rocket:type_name -> hyapp.room.v1.RoomRocketInfo + 0, // 136: hyapp.room.v1.ListRoomOnlineUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 2, // 137: hyapp.room.v1.ListRoomOnlineUsersResponse.users:type_name -> hyapp.room.v1.RoomUser + 3, // 138: hyapp.room.v1.ListRoomOnlineUsersResponse.items:type_name -> hyapp.room.v1.RoomOnlineUser + 0, // 139: hyapp.room.v1.ListRoomBannedUsersRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 117, // 140: hyapp.room.v1.ListRoomBannedUsersResponse.items:type_name -> hyapp.room.v1.RoomBannedUser + 0, // 141: hyapp.room.v1.FollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 0, // 142: hyapp.room.v1.UnfollowRoomRequest.meta:type_name -> hyapp.room.v1.RequestMeta + 41, // 143: hyapp.room.v1.RoomCommandService.CreateRoom:input_type -> hyapp.room.v1.CreateRoomRequest + 43, // 144: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:input_type -> hyapp.room.v1.UpdateRoomProfileRequest + 35, // 145: hyapp.room.v1.RoomCommandService.SaveRoomBackground:input_type -> hyapp.room.v1.SaveRoomBackgroundRequest + 39, // 146: hyapp.room.v1.RoomCommandService.SetRoomBackground:input_type -> hyapp.room.v1.SetRoomBackgroundRequest + 46, // 147: hyapp.room.v1.RoomCommandService.JoinRoom:input_type -> hyapp.room.v1.JoinRoomRequest + 48, // 148: hyapp.room.v1.RoomCommandService.RoomHeartbeat:input_type -> hyapp.room.v1.RoomHeartbeatRequest + 50, // 149: hyapp.room.v1.RoomCommandService.LeaveRoom:input_type -> hyapp.room.v1.LeaveRoomRequest + 52, // 150: hyapp.room.v1.RoomCommandService.CloseRoom:input_type -> hyapp.room.v1.CloseRoomRequest + 59, // 151: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:input_type -> hyapp.room.v1.AdminUpdateRoomRequest + 61, // 152: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:input_type -> hyapp.room.v1.AdminDeleteRoomRequest + 17, // 153: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:input_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigRequest + 22, // 154: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:input_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigRequest + 28, // 155: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:input_type -> hyapp.room.v1.AdminCreateRoomPinRequest + 30, // 156: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:input_type -> hyapp.room.v1.AdminCancelRoomPinRequest + 63, // 157: hyapp.room.v1.RoomCommandService.MicUp:input_type -> hyapp.room.v1.MicUpRequest + 65, // 158: hyapp.room.v1.RoomCommandService.MicDown:input_type -> hyapp.room.v1.MicDownRequest + 67, // 159: hyapp.room.v1.RoomCommandService.ChangeMicSeat:input_type -> hyapp.room.v1.ChangeMicSeatRequest + 69, // 160: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:input_type -> hyapp.room.v1.ConfirmMicPublishingRequest + 71, // 161: hyapp.room.v1.RoomCommandService.MicHeartbeat:input_type -> hyapp.room.v1.MicHeartbeatRequest + 73, // 162: hyapp.room.v1.RoomCommandService.SetMicMute:input_type -> hyapp.room.v1.SetMicMuteRequest + 75, // 163: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:input_type -> hyapp.room.v1.ApplyRTCEventRequest + 77, // 164: hyapp.room.v1.RoomCommandService.SetMicSeatLock:input_type -> hyapp.room.v1.SetMicSeatLockRequest + 79, // 165: hyapp.room.v1.RoomCommandService.SetChatEnabled:input_type -> hyapp.room.v1.SetChatEnabledRequest + 81, // 166: hyapp.room.v1.RoomCommandService.SetRoomPassword:input_type -> hyapp.room.v1.SetRoomPasswordRequest + 83, // 167: hyapp.room.v1.RoomCommandService.SetRoomAdmin:input_type -> hyapp.room.v1.SetRoomAdminRequest + 85, // 168: hyapp.room.v1.RoomCommandService.MuteUser:input_type -> hyapp.room.v1.MuteUserRequest + 87, // 169: hyapp.room.v1.RoomCommandService.KickUser:input_type -> hyapp.room.v1.KickUserRequest + 89, // 170: hyapp.room.v1.RoomCommandService.UnbanUser:input_type -> hyapp.room.v1.UnbanUserRequest + 91, // 171: hyapp.room.v1.RoomCommandService.SystemEvictUser:input_type -> hyapp.room.v1.SystemEvictUserRequest + 93, // 172: hyapp.room.v1.RoomCommandService.SendGift:input_type -> hyapp.room.v1.SendGiftRequest + 120, // 173: hyapp.room.v1.RoomCommandService.FollowRoom:input_type -> hyapp.room.v1.FollowRoomRequest + 122, // 174: hyapp.room.v1.RoomCommandService.UnfollowRoom:input_type -> hyapp.room.v1.UnfollowRoomRequest + 95, // 175: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:input_type -> hyapp.room.v1.CheckSpeakPermissionRequest + 97, // 176: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:input_type -> hyapp.room.v1.VerifyRoomPresenceRequest + 55, // 177: hyapp.room.v1.RoomQueryService.AdminListRooms:input_type -> hyapp.room.v1.AdminListRoomsRequest + 57, // 178: hyapp.room.v1.RoomQueryService.AdminGetRoom:input_type -> hyapp.room.v1.AdminGetRoomRequest + 15, // 179: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:input_type -> hyapp.room.v1.AdminGetRoomRocketConfigRequest + 20, // 180: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:input_type -> hyapp.room.v1.AdminGetRoomSeatConfigRequest + 26, // 181: hyapp.room.v1.RoomQueryService.AdminListRoomPins:input_type -> hyapp.room.v1.AdminListRoomPinsRequest + 99, // 182: hyapp.room.v1.RoomQueryService.ListRooms:input_type -> hyapp.room.v1.ListRoomsRequest + 100, // 183: hyapp.room.v1.RoomQueryService.ListRoomFeeds:input_type -> hyapp.room.v1.ListRoomFeedsRequest + 101, // 184: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:input_type -> hyapp.room.v1.ListRoomGiftLeaderboardRequest + 107, // 185: hyapp.room.v1.RoomQueryService.GetMyRoom:input_type -> hyapp.room.v1.GetMyRoomRequest + 109, // 186: hyapp.room.v1.RoomQueryService.GetCurrentRoom:input_type -> hyapp.room.v1.GetCurrentRoomRequest + 111, // 187: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:input_type -> hyapp.room.v1.GetRoomSnapshotRequest + 37, // 188: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:input_type -> hyapp.room.v1.ListRoomBackgroundsRequest + 113, // 189: hyapp.room.v1.RoomQueryService.GetRoomRocket:input_type -> hyapp.room.v1.GetRoomRocketRequest + 115, // 190: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:input_type -> hyapp.room.v1.ListRoomOnlineUsersRequest + 118, // 191: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:input_type -> hyapp.room.v1.ListRoomBannedUsersRequest + 42, // 192: hyapp.room.v1.RoomCommandService.CreateRoom:output_type -> hyapp.room.v1.CreateRoomResponse + 44, // 193: hyapp.room.v1.RoomCommandService.UpdateRoomProfile:output_type -> hyapp.room.v1.UpdateRoomProfileResponse + 36, // 194: hyapp.room.v1.RoomCommandService.SaveRoomBackground:output_type -> hyapp.room.v1.SaveRoomBackgroundResponse + 40, // 195: hyapp.room.v1.RoomCommandService.SetRoomBackground:output_type -> hyapp.room.v1.SetRoomBackgroundResponse + 47, // 196: hyapp.room.v1.RoomCommandService.JoinRoom:output_type -> hyapp.room.v1.JoinRoomResponse + 49, // 197: hyapp.room.v1.RoomCommandService.RoomHeartbeat:output_type -> hyapp.room.v1.RoomHeartbeatResponse + 51, // 198: hyapp.room.v1.RoomCommandService.LeaveRoom:output_type -> hyapp.room.v1.LeaveRoomResponse + 53, // 199: hyapp.room.v1.RoomCommandService.CloseRoom:output_type -> hyapp.room.v1.CloseRoomResponse + 60, // 200: hyapp.room.v1.RoomCommandService.AdminUpdateRoom:output_type -> hyapp.room.v1.AdminUpdateRoomResponse + 62, // 201: hyapp.room.v1.RoomCommandService.AdminDeleteRoom:output_type -> hyapp.room.v1.AdminDeleteRoomResponse + 18, // 202: hyapp.room.v1.RoomCommandService.AdminUpdateRoomRocketConfig:output_type -> hyapp.room.v1.AdminUpdateRoomRocketConfigResponse + 23, // 203: hyapp.room.v1.RoomCommandService.AdminUpdateRoomSeatConfig:output_type -> hyapp.room.v1.AdminUpdateRoomSeatConfigResponse + 29, // 204: hyapp.room.v1.RoomCommandService.AdminCreateRoomPin:output_type -> hyapp.room.v1.AdminCreateRoomPinResponse + 31, // 205: hyapp.room.v1.RoomCommandService.AdminCancelRoomPin:output_type -> hyapp.room.v1.AdminCancelRoomPinResponse + 64, // 206: hyapp.room.v1.RoomCommandService.MicUp:output_type -> hyapp.room.v1.MicUpResponse + 66, // 207: hyapp.room.v1.RoomCommandService.MicDown:output_type -> hyapp.room.v1.MicDownResponse + 68, // 208: hyapp.room.v1.RoomCommandService.ChangeMicSeat:output_type -> hyapp.room.v1.ChangeMicSeatResponse + 70, // 209: hyapp.room.v1.RoomCommandService.ConfirmMicPublishing:output_type -> hyapp.room.v1.ConfirmMicPublishingResponse + 72, // 210: hyapp.room.v1.RoomCommandService.MicHeartbeat:output_type -> hyapp.room.v1.MicHeartbeatResponse + 74, // 211: hyapp.room.v1.RoomCommandService.SetMicMute:output_type -> hyapp.room.v1.SetMicMuteResponse + 76, // 212: hyapp.room.v1.RoomCommandService.ApplyRTCEvent:output_type -> hyapp.room.v1.ApplyRTCEventResponse + 78, // 213: hyapp.room.v1.RoomCommandService.SetMicSeatLock:output_type -> hyapp.room.v1.SetMicSeatLockResponse + 80, // 214: hyapp.room.v1.RoomCommandService.SetChatEnabled:output_type -> hyapp.room.v1.SetChatEnabledResponse + 82, // 215: hyapp.room.v1.RoomCommandService.SetRoomPassword:output_type -> hyapp.room.v1.SetRoomPasswordResponse + 84, // 216: hyapp.room.v1.RoomCommandService.SetRoomAdmin:output_type -> hyapp.room.v1.SetRoomAdminResponse + 86, // 217: hyapp.room.v1.RoomCommandService.MuteUser:output_type -> hyapp.room.v1.MuteUserResponse + 88, // 218: hyapp.room.v1.RoomCommandService.KickUser:output_type -> hyapp.room.v1.KickUserResponse + 90, // 219: hyapp.room.v1.RoomCommandService.UnbanUser:output_type -> hyapp.room.v1.UnbanUserResponse + 92, // 220: hyapp.room.v1.RoomCommandService.SystemEvictUser:output_type -> hyapp.room.v1.SystemEvictUserResponse + 94, // 221: hyapp.room.v1.RoomCommandService.SendGift:output_type -> hyapp.room.v1.SendGiftResponse + 121, // 222: hyapp.room.v1.RoomCommandService.FollowRoom:output_type -> hyapp.room.v1.FollowRoomResponse + 123, // 223: hyapp.room.v1.RoomCommandService.UnfollowRoom:output_type -> hyapp.room.v1.UnfollowRoomResponse + 96, // 224: hyapp.room.v1.RoomGuardService.CheckSpeakPermission:output_type -> hyapp.room.v1.CheckSpeakPermissionResponse + 98, // 225: hyapp.room.v1.RoomGuardService.VerifyRoomPresence:output_type -> hyapp.room.v1.VerifyRoomPresenceResponse + 56, // 226: hyapp.room.v1.RoomQueryService.AdminListRooms:output_type -> hyapp.room.v1.AdminListRoomsResponse + 58, // 227: hyapp.room.v1.RoomQueryService.AdminGetRoom:output_type -> hyapp.room.v1.AdminGetRoomResponse + 16, // 228: hyapp.room.v1.RoomQueryService.AdminGetRoomRocketConfig:output_type -> hyapp.room.v1.AdminGetRoomRocketConfigResponse + 21, // 229: hyapp.room.v1.RoomQueryService.AdminGetRoomSeatConfig:output_type -> hyapp.room.v1.AdminGetRoomSeatConfigResponse + 27, // 230: hyapp.room.v1.RoomQueryService.AdminListRoomPins:output_type -> hyapp.room.v1.AdminListRoomPinsResponse + 104, // 231: hyapp.room.v1.RoomQueryService.ListRooms:output_type -> hyapp.room.v1.ListRoomsResponse + 104, // 232: hyapp.room.v1.RoomQueryService.ListRoomFeeds:output_type -> hyapp.room.v1.ListRoomsResponse + 106, // 233: hyapp.room.v1.RoomQueryService.ListRoomGiftLeaderboard:output_type -> hyapp.room.v1.ListRoomGiftLeaderboardResponse + 108, // 234: hyapp.room.v1.RoomQueryService.GetMyRoom:output_type -> hyapp.room.v1.GetMyRoomResponse + 110, // 235: hyapp.room.v1.RoomQueryService.GetCurrentRoom:output_type -> hyapp.room.v1.GetCurrentRoomResponse + 112, // 236: hyapp.room.v1.RoomQueryService.GetRoomSnapshot:output_type -> hyapp.room.v1.GetRoomSnapshotResponse + 38, // 237: hyapp.room.v1.RoomQueryService.ListRoomBackgrounds:output_type -> hyapp.room.v1.ListRoomBackgroundsResponse + 114, // 238: hyapp.room.v1.RoomQueryService.GetRoomRocket:output_type -> hyapp.room.v1.GetRoomRocketResponse + 116, // 239: hyapp.room.v1.RoomQueryService.ListRoomOnlineUsers:output_type -> hyapp.room.v1.ListRoomOnlineUsersResponse + 119, // 240: hyapp.room.v1.RoomQueryService.ListRoomBannedUsers:output_type -> hyapp.room.v1.ListRoomBannedUsersResponse + 192, // [192:241] is the sub-list for method output_type + 143, // [143:192] is the sub-list for method input_type + 143, // [143:143] is the sub-list for extension type_name + 143, // [143:143] is the sub-list for extension extendee + 0, // [0:143] is the sub-list for field type_name } func init() { file_proto_room_v1_room_proto_init() } @@ -10339,15 +10482,15 @@ func file_proto_room_v1_room_proto_init() { if File_proto_room_v1_room_proto != nil { return } - file_proto_room_v1_room_proto_msgTypes[42].OneofWrappers = []any{} - file_proto_room_v1_room_proto_msgTypes[58].OneofWrappers = []any{} + file_proto_room_v1_room_proto_msgTypes[43].OneofWrappers = []any{} + file_proto_room_v1_room_proto_msgTypes[59].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_room_v1_room_proto_rawDesc), len(file_proto_room_v1_room_proto_rawDesc)), NumEnums: 0, - NumMessages: 124, + NumMessages: 125, NumExtensions: 0, NumServices: 3, }, diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index c5ee3ad0..829764f2 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -102,8 +102,8 @@ message LuckyGiftDrawResult { int64 target_user_id = 20; } -// RoomTreasureRewardItem 是后台配置给客户端展示的宝箱奖励候选项。 -message RoomTreasureRewardItem { +// RoomRocketRewardItem 是后台配置给客户端展示的火箭奖励候选项。 +message RoomRocketRewardItem { string reward_item_id = 1; int64 resource_group_id = 2; int64 weight = 3; @@ -111,21 +111,21 @@ message RoomTreasureRewardItem { string icon_url = 5; } -// RoomTreasureLevel 暴露单个等级宝箱的物料、阈值和三类奖励池。 -message RoomTreasureLevel { +// RoomRocketLevel 暴露单个等级火箭的物料、阈值和三类奖励池。 +message RoomRocketLevel { int32 level = 1; - int64 energy_threshold = 2; + int64 fuel_threshold = 2; string cover_url = 3; string animation_url = 4; - string opening_animation_url = 5; - string opened_image_url = 6; - repeated RoomTreasureRewardItem in_room_rewards = 7; - repeated RoomTreasureRewardItem top1_rewards = 8; - repeated RoomTreasureRewardItem igniter_rewards = 9; + string launch_animation_url = 5; + string launched_image_url = 6; + repeated RoomRocketRewardItem in_room_rewards = 7; + repeated RoomRocketRewardItem top1_rewards = 8; + repeated RoomRocketRewardItem igniter_rewards = 9; } -// RoomTreasureRewardGrant 是一次宝箱打开后给某个用户结算出的具体奖励。 -message RoomTreasureRewardGrant { +// RoomRocketRewardGrant 是一次火箭打开后给某个用户结算出的具体奖励。 +message RoomRocketRewardGrant { string reward_role = 1; int64 user_id = 2; string reward_item_id = 3; @@ -136,80 +136,95 @@ message RoomTreasureRewardGrant { string status = 8; } -// RoomTreasureState 是 Room Cell 持有并随快照恢复的当前宝箱状态。 -message RoomTreasureState { +// RoomRocketPendingLaunch 是已经点火、等待延迟发射的单枚火箭。 +message RoomRocketPendingLaunch { + string rocket_id = 1; + int32 level = 2; + int64 fuel_threshold = 3; + int64 ignited_at_ms = 4; + int64 launch_at_ms = 5; + int64 reset_at_ms = 6; + int64 top1_user_id = 7; + int64 igniter_user_id = 8; + int64 config_version = 9; + string cover_url = 10; +} + +// RoomRocketState 是 Room Cell 持有并随快照恢复的当前火箭状态。 +message RoomRocketState { int32 current_level = 1; - int64 current_progress = 2; - int64 energy_threshold = 3; + int64 current_fuel = 2; + int64 fuel_threshold = 3; string status = 4; - int64 countdown_started_at_ms = 5; - int64 open_at_ms = 6; - int64 opened_at_ms = 7; + int64 ignited_at_ms = 5; + int64 launch_at_ms = 6; + int64 launched_at_ms = 7; int64 reset_at_ms = 8; int64 top1_user_id = 9; int64 igniter_user_id = 10; - string box_id = 11; + string rocket_id = 11; int64 config_version = 12; - repeated RoomTreasureRewardGrant last_rewards = 13; + repeated RoomRocketRewardGrant last_rewards = 13; + repeated RoomRocketPendingLaunch pending_launches = 14; } -// RoomTreasureInfo 是 App 初始化宝箱 UI 的完整读模型。 -message RoomTreasureInfo { +// RoomRocketInfo 是 App 初始化火箭 UI 的完整读模型。 +message RoomRocketInfo { bool enabled = 1; - repeated RoomTreasureLevel levels = 2; - RoomTreasureState state = 3; + repeated RoomRocketLevel levels = 2; + RoomRocketState state = 3; int64 server_time_ms = 4; string broadcast_scope = 5; - int64 open_delay_ms = 6; + int64 launch_delay_ms = 6; int64 broadcast_delay_ms = 7; string reward_stack_policy = 8; } -// RoomTreasureGiftEnergyRule 是后台配置的礼物能量覆盖规则。 -message RoomTreasureGiftEnergyRule { +// RoomRocketGiftFuelRule 是后台配置的礼物燃料覆盖规则。 +message RoomRocketGiftFuelRule { string rule_id = 1; string gift_id = 2; string gift_type_code = 3; int64 multiplier_ppm = 4; - int64 fixed_energy = 5; + int64 fixed_fuel = 5; bool excluded = 6; } -// AdminRoomTreasureConfig 是后台管理读写的完整宝箱配置。 -message AdminRoomTreasureConfig { +// AdminRoomRocketConfig 是后台管理读写的完整火箭配置。 +message AdminRoomRocketConfig { string app_code = 1; bool enabled = 2; int64 config_version = 3; - string energy_source = 4; - int64 open_delay_ms = 5; + string fuel_source = 4; + int64 launch_delay_ms = 5; bool broadcast_enabled = 6; string broadcast_scope = 7; int64 broadcast_delay_ms = 8; string reward_stack_policy = 9; - repeated RoomTreasureLevel levels = 10; - repeated RoomTreasureGiftEnergyRule gift_energy_rules = 11; + repeated RoomRocketLevel levels = 10; + repeated RoomRocketGiftFuelRule gift_fuel_rules = 11; int64 updated_by_admin_id = 12; int64 created_at_ms = 13; int64 updated_at_ms = 14; } -message AdminGetRoomTreasureConfigRequest { +message AdminGetRoomRocketConfigRequest { RequestMeta meta = 1; } -message AdminGetRoomTreasureConfigResponse { - AdminRoomTreasureConfig config = 1; +message AdminGetRoomRocketConfigResponse { + AdminRoomRocketConfig config = 1; int64 server_time_ms = 2; } -message AdminUpdateRoomTreasureConfigRequest { +message AdminUpdateRoomRocketConfigRequest { RequestMeta meta = 1; - AdminRoomTreasureConfig config = 2; + AdminRoomRocketConfig config = 2; int64 admin_id = 3; } -message AdminUpdateRoomTreasureConfigResponse { - AdminRoomTreasureConfig config = 1; +message AdminUpdateRoomRocketConfigResponse { + AdminRoomRocketConfig config = 1; int64 server_time_ms = 2; } @@ -335,8 +350,8 @@ message RoomSnapshot { int64 visible_region_id = 18; // locked 只表达房间是否需要入房密码;具体密码哈希不对外映射到 HTTP JSON。 bool locked = 19; - // treasure 是语音房宝箱当前状态;配置物料通过 GetRoomTreasure 单独读取,避免快照过大。 - RoomTreasureState treasure = 20; + // rocket 是语音房火箭当前状态;配置物料通过 GetRoomRocket 单独读取,避免快照过大。 + RoomRocketState rocket = 20; // ban_states 保存 ban 的过期边界;ban_user_ids 仍只服务简单集合判断。 repeated RoomBanState ban_states = 21; } @@ -829,7 +844,7 @@ message SendGiftResponse { int64 room_heat = 3; repeated RankItem gift_rank = 4; RoomSnapshot room = 5; - RoomTreasureState treasure = 6; + RoomRocketState rocket = 6; // lucky_gift 是本次送礼的聚合幸运礼物结果;多目标时倍率和返奖金额按所有目标累加。 LuckyGiftDrawResult lucky_gift = 7; // lucky_gifts 是每个收礼目标的独立抽奖结果;多目标客户端用 target_user_id 对齐明细表现。 @@ -1000,16 +1015,16 @@ message GetRoomSnapshotResponse { bool is_followed = 3; } -// GetRoomTreasureRequest 主动读取当前房间宝箱配置物料和进度状态。 +// GetRoomRocketRequest 主动读取当前房间火箭配置物料和进度状态。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 -message GetRoomTreasureRequest { +message GetRoomRocketRequest { RequestMeta meta = 1; string room_id = 2; int64 viewer_user_id = 3; } -message GetRoomTreasureResponse { - RoomTreasureInfo treasure = 1; +message GetRoomRocketResponse { + RoomRocketInfo rocket = 1; int64 server_time_ms = 2; } @@ -1100,7 +1115,7 @@ service RoomCommandService { rpc CloseRoom(CloseRoomRequest) returns (CloseRoomResponse); rpc AdminUpdateRoom(AdminUpdateRoomRequest) returns (AdminUpdateRoomResponse); rpc AdminDeleteRoom(AdminDeleteRoomRequest) returns (AdminDeleteRoomResponse); - rpc AdminUpdateRoomTreasureConfig(AdminUpdateRoomTreasureConfigRequest) returns (AdminUpdateRoomTreasureConfigResponse); + rpc AdminUpdateRoomRocketConfig(AdminUpdateRoomRocketConfigRequest) returns (AdminUpdateRoomRocketConfigResponse); rpc AdminUpdateRoomSeatConfig(AdminUpdateRoomSeatConfigRequest) returns (AdminUpdateRoomSeatConfigResponse); rpc AdminCreateRoomPin(AdminCreateRoomPinRequest) returns (AdminCreateRoomPinResponse); rpc AdminCancelRoomPin(AdminCancelRoomPinRequest) returns (AdminCancelRoomPinResponse); @@ -1134,7 +1149,7 @@ service RoomGuardService { service RoomQueryService { rpc AdminListRooms(AdminListRoomsRequest) returns (AdminListRoomsResponse); rpc AdminGetRoom(AdminGetRoomRequest) returns (AdminGetRoomResponse); - rpc AdminGetRoomTreasureConfig(AdminGetRoomTreasureConfigRequest) returns (AdminGetRoomTreasureConfigResponse); + rpc AdminGetRoomRocketConfig(AdminGetRoomRocketConfigRequest) returns (AdminGetRoomRocketConfigResponse); rpc AdminGetRoomSeatConfig(AdminGetRoomSeatConfigRequest) returns (AdminGetRoomSeatConfigResponse); rpc AdminListRoomPins(AdminListRoomPinsRequest) returns (AdminListRoomPinsResponse); rpc ListRooms(ListRoomsRequest) returns (ListRoomsResponse); @@ -1144,7 +1159,7 @@ service RoomQueryService { rpc GetCurrentRoom(GetCurrentRoomRequest) returns (GetCurrentRoomResponse); rpc GetRoomSnapshot(GetRoomSnapshotRequest) returns (GetRoomSnapshotResponse); rpc ListRoomBackgrounds(ListRoomBackgroundsRequest) returns (ListRoomBackgroundsResponse); - rpc GetRoomTreasure(GetRoomTreasureRequest) returns (GetRoomTreasureResponse); + rpc GetRoomRocket(GetRoomRocketRequest) returns (GetRoomRocketResponse); rpc ListRoomOnlineUsers(ListRoomOnlineUsersRequest) returns (ListRoomOnlineUsersResponse); rpc ListRoomBannedUsers(ListRoomBannedUsersRequest) returns (ListRoomBannedUsersResponse); } diff --git a/api/proto/room/v1/room_grpc.pb.go b/api/proto/room/v1/room_grpc.pb.go index 0f0a7068..03a9df6a 100644 --- a/api/proto/room/v1/room_grpc.pb.go +++ b/api/proto/room/v1/room_grpc.pb.go @@ -19,38 +19,38 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - RoomCommandService_CreateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CreateRoom" - RoomCommandService_UpdateRoomProfile_FullMethodName = "/hyapp.room.v1.RoomCommandService/UpdateRoomProfile" - RoomCommandService_SaveRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SaveRoomBackground" - RoomCommandService_SetRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomBackground" - RoomCommandService_JoinRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/JoinRoom" - RoomCommandService_RoomHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/RoomHeartbeat" - RoomCommandService_LeaveRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/LeaveRoom" - RoomCommandService_CloseRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CloseRoom" - RoomCommandService_AdminUpdateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoom" - RoomCommandService_AdminDeleteRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminDeleteRoom" - RoomCommandService_AdminUpdateRoomTreasureConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomTreasureConfig" - RoomCommandService_AdminUpdateRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomSeatConfig" - RoomCommandService_AdminCreateRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRoomPin" - RoomCommandService_AdminCancelRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCancelRoomPin" - RoomCommandService_MicUp_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicUp" - RoomCommandService_MicDown_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicDown" - RoomCommandService_ChangeMicSeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/ChangeMicSeat" - RoomCommandService_ConfirmMicPublishing_FullMethodName = "/hyapp.room.v1.RoomCommandService/ConfirmMicPublishing" - RoomCommandService_MicHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicHeartbeat" - RoomCommandService_SetMicMute_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicMute" - RoomCommandService_ApplyRTCEvent_FullMethodName = "/hyapp.room.v1.RoomCommandService/ApplyRTCEvent" - RoomCommandService_SetMicSeatLock_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicSeatLock" - RoomCommandService_SetChatEnabled_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetChatEnabled" - RoomCommandService_SetRoomPassword_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomPassword" - RoomCommandService_SetRoomAdmin_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomAdmin" - RoomCommandService_MuteUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/MuteUser" - RoomCommandService_KickUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/KickUser" - RoomCommandService_UnbanUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnbanUser" - RoomCommandService_SystemEvictUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/SystemEvictUser" - RoomCommandService_SendGift_FullMethodName = "/hyapp.room.v1.RoomCommandService/SendGift" - RoomCommandService_FollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/FollowRoom" - RoomCommandService_UnfollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnfollowRoom" + RoomCommandService_CreateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CreateRoom" + RoomCommandService_UpdateRoomProfile_FullMethodName = "/hyapp.room.v1.RoomCommandService/UpdateRoomProfile" + RoomCommandService_SaveRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SaveRoomBackground" + RoomCommandService_SetRoomBackground_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomBackground" + RoomCommandService_JoinRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/JoinRoom" + RoomCommandService_RoomHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/RoomHeartbeat" + RoomCommandService_LeaveRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/LeaveRoom" + RoomCommandService_CloseRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/CloseRoom" + RoomCommandService_AdminUpdateRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoom" + RoomCommandService_AdminDeleteRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminDeleteRoom" + RoomCommandService_AdminUpdateRoomRocketConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomRocketConfig" + RoomCommandService_AdminUpdateRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminUpdateRoomSeatConfig" + RoomCommandService_AdminCreateRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCreateRoomPin" + RoomCommandService_AdminCancelRoomPin_FullMethodName = "/hyapp.room.v1.RoomCommandService/AdminCancelRoomPin" + RoomCommandService_MicUp_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicUp" + RoomCommandService_MicDown_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicDown" + RoomCommandService_ChangeMicSeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/ChangeMicSeat" + RoomCommandService_ConfirmMicPublishing_FullMethodName = "/hyapp.room.v1.RoomCommandService/ConfirmMicPublishing" + RoomCommandService_MicHeartbeat_FullMethodName = "/hyapp.room.v1.RoomCommandService/MicHeartbeat" + RoomCommandService_SetMicMute_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicMute" + RoomCommandService_ApplyRTCEvent_FullMethodName = "/hyapp.room.v1.RoomCommandService/ApplyRTCEvent" + RoomCommandService_SetMicSeatLock_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetMicSeatLock" + RoomCommandService_SetChatEnabled_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetChatEnabled" + RoomCommandService_SetRoomPassword_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomPassword" + RoomCommandService_SetRoomAdmin_FullMethodName = "/hyapp.room.v1.RoomCommandService/SetRoomAdmin" + RoomCommandService_MuteUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/MuteUser" + RoomCommandService_KickUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/KickUser" + RoomCommandService_UnbanUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnbanUser" + RoomCommandService_SystemEvictUser_FullMethodName = "/hyapp.room.v1.RoomCommandService/SystemEvictUser" + RoomCommandService_SendGift_FullMethodName = "/hyapp.room.v1.RoomCommandService/SendGift" + RoomCommandService_FollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/FollowRoom" + RoomCommandService_UnfollowRoom_FullMethodName = "/hyapp.room.v1.RoomCommandService/UnfollowRoom" ) // RoomCommandServiceClient is the client API for RoomCommandService service. @@ -69,7 +69,7 @@ type RoomCommandServiceClient interface { CloseRoom(ctx context.Context, in *CloseRoomRequest, opts ...grpc.CallOption) (*CloseRoomResponse, error) AdminUpdateRoom(ctx context.Context, in *AdminUpdateRoomRequest, opts ...grpc.CallOption) (*AdminUpdateRoomResponse, error) AdminDeleteRoom(ctx context.Context, in *AdminDeleteRoomRequest, opts ...grpc.CallOption) (*AdminDeleteRoomResponse, error) - AdminUpdateRoomTreasureConfig(ctx context.Context, in *AdminUpdateRoomTreasureConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomTreasureConfigResponse, error) + AdminUpdateRoomRocketConfig(ctx context.Context, in *AdminUpdateRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomRocketConfigResponse, error) AdminUpdateRoomSeatConfig(ctx context.Context, in *AdminUpdateRoomSeatConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomSeatConfigResponse, error) AdminCreateRoomPin(ctx context.Context, in *AdminCreateRoomPinRequest, opts ...grpc.CallOption) (*AdminCreateRoomPinResponse, error) AdminCancelRoomPin(ctx context.Context, in *AdminCancelRoomPinRequest, opts ...grpc.CallOption) (*AdminCancelRoomPinResponse, error) @@ -201,10 +201,10 @@ func (c *roomCommandServiceClient) AdminDeleteRoom(ctx context.Context, in *Admi return out, nil } -func (c *roomCommandServiceClient) AdminUpdateRoomTreasureConfig(ctx context.Context, in *AdminUpdateRoomTreasureConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomTreasureConfigResponse, error) { +func (c *roomCommandServiceClient) AdminUpdateRoomRocketConfig(ctx context.Context, in *AdminUpdateRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminUpdateRoomRocketConfigResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(AdminUpdateRoomTreasureConfigResponse) - err := c.cc.Invoke(ctx, RoomCommandService_AdminUpdateRoomTreasureConfig_FullMethodName, in, out, cOpts...) + out := new(AdminUpdateRoomRocketConfigResponse) + err := c.cc.Invoke(ctx, RoomCommandService_AdminUpdateRoomRocketConfig_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -437,7 +437,7 @@ type RoomCommandServiceServer interface { CloseRoom(context.Context, *CloseRoomRequest) (*CloseRoomResponse, error) AdminUpdateRoom(context.Context, *AdminUpdateRoomRequest) (*AdminUpdateRoomResponse, error) AdminDeleteRoom(context.Context, *AdminDeleteRoomRequest) (*AdminDeleteRoomResponse, error) - AdminUpdateRoomTreasureConfig(context.Context, *AdminUpdateRoomTreasureConfigRequest) (*AdminUpdateRoomTreasureConfigResponse, error) + AdminUpdateRoomRocketConfig(context.Context, *AdminUpdateRoomRocketConfigRequest) (*AdminUpdateRoomRocketConfigResponse, error) AdminUpdateRoomSeatConfig(context.Context, *AdminUpdateRoomSeatConfigRequest) (*AdminUpdateRoomSeatConfigResponse, error) AdminCreateRoomPin(context.Context, *AdminCreateRoomPinRequest) (*AdminCreateRoomPinResponse, error) AdminCancelRoomPin(context.Context, *AdminCancelRoomPinRequest) (*AdminCancelRoomPinResponse, error) @@ -499,8 +499,8 @@ func (UnimplementedRoomCommandServiceServer) AdminUpdateRoom(context.Context, *A func (UnimplementedRoomCommandServiceServer) AdminDeleteRoom(context.Context, *AdminDeleteRoomRequest) (*AdminDeleteRoomResponse, error) { return nil, status.Error(codes.Unimplemented, "method AdminDeleteRoom not implemented") } -func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomTreasureConfig(context.Context, *AdminUpdateRoomTreasureConfigRequest) (*AdminUpdateRoomTreasureConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomTreasureConfig not implemented") +func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomRocketConfig(context.Context, *AdminUpdateRoomRocketConfigRequest) (*AdminUpdateRoomRocketConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomRocketConfig not implemented") } func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomSeatConfig(context.Context, *AdminUpdateRoomSeatConfigRequest) (*AdminUpdateRoomSeatConfigResponse, error) { return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomSeatConfig not implemented") @@ -766,20 +766,20 @@ func _RoomCommandService_AdminDeleteRoom_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } -func _RoomCommandService_AdminUpdateRoomTreasureConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AdminUpdateRoomTreasureConfigRequest) +func _RoomCommandService_AdminUpdateRoomRocketConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminUpdateRoomRocketConfigRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(RoomCommandServiceServer).AdminUpdateRoomTreasureConfig(ctx, in) + return srv.(RoomCommandServiceServer).AdminUpdateRoomRocketConfig(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: RoomCommandService_AdminUpdateRoomTreasureConfig_FullMethodName, + FullMethod: RoomCommandService_AdminUpdateRoomRocketConfig_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RoomCommandServiceServer).AdminUpdateRoomTreasureConfig(ctx, req.(*AdminUpdateRoomTreasureConfigRequest)) + return srv.(RoomCommandServiceServer).AdminUpdateRoomRocketConfig(ctx, req.(*AdminUpdateRoomRocketConfigRequest)) } return interceptor(ctx, in, info, handler) } @@ -1210,8 +1210,8 @@ var RoomCommandService_ServiceDesc = grpc.ServiceDesc{ Handler: _RoomCommandService_AdminDeleteRoom_Handler, }, { - MethodName: "AdminUpdateRoomTreasureConfig", - Handler: _RoomCommandService_AdminUpdateRoomTreasureConfig_Handler, + MethodName: "AdminUpdateRoomRocketConfig", + Handler: _RoomCommandService_AdminUpdateRoomRocketConfig_Handler, }, { MethodName: "AdminUpdateRoomSeatConfig", @@ -1447,21 +1447,21 @@ var RoomGuardService_ServiceDesc = grpc.ServiceDesc{ } const ( - RoomQueryService_AdminListRooms_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRooms" - RoomQueryService_AdminGetRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoom" - RoomQueryService_AdminGetRoomTreasureConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomTreasureConfig" - RoomQueryService_AdminGetRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomSeatConfig" - RoomQueryService_AdminListRoomPins_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRoomPins" - RoomQueryService_ListRooms_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRooms" - RoomQueryService_ListRoomFeeds_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomFeeds" - RoomQueryService_ListRoomGiftLeaderboard_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomGiftLeaderboard" - RoomQueryService_GetMyRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetMyRoom" - RoomQueryService_GetCurrentRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetCurrentRoom" - RoomQueryService_GetRoomSnapshot_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetRoomSnapshot" - RoomQueryService_ListRoomBackgrounds_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomBackgrounds" - RoomQueryService_GetRoomTreasure_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetRoomTreasure" - RoomQueryService_ListRoomOnlineUsers_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomOnlineUsers" - RoomQueryService_ListRoomBannedUsers_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomBannedUsers" + RoomQueryService_AdminListRooms_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRooms" + RoomQueryService_AdminGetRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoom" + RoomQueryService_AdminGetRoomRocketConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomRocketConfig" + RoomQueryService_AdminGetRoomSeatConfig_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminGetRoomSeatConfig" + RoomQueryService_AdminListRoomPins_FullMethodName = "/hyapp.room.v1.RoomQueryService/AdminListRoomPins" + RoomQueryService_ListRooms_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRooms" + RoomQueryService_ListRoomFeeds_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomFeeds" + RoomQueryService_ListRoomGiftLeaderboard_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomGiftLeaderboard" + RoomQueryService_GetMyRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetMyRoom" + RoomQueryService_GetCurrentRoom_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetCurrentRoom" + RoomQueryService_GetRoomSnapshot_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetRoomSnapshot" + RoomQueryService_ListRoomBackgrounds_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomBackgrounds" + RoomQueryService_GetRoomRocket_FullMethodName = "/hyapp.room.v1.RoomQueryService/GetRoomRocket" + RoomQueryService_ListRoomOnlineUsers_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomOnlineUsers" + RoomQueryService_ListRoomBannedUsers_FullMethodName = "/hyapp.room.v1.RoomQueryService/ListRoomBannedUsers" ) // RoomQueryServiceClient is the client API for RoomQueryService service. @@ -1472,7 +1472,7 @@ const ( type RoomQueryServiceClient interface { AdminListRooms(ctx context.Context, in *AdminListRoomsRequest, opts ...grpc.CallOption) (*AdminListRoomsResponse, error) AdminGetRoom(ctx context.Context, in *AdminGetRoomRequest, opts ...grpc.CallOption) (*AdminGetRoomResponse, error) - AdminGetRoomTreasureConfig(ctx context.Context, in *AdminGetRoomTreasureConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomTreasureConfigResponse, error) + AdminGetRoomRocketConfig(ctx context.Context, in *AdminGetRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomRocketConfigResponse, error) AdminGetRoomSeatConfig(ctx context.Context, in *AdminGetRoomSeatConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomSeatConfigResponse, error) AdminListRoomPins(ctx context.Context, in *AdminListRoomPinsRequest, opts ...grpc.CallOption) (*AdminListRoomPinsResponse, error) ListRooms(ctx context.Context, in *ListRoomsRequest, opts ...grpc.CallOption) (*ListRoomsResponse, error) @@ -1482,7 +1482,7 @@ type RoomQueryServiceClient interface { GetCurrentRoom(ctx context.Context, in *GetCurrentRoomRequest, opts ...grpc.CallOption) (*GetCurrentRoomResponse, error) GetRoomSnapshot(ctx context.Context, in *GetRoomSnapshotRequest, opts ...grpc.CallOption) (*GetRoomSnapshotResponse, error) ListRoomBackgrounds(ctx context.Context, in *ListRoomBackgroundsRequest, opts ...grpc.CallOption) (*ListRoomBackgroundsResponse, error) - GetRoomTreasure(ctx context.Context, in *GetRoomTreasureRequest, opts ...grpc.CallOption) (*GetRoomTreasureResponse, error) + GetRoomRocket(ctx context.Context, in *GetRoomRocketRequest, opts ...grpc.CallOption) (*GetRoomRocketResponse, error) ListRoomOnlineUsers(ctx context.Context, in *ListRoomOnlineUsersRequest, opts ...grpc.CallOption) (*ListRoomOnlineUsersResponse, error) ListRoomBannedUsers(ctx context.Context, in *ListRoomBannedUsersRequest, opts ...grpc.CallOption) (*ListRoomBannedUsersResponse, error) } @@ -1515,10 +1515,10 @@ func (c *roomQueryServiceClient) AdminGetRoom(ctx context.Context, in *AdminGetR return out, nil } -func (c *roomQueryServiceClient) AdminGetRoomTreasureConfig(ctx context.Context, in *AdminGetRoomTreasureConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomTreasureConfigResponse, error) { +func (c *roomQueryServiceClient) AdminGetRoomRocketConfig(ctx context.Context, in *AdminGetRoomRocketConfigRequest, opts ...grpc.CallOption) (*AdminGetRoomRocketConfigResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(AdminGetRoomTreasureConfigResponse) - err := c.cc.Invoke(ctx, RoomQueryService_AdminGetRoomTreasureConfig_FullMethodName, in, out, cOpts...) + out := new(AdminGetRoomRocketConfigResponse) + err := c.cc.Invoke(ctx, RoomQueryService_AdminGetRoomRocketConfig_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -1615,10 +1615,10 @@ func (c *roomQueryServiceClient) ListRoomBackgrounds(ctx context.Context, in *Li return out, nil } -func (c *roomQueryServiceClient) GetRoomTreasure(ctx context.Context, in *GetRoomTreasureRequest, opts ...grpc.CallOption) (*GetRoomTreasureResponse, error) { +func (c *roomQueryServiceClient) GetRoomRocket(ctx context.Context, in *GetRoomRocketRequest, opts ...grpc.CallOption) (*GetRoomRocketResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetRoomTreasureResponse) - err := c.cc.Invoke(ctx, RoomQueryService_GetRoomTreasure_FullMethodName, in, out, cOpts...) + out := new(GetRoomRocketResponse) + err := c.cc.Invoke(ctx, RoomQueryService_GetRoomRocket_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -1653,7 +1653,7 @@ func (c *roomQueryServiceClient) ListRoomBannedUsers(ctx context.Context, in *Li type RoomQueryServiceServer interface { AdminListRooms(context.Context, *AdminListRoomsRequest) (*AdminListRoomsResponse, error) AdminGetRoom(context.Context, *AdminGetRoomRequest) (*AdminGetRoomResponse, error) - AdminGetRoomTreasureConfig(context.Context, *AdminGetRoomTreasureConfigRequest) (*AdminGetRoomTreasureConfigResponse, error) + AdminGetRoomRocketConfig(context.Context, *AdminGetRoomRocketConfigRequest) (*AdminGetRoomRocketConfigResponse, error) AdminGetRoomSeatConfig(context.Context, *AdminGetRoomSeatConfigRequest) (*AdminGetRoomSeatConfigResponse, error) AdminListRoomPins(context.Context, *AdminListRoomPinsRequest) (*AdminListRoomPinsResponse, error) ListRooms(context.Context, *ListRoomsRequest) (*ListRoomsResponse, error) @@ -1663,7 +1663,7 @@ type RoomQueryServiceServer interface { GetCurrentRoom(context.Context, *GetCurrentRoomRequest) (*GetCurrentRoomResponse, error) GetRoomSnapshot(context.Context, *GetRoomSnapshotRequest) (*GetRoomSnapshotResponse, error) ListRoomBackgrounds(context.Context, *ListRoomBackgroundsRequest) (*ListRoomBackgroundsResponse, error) - GetRoomTreasure(context.Context, *GetRoomTreasureRequest) (*GetRoomTreasureResponse, error) + GetRoomRocket(context.Context, *GetRoomRocketRequest) (*GetRoomRocketResponse, error) ListRoomOnlineUsers(context.Context, *ListRoomOnlineUsersRequest) (*ListRoomOnlineUsersResponse, error) ListRoomBannedUsers(context.Context, *ListRoomBannedUsersRequest) (*ListRoomBannedUsersResponse, error) mustEmbedUnimplementedRoomQueryServiceServer() @@ -1682,8 +1682,8 @@ func (UnimplementedRoomQueryServiceServer) AdminListRooms(context.Context, *Admi func (UnimplementedRoomQueryServiceServer) AdminGetRoom(context.Context, *AdminGetRoomRequest) (*AdminGetRoomResponse, error) { return nil, status.Error(codes.Unimplemented, "method AdminGetRoom not implemented") } -func (UnimplementedRoomQueryServiceServer) AdminGetRoomTreasureConfig(context.Context, *AdminGetRoomTreasureConfigRequest) (*AdminGetRoomTreasureConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminGetRoomTreasureConfig not implemented") +func (UnimplementedRoomQueryServiceServer) AdminGetRoomRocketConfig(context.Context, *AdminGetRoomRocketConfigRequest) (*AdminGetRoomRocketConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method AdminGetRoomRocketConfig not implemented") } func (UnimplementedRoomQueryServiceServer) AdminGetRoomSeatConfig(context.Context, *AdminGetRoomSeatConfigRequest) (*AdminGetRoomSeatConfigResponse, error) { return nil, status.Error(codes.Unimplemented, "method AdminGetRoomSeatConfig not implemented") @@ -1712,8 +1712,8 @@ func (UnimplementedRoomQueryServiceServer) GetRoomSnapshot(context.Context, *Get func (UnimplementedRoomQueryServiceServer) ListRoomBackgrounds(context.Context, *ListRoomBackgroundsRequest) (*ListRoomBackgroundsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListRoomBackgrounds not implemented") } -func (UnimplementedRoomQueryServiceServer) GetRoomTreasure(context.Context, *GetRoomTreasureRequest) (*GetRoomTreasureResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRoomTreasure not implemented") +func (UnimplementedRoomQueryServiceServer) GetRoomRocket(context.Context, *GetRoomRocketRequest) (*GetRoomRocketResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetRoomRocket not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomOnlineUsers(context.Context, *ListRoomOnlineUsersRequest) (*ListRoomOnlineUsersResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListRoomOnlineUsers not implemented") @@ -1778,20 +1778,20 @@ func _RoomQueryService_AdminGetRoom_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } -func _RoomQueryService_AdminGetRoomTreasureConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AdminGetRoomTreasureConfigRequest) +func _RoomQueryService_AdminGetRoomRocketConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminGetRoomRocketConfigRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(RoomQueryServiceServer).AdminGetRoomTreasureConfig(ctx, in) + return srv.(RoomQueryServiceServer).AdminGetRoomRocketConfig(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: RoomQueryService_AdminGetRoomTreasureConfig_FullMethodName, + FullMethod: RoomQueryService_AdminGetRoomRocketConfig_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RoomQueryServiceServer).AdminGetRoomTreasureConfig(ctx, req.(*AdminGetRoomTreasureConfigRequest)) + return srv.(RoomQueryServiceServer).AdminGetRoomRocketConfig(ctx, req.(*AdminGetRoomRocketConfigRequest)) } return interceptor(ctx, in, info, handler) } @@ -1958,20 +1958,20 @@ func _RoomQueryService_ListRoomBackgrounds_Handler(srv interface{}, ctx context. return interceptor(ctx, in, info, handler) } -func _RoomQueryService_GetRoomTreasure_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetRoomTreasureRequest) +func _RoomQueryService_GetRoomRocket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRoomRocketRequest) if err := dec(in); err != nil { return nil, err } if interceptor == nil { - return srv.(RoomQueryServiceServer).GetRoomTreasure(ctx, in) + return srv.(RoomQueryServiceServer).GetRoomRocket(ctx, in) } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: RoomQueryService_GetRoomTreasure_FullMethodName, + FullMethod: RoomQueryService_GetRoomRocket_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(RoomQueryServiceServer).GetRoomTreasure(ctx, req.(*GetRoomTreasureRequest)) + return srv.(RoomQueryServiceServer).GetRoomRocket(ctx, req.(*GetRoomRocketRequest)) } return interceptor(ctx, in, info, handler) } @@ -2028,8 +2028,8 @@ var RoomQueryService_ServiceDesc = grpc.ServiceDesc{ Handler: _RoomQueryService_AdminGetRoom_Handler, }, { - MethodName: "AdminGetRoomTreasureConfig", - Handler: _RoomQueryService_AdminGetRoomTreasureConfig_Handler, + MethodName: "AdminGetRoomRocketConfig", + Handler: _RoomQueryService_AdminGetRoomRocketConfig_Handler, }, { MethodName: "AdminGetRoomSeatConfig", @@ -2068,8 +2068,8 @@ var RoomQueryService_ServiceDesc = grpc.ServiceDesc{ Handler: _RoomQueryService_ListRoomBackgrounds_Handler, }, { - MethodName: "GetRoomTreasure", - Handler: _RoomQueryService_GetRoomTreasure_Handler, + MethodName: "GetRoomRocket", + Handler: _RoomQueryService_GetRoomRocket_Handler, }, { MethodName: "ListRoomOnlineUsers", diff --git a/docs/IM全局与区域广播架构.md b/docs/IM全局与区域广播架构.md index 5c59a099..6505b9d9 100644 --- a/docs/IM全局与区域广播架构.md +++ b/docs/IM全局与区域广播架构.md @@ -38,7 +38,7 @@ docs/房间Outbox补偿开发.md | 播报发送能力 | `activity-service` | 服务端向全局/区域播报群发送自定义消息 | | 旧区域群成员移除 | `activity-service` | 用户区域变化后,对旧区域群执行 `delete_group_member(user_id)` | | 贵重礼物播报触发 | `activity-service` consuming room outbox | 基于 `RoomGiftSent` 事实判断阈值并发区域播报 | -| 宝箱倒计时播报触发 | `activity-service` consuming room outbox | 基于 `RoomTreasureCountdownStarted` 事实按后台配置发区域或全局播报 | +| 火箭倒计时播报触发 | `activity-service` consuming room outbox | 基于 `RoomRocketCountdownStarted` 事实按后台配置发区域或全局播报 | 本阶段不做: @@ -107,7 +107,7 @@ func Parse(groupID string) ParsedGroup | 红包资金事实 | `wallet-service` 或独立 red-packet domain | IM 只携带入口和展示字段 | | 客户端 IM 长连接 | Tencent IM SDK | 本仓库不自建 WebSocket | -`room-service` 只需要继续产出 `RoomGiftSent`、`RoomTreasureCountdownStarted` 等 outbox 事实。贵重礼物和宝箱倒计时是否需要区域/全局播报,由 `activity-service` 通过 direct gRPC 或 RocketMQ `hyapp_room_outbox` consumer group 消费后判断,这样不会把区域播报策略塞进 Room Cell 主链路。 +`room-service` 只需要继续产出 `RoomGiftSent`、`RoomRocketCountdownStarted` 等 outbox 事实。贵重礼物和火箭倒计时是否需要区域/全局播报,由 `activity-service` 通过 direct gRPC 或 RocketMQ `hyapp_room_outbox` consumer group 消费后判断,这样不会把区域播报策略塞进 Room Cell 主链路。 ## Client Flow @@ -404,9 +404,9 @@ sequenceDiagram 如果现有事件字段不足,应优先扩展 protobuf event,而不是让 activity-service 反查多个服务拼凑事实。 -## Room Treasure Broadcast +## Room Rocket Broadcast -宝箱满能量进入倒计时时,Room Cell 写 `RoomTreasureCountdownStarted` outbox。activity-service 消费该事实后按后台配置决定发区域播报还是全局播报;开箱到点、奖励结算和宝箱状态推进仍由 room-service 负责。 +火箭燃料满进入倒计时时,Room Cell 写 `RoomRocketCountdownStarted` outbox。activity-service 消费该事实后按后台配置决定发区域播报还是全局播报;发射到点、奖励结算和火箭状态推进仍由 room-service 负责。 ```mermaid sequenceDiagram @@ -422,10 +422,10 @@ sequenceDiagram G->>R: SendGift R->>W: DebitGift W-->>R: receipt + heat/gift point - R->>R: add effective treasure energy + R->>R: add effective rocket energy R->>R: status=countdown when threshold reached R-->>G: SendGiftResponse - R->>MQ: RoomTreasureCountdownStarted + R->>MQ: RoomRocketCountdownStarted MQ->>A: consume by hyapp-activity-room-outbox A->>IM: send_group_msg(region/global broadcast group) ``` @@ -434,8 +434,8 @@ sequenceDiagram ```json { - "event_id": "room_treasure:lalu_room_xxx:box_1", - "broadcast_type": "room_treasure", + "event_id": "room_rocket:lalu_room_xxx:box_1", + "broadcast_type": "room_rocket", "scope": "region", "app_code": "lalu", "region_id": 1001, @@ -450,7 +450,7 @@ sequenceDiagram } ``` -倒计时期间继续送礼不会累加到下一宝箱,溢出能量也不会跨级;这些规则由 room-service 在 `RoomTreasureProgressChanged` 和 `RoomTreasureCountdownStarted` 事实中表达,activity-service 不能自行推导宝箱进度。 +倒计时期间继续送礼不会累加到下一火箭,溢出燃料也不会跨级;这些规则由 room-service 在 `RoomRocketProgressChanged` 和 `RoomRocketCountdownStarted` 事实中表达,activity-service 不能自行推导火箭进度。 ## Red Packet Broadcast @@ -496,7 +496,7 @@ sequenceDiagram 5. `activity-service` 增加 broadcast group reconciler,启动时确保全局和 active 区域群。 6. `activity-service` 增加 `PublishRegionBroadcast/PublishGlobalBroadcast` 和 broadcast outbox。 7. 扩展 `RoomGiftSent` 事件字段,activity-service 消费后按阈值发 `super_gift` 区域播报。 -8. 消费 `RoomTreasureCountdownStarted`,按后台配置发 `room_treasure` 区域或全局播报。 +8. 消费 `RoomRocketCountdownStarted`,按后台配置发 `room_rocket` 区域或全局播报。 9. 红包领域落账务事实后,复用同一播报能力发送 `red_packet` 消息。 ## Test Expectations @@ -513,5 +513,5 @@ sequenceDiagram | group reconciler | 已存在群视为成功,失败可重试 | | broadcast outbox | 同一 `event_id` 幂等,失败后 retry | | super gift | 未达阈值不播报,达阈值发送到用户房间所在区域群 | -| room treasure | 宝箱满能量后只按 `RoomTreasureCountdownStarted` 播报一次;区域/全局 scope 来自后台配置 | +| room rocket | 火箭燃料满后只按 `RoomRocketCountdownStarted` 播报一次;区域/全局 scope 来自后台配置 | | red packet | IM payload 不影响领取接口的后端金额校验 | diff --git a/docs/flutter对接/语音房宝箱Flutter对接.md b/docs/flutter对接/语音房火箭Flutter对接.md similarity index 76% rename from docs/flutter对接/语音房宝箱Flutter对接.md rename to docs/flutter对接/语音房火箭Flutter对接.md index 00ae1ffe..5d3f10fa 100644 --- a/docs/flutter对接/语音房宝箱Flutter对接.md +++ b/docs/flutter对接/语音房火箭Flutter对接.md @@ -1,6 +1,6 @@ -# 语音房宝箱 Flutter 对接 +# 语音房火箭 Flutter 对接 -本文描述 Flutter App 对接语音房宝箱所需的 HTTP 接口、请求参数、返回值、错误处理和腾讯云 IM 自定义消息 key。宝箱进度、开箱和发奖事实由 `room-service` Room Cell 持有;客户端只展示服务端返回或 IM 推送的状态,不能本地计算能量、奖励或开箱结果。 +本文描述 Flutter App 对接语音房火箭所需的 HTTP 接口、请求参数、返回值、错误处理和腾讯云 IM 自定义消息 key。火箭进度、发射和发奖事实由 `room-service` Room Cell 持有;客户端只展示服务端返回或 IM 推送的状态,不能本地计算燃料、奖励或发射结果。 ## 基础约定 @@ -40,18 +40,18 @@ http://127.0.0.1:13000 ## 客户端流程 -1. 用户成功 `JoinRoom` 后调用 `GET /api/v1/rooms/{room_id}/treasure` 初始化 7 级物料和当前进度。 -2. 用户送礼调用 `POST /api/v1/rooms/gift/send`;成功响应里的 `data.treasure` 可立即更新当前宝箱状态。 -3. 房间内监听腾讯 IM 群 `TIMCustomElem.Ext=room_system_message`,处理宝箱进度、倒计时、开箱和发奖。 -4. App 全局或区域播报监听 `TIMCustomElem.Ext=im_broadcast` 且 `broadcast_type=room_treasure`。 -5. 任意 IM 丢失、字段解析失败、版本倒退或页面重进时,重新调用 `GET /api/v1/rooms/{room_id}/treasure` 纠正本地状态。 +1. 用户成功 `JoinRoom` 后调用 `GET /api/v1/rooms/{room_id}/rocket` 初始化 7 级物料和当前进度。 +2. 用户送礼调用 `POST /api/v1/rooms/gift/send`;成功响应里的 `data.rocket` 可立即更新当前火箭状态。 +3. 房间内监听腾讯 IM 群 `TIMCustomElem.Ext=room_system_message`,处理火箭进度、倒计时、发射和发奖。 +4. App 全局或区域播报监听 `TIMCustomElem.Ext=im_broadcast` 且 `broadcast_type=room_rocket`。 +5. 任意 IM 丢失、字段解析失败、版本倒退或页面重进时,重新调用 `GET /api/v1/rooms/{room_id}/rocket` 纠正本地状态。 客户端必须用 `event_id` 去重,用 `room_version` 丢弃旧房间消息。 -## 获取宝箱信息 +## 获取火箭信息 ```http -GET /api/v1/rooms/{room_id}/treasure +GET /api/v1/rooms/{room_id}/rocket Authorization: Bearer X-App-Code: lalu ``` @@ -117,11 +117,11 @@ X-App-Code: lalu | 字段 | 类型 | 说明 | | --- | --- | --- | -| `enabled` | bool | 宝箱总开关。`false` 时客户端隐藏或置灰宝箱入口。 | +| `enabled` | bool | 火箭总开关。`false` 时客户端隐藏或置灰火箭入口。 | | `levels` | array | 固定 7 个等级的物料、阈值和奖励池。 | -| `state` | object | 当前房间当前 UTC 日的宝箱状态。 | +| `state` | object | 当前房间当前 UTC 日的火箭状态。 | | `broadcast_scope` | string | `none`、`region`、`global`。 | -| `open_delay_ms` | int64 | 满能量后到开箱的倒计时配置。 | +| `open_delay_ms` | int64 | 燃料满后到发射的倒计时配置。 | | `broadcast_delay_ms` | int64 | 后台配置字段;当前房间事件会立即进入播报链路。 | | `reward_stack_policy` | string | `allow_stack` 或 `priority_only`。 | | `server_time_ms` | int64 | 服务端当前时间,倒计时要以它校准本地时钟偏差。 | @@ -131,12 +131,12 @@ X-App-Code: lalu | 字段 | 类型 | 说明 | | --- | --- | --- | | `level` | int32 | 等级,1 到 7。 | -| `energy_threshold` | int64 | 当前等级满能量阈值。 | +| `energy_threshold` | int64 | 当前等级燃料满阈值。 | | `cover_url` | string | 静态封面图。 | -| `animation_url` | string | 未开箱/蓄能态动效。 | -| `opening_animation_url` | string | 开箱动效。 | -| `opened_image_url` | string | 开箱后展示图。 | -| `in_room_rewards` | array | 开箱时仍在房用户的奖励候选展示。 | +| `animation_url` | string | 未发射/蓄能态动效。 | +| `opening_animation_url` | string | 发射动效。 | +| `opened_image_url` | string | 发射后展示图。 | +| `in_room_rewards` | array | 发射时仍在房用户的奖励候选展示。 | | `top1_rewards` | array | 倒计时开始时贡献第一用户奖励候选展示。 | | `igniter_rewards` | array | 点火人奖励候选展示。 | @@ -155,18 +155,18 @@ X-App-Code: lalu | 字段 | 类型 | 说明 | | --- | --- | --- | | `current_level` | int32 | 当前等级,1 到 7。 | -| `current_progress` | int64 | 当前等级已累计有效能量。 | +| `current_progress` | int64 | 当前等级已累计有效燃料。 | | `energy_threshold` | int64 | 当前等级阈值。 | | `status` | string | 当前返回 `idle` 或 `countdown`。 | | `countdown_started_at_ms` | int64 | 倒计时开始时间;非倒计时可为空或 0。 | -| `open_at_ms` | int64 | 预计开箱时间;`status=countdown` 时有效。 | -| `opened_at_ms` | int64 | 最近一次开箱时间。 | +| `open_at_ms` | int64 | 预计发射时间;`status=countdown` 时有效。 | +| `opened_at_ms` | int64 | 最近一次发射时间。 | | `reset_at_ms` | int64 | 下一个 UTC 0 点;到点后进度按新 UTC 日重置。 | | `top1_user_id` | string | 倒计时开始时锁定的贡献第一;GET 接口中按字符串返回。 | | `igniter_user_id` | string | 点火人;GET 接口中按字符串返回。 | -| `box_id` | string | 当前倒计时宝箱或最近状态的单轮幂等 ID。 | +| `box_id` | string | 当前倒计时火箭或最近状态的单轮幂等 ID。 | | `config_version` | int64 | 当前状态关联的后台配置版本。 | -| `last_rewards` | array | 最近一次开箱发奖结果;客户端可用于展示开箱结果兜底。 | +| `last_rewards` | array | 最近一次发射发奖结果;客户端可用于展示发射结果兜底。 | `last_rewards[]` 字段: @@ -185,10 +185,10 @@ X-App-Code: lalu - 进度条使用 `current_progress / energy_threshold`,并且最大显示 100%。 - 倒计时使用 `open_at_ms - server_time_ms` 初始化,再用本地 timer 驱动。 -- 不要把送礼溢出能量展示到下一等级;服务端规则是溢出作废。 -- 如果 `status=countdown`,继续送礼不会改变宝箱进度、点火人、贡献第一或 `open_at_ms`。 +- 不要把送礼溢出燃料展示到下一等级;服务端规则是溢出作废。 +- 如果 `status=countdown`,继续送礼不会改变火箭进度、点火人、贡献第一或 `open_at_ms`。 -## 送礼并更新宝箱 +## 送礼并更新火箭 ```http POST /api/v1/rooms/gift/send @@ -246,7 +246,7 @@ Content-Type: application/json } ], "room": {}, - "treasure": { + "rocket": { "current_level": 2, "current_progress": 200, "energy_threshold": 200, @@ -256,7 +256,7 @@ Content-Type: application/json "reset_at_ms": 1779321600000, "top1_user_id": 12345678, "igniter_user_id": 12345678, - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "config_version": 3 } } @@ -273,9 +273,9 @@ Content-Type: application/json | `data.room_heat` | int64 | 送礼后的房间热度。 | | `data.gift_rank` | array | 送礼后的本地贡献榜快照。 | | `data.room` | object | 房间快照。 | -| `data.treasure` | object | 送礼后宝箱状态;送礼人可立即用它刷新 UI。 | +| `data.rocket` | object | 送礼后火箭状态;送礼人可立即用它刷新 UI。 | -注意:`GET /treasure` 的用户 ID 字段按字符串返回,`POST /gift/send` 透出的 protobuf 状态里部分用户 ID 可能是数字。Flutter 侧建议用统一 helper 兼容 `String` 和 `num`。 +注意:`GET /rocket` 的用户 ID 字段按字符串返回,`POST /gift/send` 透出的 protobuf 状态里部分用户 ID 可能是数字。Flutter 侧建议用统一 helper 兼容 `String` 和 `num`。 ```dart String readId(dynamic value) { @@ -324,15 +324,15 @@ String readId(dynamic value) { | 502 | `UPSTREAM_ERROR` | room/wallet 等依赖暂不可用。 | 提示稍后重试,可保留原 `command_id` 重试同一次送礼。 | | 500 | `INTERNAL_ERROR` | 服务端内部错误。 | 提示失败并记录 `request_id`。 | -宝箱相关额外规则: +火箭相关额外规则: -- 获取宝箱信息要求当前用户仍在房间业务 presence 内;离房后调用会返回 `PERMISSION_DENIED` 或 `NOT_FOUND`。 -- 宝箱关闭时,`GET /treasure` 仍可能返回 `enabled=false` 和 7 级配置;客户端不展示进度入口即可。 +- 获取火箭信息要求当前用户仍在房间业务 presence 内;离房后调用会返回 `PERMISSION_DENIED` 或 `NOT_FOUND`。 +- 火箭关闭时,`GET /rocket` 仍可能返回 `enabled=false` 和 7 级配置;客户端不展示进度入口即可。 - 发奖自动完成,没有 App 领取接口;客户端不要补发或重复调用钱包接口。 ## 房间群 IM 消息 -房间内宝箱进度、倒计时、开箱和发奖通过腾讯云 IM 房间群 `TIMCustomElem` 投递。 +房间内火箭进度、倒计时、发射和发奖通过腾讯云 IM 房间群 `TIMCustomElem` 投递。 | 字段 | 值 | | --- | --- | @@ -348,12 +348,12 @@ String readId(dynamic value) { { "event_id": "evt_xxx", "room_id": "lalu_xxx", - "event_type": "room_treasure_progress_changed", + "event_type": "room_rocket_progress_changed", "actor_user_id": 12345678, "target_user_id": 0, "room_version": 8, "attributes": { - "box_id": "room_treasure_box_xxx" + "box_id": "room_rocket_box_xxx" } } ``` @@ -365,21 +365,21 @@ String readId(dynamic value) { | `event_id` | string | IM 去重键。 | | `room_id` | string | 房间 ID。 | | `event_type` | string | 事件类型,见下表。 | -| `actor_user_id` | int64 | 触发用户;倒计时/开箱通常为点火人。 | -| `target_user_id` | int64 | 目标用户;倒计时/开箱通常为 top1。 | +| `actor_user_id` | int64 | 触发用户;倒计时/发射通常为点火人。 | +| `target_user_id` | int64 | 目标用户;倒计时/发射通常为 top1。 | | `room_version` | int64 | 房间版本,本地版本更高时丢弃旧消息。 | | `attributes` | map | 业务字段;值全部按字符串传输,Flutter 侧按需转 int/bool/JSON。 | -宝箱房间群事件: +火箭房间群事件: | `event_type` | `Desc` | 用途 | | --- | --- | --- | -| `room_treasure_progress_changed` | `room_treasure_progress_changed` | 有效宝箱能量增加。 | -| `room_treasure_countdown_started` | `room_treasure_countdown_started` | 当前等级满能量,进入倒计时。 | -| `room_treasure_opened` | `room_treasure_opened` | 宝箱已打开,包含公开奖励摘要。 | -| `room_treasure_reward_granted` | `room_treasure_reward_granted` | 发奖结果事件,包含奖励列表。 | +| `room_rocket_progress_changed` | `room_rocket_progress_changed` | 有效火箭燃料增加。 | +| `room_rocket_countdown_started` | `room_rocket_countdown_started` | 当前等级燃料满,进入倒计时。 | +| `room_rocket_opened` | `room_rocket_opened` | 火箭已打开,包含公开奖励摘要。 | +| `room_rocket_reward_granted` | `room_rocket_reward_granted` | 发奖结果事件,包含奖励列表。 | -### room_treasure_progress_changed +### room_rocket_progress_changed 示例: @@ -387,11 +387,11 @@ String readId(dynamic value) { { "event_id": "evt_progress", "room_id": "lalu_xxx", - "event_type": "room_treasure_progress_changed", + "event_type": "room_rocket_progress_changed", "actor_user_id": 12345678, "room_version": 6, "attributes": { - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "level": "2", "added_energy": "300", "effective_added_energy": "200", @@ -410,11 +410,11 @@ String readId(dynamic value) { 处理: - 更新当前等级进度为 `current_progress`。 -- `effective_added_energy` 是本次实际计入宝箱的能量。 -- `overflow_energy` 是作废能量,不能加到下一等级。 -- 如果 `status=countdown`,立即切换倒计时态,等待 `room_treasure_countdown_started` 补齐 `open_at_ms`;如该消息丢失,调用 GET 兜底。 +- `effective_added_energy` 是本次实际计入火箭的燃料。 +- `overflow_energy` 是作废燃料,不能加到下一等级。 +- 如果 `status=countdown`,立即切换倒计时态,等待 `room_rocket_countdown_started` 补齐 `open_at_ms`;如该消息丢失,调用 GET 兜底。 -### room_treasure_countdown_started +### room_rocket_countdown_started 示例: @@ -422,12 +422,12 @@ String readId(dynamic value) { { "event_id": "evt_countdown", "room_id": "lalu_xxx", - "event_type": "room_treasure_countdown_started", + "event_type": "room_rocket_countdown_started", "actor_user_id": 12345678, "target_user_id": 12345678, "room_version": 6, "attributes": { - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "level": "2", "current_progress": "200", "energy_threshold": "200", @@ -444,13 +444,13 @@ String readId(dynamic value) { 处理: -- 按 `open_at_ms` 展示开箱倒计时。 +- 按 `open_at_ms` 展示发射倒计时。 - `top1_user_id` 和 `igniter_user_id` 在此刻锁定;后续离房或下线也不影响这两类奖励发放。 -- 倒计时期间再收到普通 `room_gift_sent`,只更新礼物表现和热度,不改变宝箱倒计时。 +- 倒计时期间再收到普通 `room_gift_sent`,只更新礼物表现和热度,不改变火箭倒计时。 注意:房间群 IM 字段名是 `countdown_start_ms`,HTTP state 字段名是 `countdown_started_at_ms`。 -### room_treasure_opened +### room_rocket_opened 示例: @@ -458,12 +458,12 @@ String readId(dynamic value) { { "event_id": "evt_opened", "room_id": "lalu_xxx", - "event_type": "room_treasure_opened", + "event_type": "room_rocket_opened", "actor_user_id": 12345678, "target_user_id": 12345678, "room_version": 8, "attributes": { - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "level": "2", "next_level": "3", "opened_at_ms": "1779259512668", @@ -481,7 +481,7 @@ String readId(dynamic value) { - 解析 `rewards_json` 得到奖励列表;如果解析失败,调用 GET 获取 `state.last_rewards`。 - 本地状态进入 `next_level`,进度归 0,状态归 `idle`。 -### room_treasure_reward_granted +### room_rocket_reward_granted 示例: @@ -489,10 +489,10 @@ String readId(dynamic value) { { "event_id": "evt_reward", "room_id": "lalu_xxx", - "event_type": "room_treasure_reward_granted", + "event_type": "room_rocket_reward_granted", "room_version": 8, "attributes": { - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "level": "2", "rewards_json": "[{\"reward_role\":\"top1\",\"user_id\":12345678,\"reward_item_id\":\"lv2_top1_1\",\"resource_group_id\":1002,\"display_name\":\"Top Reward\",\"icon_url\":\"https://cdn.example/reward/top.png\",\"grant_id\":\"rgr_xxx\",\"status\":\"succeeded\"}]" } @@ -505,17 +505,17 @@ String readId(dynamic value) { - 当前登录用户在奖励列表中时,展示“获得奖励”提示。 - 同一用户可能同时命中 `in_room`、`top1`、`igniter`,是否叠加由 `reward_stack_policy` 决定;客户端按服务端发下来的列表展示。 -当前没有单独的 C2C 宝箱中奖私信,也没有 App 消息 Tab 宝箱入箱消息。后续如新增私有通知,应以新的 C2C `Ext` 文档为准,不复用房间群消息假装私信。 +当前没有单独的 C2C 火箭中奖私信,也没有 App 消息 Tab 火箭入箱消息。后续如新增私有通知,应以新的 C2C `Ext` 文档为准,不复用房间群消息假装私信。 ## 区域/全局播报 IM -满能量进入倒计时后,如果后台配置允许播报,`activity-service` 会向区域或全局播报群发送 `TIMCustomElem`。 +燃料满进入倒计时后,如果后台配置允许播报,`activity-service` 会向区域或全局播报群发送 `TIMCustomElem`。 | 字段 | 值 | | --- | --- | | `MsgType` | `TIMCustomElem` | | `MsgContent.Ext` | `im_broadcast` | -| `MsgContent.Desc` | `room_treasure` | +| `MsgContent.Desc` | `room_rocket` | | `MsgContent.Data` | JSON 字符串 | | `CloudCustomData` | 与 `MsgContent.Data` 相同的 JSON 字符串 | @@ -523,13 +523,13 @@ String readId(dynamic value) { ```json { - "event_id": "room_treasure_broadcast:lalu_xxx:room_treasure_box_xxx", - "broadcast_type": "room_treasure", + "event_id": "room_rocket_broadcast:lalu_xxx:room_rocket_box_xxx", + "broadcast_type": "room_rocket", "scope": "region", "app_code": "lalu", "region_id": 1001, "room_id": "lalu_xxx", - "box_id": "room_treasure_box_xxx", + "box_id": "room_rocket_box_xxx", "level": 2, "open_at_ms": 1779259512104, "top1_user_id": 12345678, @@ -549,10 +549,10 @@ String readId(dynamic value) { 处理: -- `broadcast_type=room_treasure` 时展示宝箱倒计时播报。 +- `broadcast_type=room_rocket` 时展示火箭倒计时播报。 - 点击播报按 `action.type=enter_room` 跳转或进房。 - `scope=region` 表示区域播报群;`scope=global` 表示全局播报群。 -- 播报只负责引导和展示,不代替房间内宝箱状态;进房后仍调用 GET 初始化。 +- 播报只负责引导和展示,不代替房间内火箭状态;进房后仍调用 GET 初始化。 ## 普通送礼房间 IM @@ -564,7 +564,7 @@ String readId(dynamic value) { | `MsgContent.Desc` | `room_gift_sent` | | `Data.event_type` | `room_gift_sent` | -宝箱 UI 不应该只靠 `room_gift_sent` 推算能量;能量以 `room_treasure_progress_changed`、`room_treasure_countdown_started`、`POST /gift/send.data.treasure` 或 GET 结果为准。 +火箭 UI 不应该只靠 `room_gift_sent` 推算燃料;燃料以 `room_rocket_progress_changed`、`room_rocket_countdown_started`、`POST /gift/send.data.rocket` 或 GET 结果为准。 ## Flutter 解析建议 @@ -600,12 +600,12 @@ List> readRewardsJson(dynamic value) { | 输入 | 处理 | | --- | --- | -| `GET /treasure` | 覆盖本地完整宝箱状态和 7 级物料。 | -| `POST /gift/send.data.treasure` | 送礼人立即刷新当前状态。 | -| `room_treasure_progress_changed` | 同房间、版本不旧时更新进度。 | -| `room_treasure_countdown_started` | 切换倒计时,并锁定 top1/点火人展示。 | -| `room_treasure_opened` | 播放开箱动效,状态切到下一等级 idle。 | -| `room_treasure_reward_granted` | 展示当前用户中奖提示;按 `event_id` 去重。 | -| `im_broadcast + room_treasure` | 展示区域/全局播报入口,不直接改当前房间状态。 | +| `GET /rocket` | 覆盖本地完整火箭状态和 7 级物料。 | +| `POST /gift/send.data.rocket` | 送礼人立即刷新当前状态。 | +| `room_rocket_progress_changed` | 同房间、版本不旧时更新进度。 | +| `room_rocket_countdown_started` | 切换倒计时,并锁定 top1/点火人展示。 | +| `room_rocket_opened` | 播放发射动效,状态切到下一等级 idle。 | +| `room_rocket_reward_granted` | 展示当前用户中奖提示;按 `event_id` 去重。 | +| `im_broadcast + room_rocket` | 展示区域/全局播报入口,不直接改当前房间状态。 | -如果客户端发现本地状态和服务端事件无法合并,例如当前 `box_id` 不一致、`level` 倒退、`room_version` 缺失,直接调用 `GET /api/v1/rooms/{room_id}/treasure` 重新同步。 +如果客户端发现本地状态和服务端事件无法合并,例如当前 `box_id` 不一致、`level` 倒退、`room_version` 缺失,直接调用 `GET /api/v1/rooms/{room_id}/rocket` 重新同步。 diff --git a/docs/定时任务服务架构.md b/docs/定时任务服务架构.md index 22616dbd..076661d7 100644 --- a/docs/定时任务服务架构.md +++ b/docs/定时任务服务架构.md @@ -18,7 +18,7 @@ | `room-service` | stale presence cleanup | `services/room-service/internal/room/service/presence.go` | 留在 `room-service` | | `room-service` | mic publish timeout cleanup | `services/room-service/internal/room/service/mic_publish_timeout.go` | 留在 `room-service` | | `room-service` | room outbox relay to direct publishers / RocketMQ | `services/room-service/internal/room/service/outbox_worker.go` | 留在 `room-service` 或后续拆 `room-worker`,不进通用 cron | -| `room-service` | room treasure delayed open wakeup | `services/room-service/internal/room/service/room_treasure.go`、`services/room-service/internal/room/service/room_treasure_mq.go` | 留在 `room-service`;RocketMQ 只唤醒,到点后仍走 Room Cell 命令链路 | +| `room-service` | room rocket delayed open wakeup | `services/room-service/internal/room/service/room_rocket.go`、`services/room-service/internal/room/service/room_rocket_mq.go` | 留在 `room-service`;RocketMQ 只唤醒,到点后仍走 Room Cell 命令链路 | | `user-service` | region rebuild task | `UserCronService.ProcessRegionRebuildBatch` | 已迁移到 cron-service 调度,旧内置 ticker 已删除 | | `user-service` | login IP risk job | `UserCronService.ProcessLoginIPRiskBatch` | 已迁移到 cron-service 调度,旧内置 ticker 已删除 | | `user-service` | invite recharge wallet outbox consumer | `services/user-service/internal/service/invite/service.go` | 先不迁,需补 durable cursor 或事件总线 | @@ -95,7 +95,7 @@ graph LR | Room Cell stale presence cleanup | 依赖本节点已装载 Room Cell 和 Redis lease,必须由 `room-service` owner 执行命令链路 | | Mic publish timeout cleanup | 必须对当前 Room Cell 状态做二次校验并执行 `MicDown`,不能让 cron 直接清麦 | | room outbox relay | 这是 room-service 的事件投递补偿,不是通用定时任务;需要和 direct publisher、RocketMQ 发布、outbox 状态语义绑定 | -| room treasure open timer | 宝箱状态属于 Room Cell;延迟消息只负责唤醒,开箱必须由 room-service 重新校验 `box_id/open_at_ms/UTC reset` 后执行命令 | +| room rocket open timer | 火箭状态属于 Room Cell;延迟消息只负责唤醒,发射必须由 room-service 重新校验 `box_id/open_at_ms/UTC reset` 后执行命令 | | wallet ledger transaction | 金币、钻石、积分、余额的加减和冻结必须在 `wallet-service` 事务内完成 | | wallet outbox publish | 属于 wallet-service outbox relay 或 MQ 投递,不应该由通用 cron 直接扫表改状态 | | invite recharge outbox consumer | 当前使用 in-memory cursor 扫 wallet outbox,迁移前必须先做 durable offset 或正式事件总线 | @@ -269,7 +269,7 @@ cron-service 可以直接开启多个实例;调度层通过 `cron_task_leases` - activity room outbox consumer。 - notice room outbox consumer。 - room IM bridge MQ consumer。 -- room treasure delayed open consumer。 +- room rocket delayed open consumer。 这些需要的是事件消费基础设施:RocketMQ、Redis Stream、或 MySQL durable offset。cron-service 不能用“每隔几秒从头扫 outbox”的方式替代事件消费者。即使某些消费者内部有低频扫描补偿,也必须留在业务 owner service 中,因为它们需要理解 outbox 状态、消费幂等和领域状态校验。 diff --git a/docs/房间Outbox补偿开发.md b/docs/房间Outbox补偿开发.md index 938073f4..d76fff6c 100644 --- a/docs/房间Outbox补偿开发.md +++ b/docs/房间Outbox补偿开发.md @@ -9,7 +9,7 @@ | 状态 owner | Room Cell 和 MySQL snapshot/command log 是房间状态权威来源 | | 持久事实 | `room_outbox` 是房间外事件的持久事实源,和房间命令提交链路一起落 MySQL | | 发布模式 | `outbox_worker.publish_mode` 支持 `direct`、`mq`、`dual` | -| MQ 职责 | RocketMQ 只做事件分发和宝箱延迟唤醒,不保存房间核心状态 | +| MQ 职责 | RocketMQ 只做事件分发和火箭延迟唤醒,不保存房间核心状态 | | 下游语义 | 下游服务按 `event_id` 幂等消费,失败由自己的位点、重试和死信处理 | | 主链路 | HTTP/gRPC 请求不等待 IM REST、activity、notice、push 或 inbox 投递完成 | @@ -37,7 +37,7 @@ gateway -> room-service command outbox worker -> claim pending/retryable rows - -> if RoomTreasureCountdownStarted, schedule treasure open delayed wakeup when configured + -> if RoomRocketCountdownStarted, schedule rocket open delayed wakeup when configured -> publish by mode: direct: Tencent IM publisher + activity gRPC publisher mq: RocketMQ room_outbox publisher @@ -78,9 +78,9 @@ outbox worker | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-activity-room-outbox` | activity-service 消费房间事实,做活动、播报、系统消息等后续处理 | | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-notice-room-outbox` | notice-service 消费私有通知相关事实,例如 `RoomUserKicked` | | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-room-im-bridge` | room-service IM bridge 消费房间群系统消息和群成员控制事实 | -| `hyapp_room_treasure_open` | `room-service` treasure scheduler | `hyapp-room-treasure-open` | 宝箱倒计时到点唤醒 Room Cell 开箱命令 | +| `hyapp_room_rocket_open` | `room-service` rocket scheduler | `hyapp-room-rocket-open` | 火箭倒计时到点唤醒 Room Cell 发射命令 | -`hyapp_room_treasure_open` 不是业务状态源。消息只携带 `app_code、room_id、box_id、level、open_at_ms、command_id` 等唤醒参数;真正能否开箱仍由 room-service 加载 Room Cell 后校验当前宝箱状态、等级、`box_id`、`open_at_ms` 和 UTC 重置边界。 +`hyapp_room_rocket_open` 不是业务状态源。消息只携带 `app_code、room_id、box_id、level、open_at_ms、command_id` 等唤醒参数;真正能否发射仍由 room-service 加载 Room Cell 后校验当前火箭状态、等级、`box_id`、`open_at_ms` 和 UTC 重置边界。 ## 配置 @@ -103,11 +103,11 @@ rocketmq: tencent_im_consumer_enabled: false tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - treasure_open: + rocket_open: enabled: false - topic: "hyapp_room_treasure_open" - producer_group: "hyapp-room-treasure-open-producer" - consumer_group: "hyapp-room-treasure-open" + topic: "hyapp_room_rocket_open" + producer_group: "hyapp-room-rocket-open-producer" + consumer_group: "hyapp-room-rocket-open" consumer_max_reconsume_times: 16 outbox_worker: @@ -129,7 +129,7 @@ outbox_worker: | `rocketmq.enabled` | 控制 RocketMQ client 是否启用;本地默认关闭,线上示例开启 | | `rocketmq.room_outbox.enabled` | 控制 room outbox 是否可发布到 MQ;`publish_mode=mq/dual` 时必须开启 | | `rocketmq.room_outbox.tencent_im_consumer_enabled` | 控制 room-service 是否作为 IM bridge consumer 消费 `hyapp_room_outbox` | -| `rocketmq.treasure_open.enabled` | 控制宝箱倒计时是否发布和消费延迟唤醒消息 | +| `rocketmq.rocket_open.enabled` | 控制火箭倒计时是否发布和消费延迟唤醒消息 | | `outbox_worker.publish_mode` | 本地默认 `direct`,线上建议 `mq`,迁移期可用 `dual` | | `poll_interval` | worker 空轮询间隔,必须大于 0,避免 busy loop | | `batch_size` | 每轮最大抢占条数,必须大于 0,避免全表扫描 | @@ -143,7 +143,7 @@ outbox_worker: | RocketMQ room outbox publisher | 把 protobuf outbox 包装成统一 `room_outbox_event`,发布到 `hyapp_room_outbox` | | Tencent IM direct publisher | `RoomCreated` 对已同步创建的房间群执行幂等 EnsureGroup;房间系统事件发送腾讯云 IM 群自定义消息 | | Activity direct publisher | 本地或未接 MQ 时直接调用 activity-service room event 消费入口 | -| Treasure open scheduler | 在 `RoomTreasureCountdownStarted` 后发布到点延迟消息,唤醒 room-service 开箱 | +| Rocket open scheduler | 在 `RoomRocketCountdownStarted` 后发布到点延迟消息,唤醒 room-service 发射 | | Activity MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,按 `event_id` 幂等推进活动/播报逻辑 | | Notice MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,写 `notice_delivery_events` 后投 C2C 私有通知 | | Room IM bridge MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,投递房间群系统消息和群成员控制 | @@ -193,6 +193,6 @@ RocketMQ consumer 失败时不修改 `room_outbox`。consumer 应依赖 RocketMQ | MQ 不可用,`mq/dual` | 房间写命令仍成功,outbox 进入重试;MQ 恢复后补发 | | activity consumer 不可用,`mq` | `room_outbox` 不回退;RocketMQ 和 activity 消费位点负责积压与重试 | | poison event | 达到 `max_retry_count` 后进入 `failed`,不再每秒刷日志 | -| 宝箱倒计时 | `RoomTreasureCountdownStarted` 发布延迟唤醒;到点后 room-service 重新校验状态再开箱 | +| 火箭倒计时 | `RoomRocketCountdownStarted` 发布延迟唤醒;到点后 room-service 重新校验状态再发射 | | 正常投递 | 同一 `event_id` 可被多个 consumer group 独立消费且重复投递不产生重复副作用 | | 真实链路 | create/join/mic/sendGift/leave 均有 `room_command_timing` | diff --git a/docs/语音房功能清单.md b/docs/语音房功能清单.md index ae123365..bb56f688 100644 --- a/docs/语音房功能清单.md +++ b/docs/语音房功能清单.md @@ -136,7 +136,7 @@ | 礼物配置 | `PARTIAL` | `wallet_gift_prices` 提供服务端价格和 `COIN`/`DIAMOND` 收费资产,`gift_configs` 提供礼物类型、有效期和特效;SendGift 请求只传 `gift_id/gift_count`;礼物配置已绑定 `resource_type=gift` 资源 | 客户端礼物表现联调、资源版本缓存刷新未做 | | 背包/道具 | `PARTIAL` | `user_resource_entitlements`、`user_resource_equipment` 支持资源发放、我的资源和可佩戴资源装备 | 背包扣减、免费礼物、道具过期扫描未做 | | 礼物消息补偿 | `DONE` | GiftSent/Heat/Rank 事件进入 outbox,由 worker direct 投 IM/activity,或发布到 RocketMQ 后由各 consumer group 消费 | 客户端去重和展示策略未验收 | -| 语音房宝箱 | `DONE` | `room_treasure_configs`、`GetRoomTreasure`、`RoomTreasureProgressChanged/CountdownStarted/Opened/RewardGranted`,开箱支持本地扫描和 RocketMQ 延迟唤醒 | App UI、后台配置运营验收和真实 MQ 联调 | +| 语音房火箭 | `DONE` | `room_rocket_configs`、`GetRoomRocket`、`RoomRocketProgressChanged/CountdownStarted/Opened/RewardGranted`,发射支持本地扫描和 RocketMQ 延迟唤醒 | App UI、后台配置运营验收和真实 MQ 联调 | ## Activity And Lucky Gift diff --git a/docs/语音房宝箱功能架构.md b/docs/语音房火箭功能架构.md similarity index 64% rename from docs/语音房宝箱功能架构.md rename to docs/语音房火箭功能架构.md index 197d182e..687e3d64 100644 --- a/docs/语音房宝箱功能架构.md +++ b/docs/语音房火箭功能架构.md @@ -1,45 +1,45 @@ -# 语音房宝箱功能架构 +# 语音房火箭功能架构 -本文定义当前语音房宝箱的产品规则、服务边界、App 接口、后台配置、MQ 唤醒、room outbox 事件和验收边界。宝箱是房间内送礼驱动的互动玩法:用户在语音房送礼积攒能量,当前等级满能量后进入倒计时,倒计时结束时由 `room-service` 按 Room Cell 快照结算并调用 `wallet-service` 发放资源组奖励。所有周期、重置和统计口径统一使用 UTC。 +本文定义当前语音房火箭的产品规则、服务边界、App 接口、后台配置、MQ 唤醒、room outbox 事件和验收边界。火箭是房间内送礼驱动的互动玩法:用户在语音房送礼积攒燃料,当前等级燃料满后进入倒计时,倒计时结束时由 `room-service` 按 Room Cell 快照结算并调用 `wallet-service` 发放资源组奖励。所有周期、重置和统计口径统一使用 UTC。 ## 当前实现结论 | 能力 | 当前事实 | | --- | --- | -| App 初始化 | `GET /api/v1/rooms/{room_id}/treasure` 返回 7 级物料、当前等级、当前进度、重置时间、奖励展示配置 | -| 送礼累积 | `SendGift` 同步调用 `wallet-service.DebitGift` 成功后,Room Cell 内更新热度、礼物榜和宝箱进度 | -| 满能量 | 当前等级进度封顶为阈值,锁定点火人、贡献第一、`box_id`、`open_at_ms` 和 UTC `reset_at_ms` | -| 溢出和倒计时送礼 | 当前等级溢出能量作废;倒计时期间送礼不累加到下一级,也不改变点火人或贡献第一 | -| 到期开箱 | `room-service` 通过 RocketMQ 延迟消息到 `open_at_ms` 唤醒;本地已加载 Cell 扫描 worker 仍作为兜底 | -| 奖励结算 | `room-service` 在开箱命令内按配置加权抽取奖励,并调用 `wallet-service.GrantResourceGroup` 幂等发放 | -| 离房/下线 | `top1` 和 `igniter` 在倒计时开始时锁定;开箱前离房或下线仍结算对应角色奖励 | -| 在房奖励 | 只发给开箱命令执行时 Room Cell `OnlineUsers` 中的用户 | -| 播报 | `activity-service` 消费 `RoomTreasureCountdownStarted`,按 `broadcast_scope` 发区域或全局播报 | +| App 初始化 | `GET /api/v1/rooms/{room_id}/rocket` 返回 7 级物料、当前等级、当前进度、重置时间、奖励展示配置 | +| 送礼累积 | `SendGift` 同步调用 `wallet-service.DebitGift` 成功后,Room Cell 内更新热度、礼物榜和火箭进度 | +| 燃料满 | 当前等级进度封顶为阈值,锁定点火人、贡献第一、`box_id`、`open_at_ms` 和 UTC `reset_at_ms` | +| 溢出和倒计时送礼 | 当前等级溢出燃料作废;倒计时期间送礼不累加到下一级,也不改变点火人或贡献第一 | +| 到期发射 | `room-service` 通过 RocketMQ 延迟消息到 `open_at_ms` 唤醒;本地已加载 Cell 扫描 worker 仍作为兜底 | +| 奖励结算 | `room-service` 在发射命令内按配置加权抽取奖励,并调用 `wallet-service.GrantResourceGroup` 幂等发放 | +| 离房/下线 | `top1` 和 `igniter` 在倒计时开始时锁定;发射前离房或下线仍结算对应角色奖励 | +| 在房奖励 | 只发给发射命令执行时 Room Cell `OnlineUsers` 中的用户 | +| 播报 | `activity-service` 消费 `RoomRocketCountdownStarted`,按 `broadcast_scope` 发区域或全局播报 | | 事件分发 | `room_outbox` 先落 MySQL,再由 outbox worker 发布 RocketMQ;activity、notice、IM bridge 各自 consumer group 消费 | ## Non-Goals | 不做 | 原因 | | --- | --- | -| 客户端提交能量、奖励或中奖结果 | 能量和奖励必须来自服务端扣费、配置和确定性抽奖 | -| 只用 Redis 保存宝箱进度 | MySQL snapshot、command log 和 `room_outbox` 才是恢复来源 | -| activity-service 判断谁在房 | 房间 presence 和开箱快照必须由 Room Cell 产出 | -| activity-service 发放宝箱奖励 | 当前发奖在 `room-service` 开箱命令内调用 `wallet-service`,避免跨服务二次改写房间结算事实 | -| cron-service 到点开箱 | 到点唤醒属于房间事件消费和 Room Cell 命令触发,不是通用 cron 任务 | -| 倒计时期间继续排队能量 | 产品规则明确无效,不累加到下一个宝箱 | +| 客户端提交燃料、奖励或中奖结果 | 燃料和奖励必须来自服务端扣费、配置和确定性抽奖 | +| 只用 Redis 保存火箭进度 | MySQL snapshot、command log 和 `room_outbox` 才是恢复来源 | +| activity-service 判断谁在房 | 房间 presence 和发射快照必须由 Room Cell 产出 | +| activity-service 发放火箭奖励 | 当前发奖在 `room-service` 发射命令内调用 `wallet-service`,避免跨服务二次改写房间结算事实 | +| cron-service 到点发射 | 到点唤醒属于房间事件消费和 Room Cell 命令触发,不是通用 cron 任务 | +| 倒计时期间继续排队燃料 | 产品规则明确无效,不累加到下一个火箭 | ## 服务边界 | 模块 | 拥有 | 不拥有 | | --- | --- | --- | -| `room-service` | 宝箱进度、等级、状态机、点火人、贡献第一、开箱在线用户快照、抽奖结果、房间宝箱 IM outbox、RocketMQ 延迟开箱唤醒消费 | 用户完整资料、全局/区域播报群成员、钱包余额账本 | -| `wallet-service` | 送礼扣费、资源组发放、钱包账务、发放幂等 | 宝箱进度、中奖资格、房间 presence | -| `activity-service` | 满能量后区域/全局播报、成长值等房间事件派生消费 | Room Cell 状态、宝箱奖励结算 | +| `room-service` | 火箭进度、等级、状态机、点火人、贡献第一、发射在线用户快照、抽奖结果、房间火箭 IM outbox、RocketMQ 延迟发射唤醒消费 | 用户完整资料、全局/区域播报群成员、钱包余额账本 | +| `wallet-service` | 送礼扣费、资源组发放、钱包账务、发放幂等 | 火箭进度、中奖资格、房间 presence | +| `activity-service` | 燃料满后区域/全局播报、成长值等房间事件派生消费 | Room Cell 状态、火箭奖励结算 | | `notice-service` | 通过 room outbox/MQ 消费需要私信的房间事实,写自己的投递位点和死信 | 房间群系统消息、群成员控制、房间状态 | -| `gateway-service` | App HTTP envelope、鉴权、协议转换、调用 room gRPC | 能量、抽奖和发奖事实 | +| `gateway-service` | App HTTP envelope、鉴权、协议转换、调用 room gRPC | 燃料、抽奖和发奖事实 | | `server/admin` | 后台菜单、配置表单、审计、调用 owner service 管理接口 | 直接写 room/wallet/activity 业务表 | -宝箱进度和开箱必须经过 Room Cell 命令链路。MQ 只承担“到点唤醒”和“已提交事实分发”,不能成为宝箱状态 owner。 +火箭进度和发射必须经过 Room Cell 命令链路。MQ 只承担“到点唤醒”和“已提交事实分发”,不能成为火箭状态 owner。 ## 状态机 @@ -58,35 +58,35 @@ stateDiagram-v2 | 状态 | 语义 | | --- | --- | -| `idle` | 当前等级可累积能量 | +| `idle` | 当前等级可累积燃料 | | `countdown` | 当前等级已满,`open_at_ms` 已确定,本轮进度、点火人、贡献第一和配置版本锁定 | -| `opened` | 本轮已开箱,奖励已在命令内完成抽取和资源组发放请求 | +| `opened` | 本轮已发射,奖励已在命令内完成抽取和资源组发放请求 | | `exhausted` | 当天 7 级都已开启,等下一个 UTC 自然日 | -当前实现没有单独持久化 `round_id` 表。`box_id` 是单轮宝箱幂等和奖励选择的核心 ID,开箱命令 ID 固定为: +当前实现没有单独持久化 `round_id` 表。`box_id` 是单轮火箭幂等和奖励选择的核心 ID,发射命令 ID 固定为: ```text -cmd_room_treasure_open_ +cmd_room_rocket_open_ ``` -奖励发放命令 ID 固定由 `box_id + role + user_id + reward_item_id` 派生,重复开箱或 MQ 重投不会重复发放同一条奖励。 +奖励发放命令 ID 固定由 `box_id + role + user_id + reward_item_id` 派生,重复发射或 MQ 重投不会重复发放同一条奖励。 -## 能量规则 +## 燃料规则 | 规则 | 决策 | | --- | --- | -| 能量来源 | 默认使用 `DebitGiftResponse.gift_point_added`;后台可配置 `gift_id` 或 `gift_type_code` 的倍率、覆盖值和排除规则 | -| 生效条件 | wallet 扣费成功、Room Cell 提交 `SendGift`、礼物能量值大于 0 | -| 幂等 | 同一 `SendGift.command_id` 只能增加一次宝箱能量 | +| 燃料来源 | 默认使用 `DebitGiftResponse.gift_point_added`;后台可配置 `gift_id` 或 `gift_type_code` 的倍率、覆盖值和排除规则 | +| 生效条件 | wallet 扣费成功、Room Cell 提交 `SendGift`、礼物燃料值大于 0 | +| 幂等 | 同一 `SendGift.command_id` 只能增加一次火箭燃料 | | 点火人 | 第一笔让当前等级 `progress >= threshold` 的送礼用户 | -| 贡献第一 | 当前等级倒计时前累计有效能量最高用户 | -| 溢出能量 | 单笔礼物超过当前等级剩余阈值时,只计入补满当前等级所需能量,多余能量作废 | -| 倒计时送礼 | 当前等级已经满能量,继续送礼不再增加宝箱能量,也不会排队到下一等级 | -| 7 级后送礼 | 当天不再累计宝箱能量,礼物仍正常扣费、热度和榜单照常更新 | +| 贡献第一 | 当前等级倒计时前累计有效燃料最高用户 | +| 溢出燃料 | 单笔礼物超过当前等级剩余阈值时,只计入补满当前等级所需燃料,多余燃料作废 | +| 倒计时送礼 | 当前等级已经燃料满,继续送礼不再增加火箭燃料,也不会排队到下一等级 | +| 7 级后送礼 | 当天不再累计火箭燃料,礼物仍正常扣费、热度和榜单照常更新 | -无效能量只进入 `RoomTreasureProgressChanged` 的审计字段,不计入当前等级贡献、不计入下一等级进度、不改变点火人或贡献第一。 +无效燃料只进入 `RoomRocketProgressChanged` 的审计字段,不计入当前等级贡献、不计入下一等级进度、不改变点火人或贡献第一。 -## 开箱与 MQ 唤醒 +## 发射与 MQ 唤醒 ```mermaid sequenceDiagram @@ -101,16 +101,16 @@ sequenceDiagram C->>R: SendGift(command_id) R->>W: DebitGift(command_id) W-->>R: gift_point_added, heat_value - R->>R: Room Cell updates treasure + R->>R: Room Cell updates rocket R->>DB: command_log + snapshot + room_outbox - R-->>C: SendGiftResponse.treasure - R->>DB: outbox worker claims RoomTreasureCountdownStarted - R->>MQ: delayed RoomTreasureOpenDue(open_at_ms) + R-->>C: SendGiftResponse.rocket + R->>DB: outbox worker claims RoomRocketCountdownStarted + R->>MQ: delayed RoomRocketOpenDue(open_at_ms) R->>MQ: room_outbox event - MQ-->>A: RoomTreasureCountdownStarted + MQ-->>A: RoomRocketCountdownStarted A-->>IM: region/global broadcast - MQ-->>R: RoomTreasureOpenDue at open_at_ms - R->>R: OpenRoomTreasure command + MQ-->>R: RoomRocketOpenDue at open_at_ms + R->>R: OpenRoomRocket command R->>W: GrantResourceGroup per reward R->>DB: command_log + snapshot + opened/reward outbox ``` @@ -118,16 +118,16 @@ sequenceDiagram 关键规则: - 延迟消息只唤醒,不直接修改状态。 -- MQ 提前投递时,`room-service` 先检查 `open_at_ms`,未到点返回可重试错误,不写 no-op command log,避免污染开箱 `command_id`。 +- MQ 提前投递时,`room-service` 先检查 `open_at_ms`,未到点返回可重试错误,不写 no-op command log,避免污染发射 `command_id`。 - MQ 重复投递、outbox 重试或扫描 worker 同时触发时,`command_id` 和 wallet grant command 保证幂等。 -- 如果 `reset_at_ms` 已过,UTC 日界优先,昨天倒计时宝箱不再结算。 -- 本地 `room_treasure_open_scan_interval` 只扫描本节点已加载且仍持有 lease 的 Cell,是兜底,不解决未加载房间;未加载房间依赖 MQ delayed wakeup。 +- 如果 `reset_at_ms` 已过,UTC 日界优先,昨天倒计时火箭不再结算。 +- 本地 `room_rocket_open_scan_interval` 只扫描本节点已加载且仍持有 lease 的 Cell,是兜底,不解决未加载房间;未加载房间依赖 MQ delayed wakeup。 ## 奖励规则 | 奖励角色 | 资格 | | --- | --- | -| `in_room` | 开箱命令执行时 Room Cell `OnlineUsers` 内的每个用户 | +| `in_room` | 发射命令执行时 Room Cell `OnlineUsers` 内的每个用户 | | `top1` | 倒计时开始时锁定的贡献第一用户 | | `igniter` | 倒计时开始时锁定的点火人 | @@ -158,10 +158,10 @@ sequenceDiagram ## App 接口 -### 获取宝箱信息 +### 获取火箭信息 ```http -GET /api/v1/rooms/{room_id}/treasure +GET /api/v1/rooms/{room_id}/rocket Authorization: Bearer ``` @@ -207,29 +207,29 @@ Response `data` 核心字段: - `levels` 固定返回 7 个等级。 - `reset_at_ms` 是下一个 UTC 零点,不是用户本地零点。 -- 客户端只展示服务端返回的当前等级进度;不要自行把溢出能量展示到下一等级。 -- 当前没有单独的 App 领奖接口,奖励自动发放,最近一次开箱奖励通过 `state.last_rewards` 展示。 +- 客户端只展示服务端返回的当前等级进度;不要自行把溢出燃料展示到下一等级。 +- 当前没有单独的 App 领奖接口,奖励自动发放,最近一次发射奖励通过 `state.last_rewards` 展示。 ### SendGift 响应 -`SendGiftResponse` 已携带 `treasure` 状态,送礼人成功送礼后可立即更新宝箱 UI,不必等待 IM。 +`SendGiftResponse` 已携带 `rocket` 状态,送礼人成功送礼后可立即更新火箭 UI,不必等待 IM。 ## 房间 IM 事件 -房间内宝箱 IM 走腾讯云房间群 `TIMCustomElem`,由 room outbox 事件转换。当前事件类型: +房间内火箭 IM 走腾讯云房间群 `TIMCustomElem`,由 room outbox 事件转换。当前事件类型: | Event | 客户端 `event_type` | 用途 | | --- | --- | --- | -| `RoomTreasureProgressChanged` | `room_treasure_progress_changed` | 宝箱进度增加 | -| `RoomTreasureCountdownStarted` | `room_treasure_countdown_started` | 满能量进入倒计时 | -| `RoomTreasureOpened` | `room_treasure_opened` | 宝箱打开并给出公开奖励摘要 | -| `RoomTreasureRewardGranted` | `room_treasure_reward_granted` | 发奖结果事件,包含奖励列表 | +| `RoomRocketProgressChanged` | `room_rocket_progress_changed` | 火箭进度增加 | +| `RoomRocketCountdownStarted` | `room_rocket_countdown_started` | 燃料满进入倒计时 | +| `RoomRocketOpened` | `room_rocket_opened` | 火箭打开并给出公开奖励摘要 | +| `RoomRocketRewardGranted` | `room_rocket_reward_granted` | 发奖结果事件,包含奖励列表 | ### Progress Changed ```json { - "event_type": "room_treasure_progress_changed", + "event_type": "room_rocket_progress_changed", "box_id": "box_xxx", "level": 3, "added_energy": 500, @@ -248,7 +248,7 @@ Response `data` 核心字段: ```json { - "event_type": "room_treasure_countdown_started", + "event_type": "room_rocket_countdown_started", "box_id": "box_xxx", "level": 3, "current_progress": 10000, @@ -265,7 +265,7 @@ Response `data` 核心字段: ```json { - "event_type": "room_treasure_opened", + "event_type": "room_rocket_opened", "box_id": "box_xxx", "level": 3, "next_level": 4, @@ -276,23 +276,23 @@ Response `data` 核心字段: } ``` -群 IM 承载公开摘要。后续如要做个人中奖私信或消息 Tab,应由 `notice-service` 或 inbox consumer 消费 `RoomTreasureRewardGranted`,不要让 `room-service` 同步投递私信。 +群 IM 承载公开摘要。后续如要做个人中奖私信或消息 Tab,应由 `notice-service` 或 inbox consumer 消费 `RoomRocketRewardGranted`,不要让 `room-service` 同步投递私信。 ## 后台配置 -后台配置带 `config_version`。倒计时开始后,当前宝箱的 `box_id`、等级、进度、`open_at_ms`、点火人和贡献第一不再因配置修改而变化;当前实现开箱时读取最新启用配置的奖励池,因此运营在倒计时窗口内修改奖励配置要按发布窗口处理。 +后台配置带 `config_version`。倒计时开始后,当前火箭的 `box_id`、等级、进度、`open_at_ms`、点火人和贡献第一不再因配置修改而变化;当前实现发射时读取最新启用配置的奖励池,因此运营在倒计时窗口内修改奖励配置要按发布窗口处理。 | 字段 | 含义 | | --- | --- | | `enabled` | 总开关 | | `energy_source` | 默认 `gift_point_added` | -| `open_delay_ms` | 满能量到开箱的倒计时 | -| `broadcast_enabled` | 是否满能量后播报 | +| `open_delay_ms` | 燃料满到发射的倒计时 | +| `broadcast_enabled` | 是否燃料满后播报 | | `broadcast_scope` | `none/region/global` | -| `broadcast_delay_ms` | 满能量后多久发播报,当前代码写入配置和读模型,实际倒计时事件立即进入 room outbox | +| `broadcast_delay_ms` | 燃料满后多久发播报,当前代码写入配置和读模型,实际倒计时事件立即进入 room outbox | | `reward_stack_policy` | `allow_stack` 或 `priority_only` | | `levels` | 7 个等级配置,包含阈值、物料 URL 和三类奖励池 | -| `gift_energy_rules` | gift_id 或 gift_type_code 的能量倍率、覆盖值和排除规则 | +| `gift_energy_rules` | gift_id 或 gift_type_code 的燃料倍率、覆盖值和排除规则 | | `updated_by_admin_id` | 审计字段 | 奖励池保存时应校验: @@ -311,7 +311,7 @@ Response `data` 核心字段: | Topic | Producer | Consumer | | --- | --- | --- | | `hyapp_room_outbox` | `room-service` outbox worker | `activity-service`、`notice-service`、`room-service` IM bridge、后续 push/inbox | -| `hyapp_room_treasure_open` | `room-service` treasure open scheduler | `room-service` treasure open consumer | +| `hyapp_room_rocket_open` | `room-service` rocket open scheduler | `room-service` rocket open consumer | 推荐线上配置: @@ -325,9 +325,9 @@ rocketmq: room_outbox: enabled: true topic: "hyapp_room_outbox" - treasure_open: + rocket_open: enabled: true - topic: "hyapp_room_treasure_open" + topic: "hyapp_room_rocket_open" ``` `publish_mode`: @@ -346,7 +346,7 @@ rocketmq: | 重置时间 | 每天 UTC `00:00:00.000` | | 时间区间 | `[day_start_ms, next_day_start_ms)` | | idle | 到达新 UTC 日时回到 level 1,清空进度和贡献 | -| countdown | 如果 `open_at_ms` 跨过 `reset_at_ms`,UTC 日界优先,旧宝箱不再结算 | +| countdown | 如果 `open_at_ms` 跨过 `reset_at_ms`,UTC 日界优先,旧火箭不再结算 | | exhausted | 下一个 UTC 日恢复 level 1 | 必须覆盖 UTC 边界测试:`day_start_ms`、`next_day_start_ms - 1`、`next_day_start_ms`。不要重新引入 `time.Local`、`task_timezone` 或客户端时区。 @@ -355,14 +355,14 @@ rocketmq: | 场景 | 验收 | | --- | --- | -| 送礼成功 | wallet 扣费成功,Room Cell 进度增加,`SendGiftResponse.treasure` 返回最新状态 | -| 单笔溢出 | 进度封顶当前阈值,溢出能量作废,不进入下一等级 | -| 倒计时送礼 | 礼物正常扣费和加热度,但宝箱进度、点火人、贡献第一不变化 | -| 满能量 | 写 `RoomTreasureCountdownStarted`,outbox worker 安排 RocketMQ delayed open | -| 提前延迟消息 | 不写开箱 no-op command log,MQ 后续可重试 | -| 到点开箱 | 即使房间未加载,MQ 唤醒后 room-service 恢复 Room Cell 并开箱 | +| 送礼成功 | wallet 扣费成功,Room Cell 进度增加,`SendGiftResponse.rocket` 返回最新状态 | +| 单笔溢出 | 进度封顶当前阈值,溢出燃料作废,不进入下一等级 | +| 倒计时送礼 | 礼物正常扣费和加热度,但火箭进度、点火人、贡献第一不变化 | +| 燃料满 | 写 `RoomRocketCountdownStarted`,outbox worker 安排 RocketMQ delayed open | +| 提前延迟消息 | 不写发射 no-op command log,MQ 后续可重试 | +| 到点发射 | 即使房间未加载,MQ 唤醒后 room-service 恢复 Room Cell 并发射 | | top1/igniter 离房 | 仍发角色奖励 | -| 在房奖励 | 只发开箱瞬间在线用户 | +| 在房奖励 | 只发发射瞬间在线用户 | | UTC 重置 | 到达 UTC 零点后进度回到 level 1,跨日倒计时不结算 | | MQ/outbox 重投 | `event_id`、`box_id`、wallet grant command 保证幂等 | @@ -370,9 +370,9 @@ rocketmq: | 模块 | 路径 | | --- | --- | -| 宝箱状态机和结算 | `services/room-service/internal/room/service/room_treasure.go` | -| MQ delayed open | `services/room-service/internal/room/service/room_treasure_mq.go` | +| 火箭状态机和结算 | `services/room-service/internal/room/service/room_rocket.go` | +| MQ delayed open | `services/room-service/internal/room/service/room_rocket_mq.go` | | outbox worker | `services/room-service/internal/room/service/outbox_worker.go` | | RocketMQ 适配 | `pkg/rocketmqx`、`pkg/roommq`、`services/room-service/internal/integration/rocketmq_outbox.go` | | App HTTP | `services/gateway-service/internal/transport/http/roomapi` | -| 后台配置 | `server/admin/internal/modules/roomtreasure` | +| 后台配置 | `server/admin/internal/modules/roomrocket` | diff --git a/pkg/roommq/messages.go b/pkg/roommq/messages.go index ea2e0d90..b06e1ef7 100644 --- a/pkg/roommq/messages.go +++ b/pkg/roommq/messages.go @@ -11,10 +11,10 @@ import ( const ( MessageTypeRoomOutboxEvent = "room_outbox_event" - MessageTypeRoomTreasureOpenDue = "room_treasure_open_due" + MessageTypeRoomRocketLaunchDue = "room_rocket_launch_due" TagRoomOutboxEvent = "room_outbox_event" - TagRoomTreasureOpenDue = "room_treasure_open_due" + TagRoomRocketLaunchDue = "room_rocket_launch_due" ) // RoomOutboxMessage is the MQ representation of one durable room_outbox fact. @@ -29,14 +29,14 @@ type RoomOutboxMessage struct { Envelope []byte `json:"envelope"` } -// RoomTreasureOpenDueMessage wakes room-service at the configured open_at_ms. -type RoomTreasureOpenDueMessage struct { +// RoomRocketLaunchDueMessage wakes room-service at the configured launch_at_ms. +type RoomRocketLaunchDueMessage struct { MessageType string `json:"message_type"` AppCode string `json:"app_code"` RoomID string `json:"room_id"` - BoxID string `json:"box_id"` + RocketID string `json:"rocket_id"` Level int32 `json:"level"` - OpenAtMS int64 `json:"open_at_ms"` + LaunchAtMS int64 `json:"launch_at_ms"` ResetAtMS int64 `json:"reset_at_ms"` CommandID string `json:"command_id"` } @@ -81,26 +81,26 @@ func DecodeRoomOutboxMessage(body []byte) (*roomeventsv1.EventEnvelope, RoomOutb return &envelope, message, nil } -// EncodeRoomTreasureOpenDueMessage serializes an open wakeup command. -func EncodeRoomTreasureOpenDueMessage(message RoomTreasureOpenDueMessage) ([]byte, error) { - message.MessageType = MessageTypeRoomTreasureOpenDue - if message.AppCode == "" || message.RoomID == "" || message.BoxID == "" || message.Level <= 0 || message.OpenAtMS <= 0 { - return nil, errors.New("room treasure open due message is incomplete") +// EncodeRoomRocketLaunchDueMessage serializes a launch wakeup command. +func EncodeRoomRocketLaunchDueMessage(message RoomRocketLaunchDueMessage) ([]byte, error) { + message.MessageType = MessageTypeRoomRocketLaunchDue + if message.AppCode == "" || message.RoomID == "" || message.RocketID == "" || message.Level <= 0 || message.LaunchAtMS <= 0 { + return nil, errors.New("room rocket launch due message is incomplete") } return json.Marshal(message) } -// DecodeRoomTreasureOpenDueMessage validates an open wakeup body. -func DecodeRoomTreasureOpenDueMessage(body []byte) (RoomTreasureOpenDueMessage, error) { - var message RoomTreasureOpenDueMessage +// DecodeRoomRocketLaunchDueMessage validates a launch wakeup body. +func DecodeRoomRocketLaunchDueMessage(body []byte) (RoomRocketLaunchDueMessage, error) { + var message RoomRocketLaunchDueMessage if err := json.Unmarshal(body, &message); err != nil { - return RoomTreasureOpenDueMessage{}, err + return RoomRocketLaunchDueMessage{}, err } - if message.MessageType != MessageTypeRoomTreasureOpenDue { - return RoomTreasureOpenDueMessage{}, errors.New("unexpected room treasure message_type") + if message.MessageType != MessageTypeRoomRocketLaunchDue { + return RoomRocketLaunchDueMessage{}, errors.New("unexpected room rocket message_type") } - if message.AppCode == "" || message.RoomID == "" || message.BoxID == "" || message.Level <= 0 || message.OpenAtMS <= 0 { - return RoomTreasureOpenDueMessage{}, errors.New("room treasure open due message is incomplete") + if message.AppCode == "" || message.RoomID == "" || message.RocketID == "" || message.Level <= 0 || message.LaunchAtMS <= 0 { + return RoomRocketLaunchDueMessage{}, errors.New("room rocket launch due message is incomplete") } return message, nil } diff --git a/pkg/roommq/messages_test.go b/pkg/roommq/messages_test.go index b2f33068..5ab67f7c 100644 --- a/pkg/roommq/messages_test.go +++ b/pkg/roommq/messages_test.go @@ -8,14 +8,14 @@ import ( ) func TestRoomOutboxMessageRoundTrip(t *testing.T) { - body, err := proto.Marshal(&roomeventsv1.RoomTreasureCountdownStarted{BoxId: "box-1", Level: 2, OpenAtMs: 12345}) + body, err := proto.Marshal(&roomeventsv1.RoomRocketIgnited{RocketId: "rocket-1", Level: 2, LaunchAtMs: 12345}) if err != nil { t.Fatalf("marshal body: %v", err) } envelope := &roomeventsv1.EventEnvelope{ AppCode: "default", EventId: "evt-1", - EventType: "RoomTreasureCountdownStarted", + EventType: "RoomRocketIgnited", RoomId: "room-1", RoomVersion: 9, OccurredAtMs: 12300, @@ -34,24 +34,24 @@ func TestRoomOutboxMessageRoundTrip(t *testing.T) { } } -func TestRoomTreasureOpenDueRoundTrip(t *testing.T) { - encoded, err := EncodeRoomTreasureOpenDueMessage(RoomTreasureOpenDueMessage{ - AppCode: "default", - RoomID: "room-1", - BoxID: "box-1", - Level: 1, - OpenAtMS: 12345, - ResetAtMS: 99999, - CommandID: "cmd_room_treasure_open_box-1", +func TestRoomRocketLaunchDueRoundTrip(t *testing.T) { + encoded, err := EncodeRoomRocketLaunchDueMessage(RoomRocketLaunchDueMessage{ + AppCode: "default", + RoomID: "room-1", + RocketID: "rocket-1", + Level: 1, + LaunchAtMS: 12345, + ResetAtMS: 99999, + CommandID: "cmd_room_rocket_launch_rocket-1", }) if err != nil { t.Fatalf("encode: %v", err) } - decoded, err := DecodeRoomTreasureOpenDueMessage(encoded) + decoded, err := DecodeRoomRocketLaunchDueMessage(encoded) if err != nil { t.Fatalf("decode: %v", err) } - if decoded.MessageType != MessageTypeRoomTreasureOpenDue || decoded.BoxID != "box-1" || decoded.OpenAtMS != 12345 { + if decoded.MessageType != MessageTypeRoomRocketLaunchDue || decoded.RocketID != "rocket-1" || decoded.LaunchAtMS != 12345 { t.Fatalf("unexpected decoded message: %#v", decoded) } } diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index c7912c59..b3844776 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -53,7 +53,7 @@ import ( reportmodule "hyapp-admin-server/internal/modules/report" resourcemodule "hyapp-admin-server/internal/modules/resource" roomadminmodule "hyapp-admin-server/internal/modules/roomadmin" - roomtreasuremodule "hyapp-admin-server/internal/modules/roomtreasure" + roomrocketmodule "hyapp-admin-server/internal/modules/roomrocket" searchmodule "hyapp-admin-server/internal/modules/search" sevendaycheckinmodule "hyapp-admin-server/internal/modules/sevendaycheckin" teamsalarypolicymodule "hyapp-admin-server/internal/modules/teamsalarypolicy" @@ -247,7 +247,7 @@ func main() { RegionBlock: regionblockmodule.New(userDB, auditHandler), Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, auditHandler), RoomAdmin: roomadminmodule.New(userDB, roomClient, auditHandler), - RoomTreasure: roomtreasuremodule.New(roomClient, auditHandler), + RoomRocket: roomrocketmodule.New(roomClient, auditHandler), Search: searchmodule.New(store), SevenDayCheckIn: sevendaycheckinmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), TeamSalaryPolicy: teamsalarypolicymodule.New(store, auditHandler), diff --git a/server/admin/internal/integration/roomclient/client.go b/server/admin/internal/integration/roomclient/client.go index 2b486a30..a4b1a4a7 100644 --- a/server/admin/internal/integration/roomclient/client.go +++ b/server/admin/internal/integration/roomclient/client.go @@ -17,8 +17,8 @@ type Client interface { GetRoom(ctx context.Context, req GetRoomRequest) (*Room, error) UpdateRoom(ctx context.Context, req UpdateRoomRequest) (*CloseRoomResult, error) DeleteRoom(ctx context.Context, req DeleteRoomRequest) (*CloseRoomResult, error) - GetRoomTreasureConfig(ctx context.Context) (RoomTreasureConfig, error) - UpdateRoomTreasureConfig(ctx context.Context, req UpdateRoomTreasureConfigRequest) (RoomTreasureConfig, error) + GetRoomRocketConfig(ctx context.Context) (RoomRocketConfig, error) + UpdateRoomRocketConfig(ctx context.Context, req UpdateRoomRocketConfigRequest) (RoomRocketConfig, error) GetRoomSeatConfig(ctx context.Context) (RoomSeatConfig, error) UpdateRoomSeatConfig(ctx context.Context, req UpdateRoomSeatConfigRequest) (RoomSeatConfig, error) ListRoomPins(ctx context.Context, req ListRoomPinsRequest) (ListRoomPinsResult, error) @@ -93,36 +93,36 @@ type Room struct { UpdatedAtMS int64 } -type RoomTreasureConfig struct { +type RoomRocketConfig struct { AppCode string Enabled bool ConfigVersion int64 - EnergySource string - OpenDelayMS int64 + FuelSource string + LaunchDelayMS int64 BroadcastEnabled bool BroadcastScope string BroadcastDelayMS int64 RewardStackPolicy string - Levels []RoomTreasureLevelConfig - GiftEnergyRules []GiftEnergyRuleConfig + Levels []RoomRocketLevelConfig + GiftFuelRules []GiftFuelRuleConfig UpdatedByAdminID int64 CreatedAtMS int64 UpdatedAtMS int64 } -type RoomTreasureLevelConfig struct { - Level int32 - EnergyThreshold int64 - CoverURL string - AnimationURL string - OpeningAnimationURL string - OpenedImageURL string - InRoomRewards []RoomTreasureRewardItem - Top1Rewards []RoomTreasureRewardItem - IgniterRewards []RoomTreasureRewardItem +type RoomRocketLevelConfig struct { + Level int32 + FuelThreshold int64 + CoverURL string + AnimationURL string + LaunchAnimationURL string + LaunchedImageURL string + InRoomRewards []RoomRocketRewardItem + Top1Rewards []RoomRocketRewardItem + IgniterRewards []RoomRocketRewardItem } -type RoomTreasureRewardItem struct { +type RoomRocketRewardItem struct { RewardItemID string ResourceGroupID int64 Weight int64 @@ -130,17 +130,17 @@ type RoomTreasureRewardItem struct { IconURL string } -type GiftEnergyRuleConfig struct { +type GiftFuelRuleConfig struct { RuleID string GiftID string GiftTypeCode string MultiplierPPM int64 - FixedEnergy int64 + FixedFuel int64 Excluded bool } -type UpdateRoomTreasureConfigRequest struct { - Config RoomTreasureConfig +type UpdateRoomRocketConfigRequest struct { + Config RoomRocketConfig AdminID int64 } @@ -301,26 +301,26 @@ func (c *GRPCClient) DeleteRoom(ctx context.Context, req DeleteRoomRequest) (*Cl return closeRoomResultFromCommand(resp.GetResult(), resp.GetRoom()), nil } -func (c *GRPCClient) GetRoomTreasureConfig(ctx context.Context) (RoomTreasureConfig, error) { - resp, err := c.queryClient.AdminGetRoomTreasureConfig(ctx, &roomv1.AdminGetRoomTreasureConfigRequest{ - Meta: requestMeta(ctx, "", 0, "admin-get-room-treasure-config"), +func (c *GRPCClient) GetRoomRocketConfig(ctx context.Context) (RoomRocketConfig, error) { + resp, err := c.queryClient.AdminGetRoomRocketConfig(ctx, &roomv1.AdminGetRoomRocketConfigRequest{ + Meta: requestMeta(ctx, "", 0, "admin-get-room-rocket-config"), }) if err != nil { - return RoomTreasureConfig{}, err + return RoomRocketConfig{}, err } - return roomTreasureConfigFromProto(resp.GetConfig()), nil + return roomRocketConfigFromProto(resp.GetConfig()), nil } -func (c *GRPCClient) UpdateRoomTreasureConfig(ctx context.Context, req UpdateRoomTreasureConfigRequest) (RoomTreasureConfig, error) { - resp, err := c.client.AdminUpdateRoomTreasureConfig(ctx, &roomv1.AdminUpdateRoomTreasureConfigRequest{ - Meta: requestMeta(ctx, "", req.AdminID, "admin-update-room-treasure-config"), - Config: roomTreasureConfigToProto(req.Config), +func (c *GRPCClient) UpdateRoomRocketConfig(ctx context.Context, req UpdateRoomRocketConfigRequest) (RoomRocketConfig, error) { + resp, err := c.client.AdminUpdateRoomRocketConfig(ctx, &roomv1.AdminUpdateRoomRocketConfigRequest{ + Meta: requestMeta(ctx, "", req.AdminID, "admin-update-room-rocket-config"), + Config: roomRocketConfigToProto(req.Config), AdminId: req.AdminID, }) if err != nil { - return RoomTreasureConfig{}, err + return RoomRocketConfig{}, err } - return roomTreasureConfigFromProto(resp.GetConfig()), nil + return roomRocketConfigFromProto(resp.GetConfig()), nil } func (c *GRPCClient) GetRoomSeatConfig(ctx context.Context) (RoomSeatConfig, error) { @@ -483,22 +483,22 @@ func roomFromProto(item *roomv1.AdminRoomListItem) Room { } } -func roomTreasureConfigFromProto(input *roomv1.AdminRoomTreasureConfig) RoomTreasureConfig { +func roomRocketConfigFromProto(input *roomv1.AdminRoomRocketConfig) RoomRocketConfig { if input == nil { - return RoomTreasureConfig{} + return RoomRocketConfig{} } - return RoomTreasureConfig{ + return RoomRocketConfig{ AppCode: input.GetAppCode(), Enabled: input.GetEnabled(), ConfigVersion: input.GetConfigVersion(), - EnergySource: input.GetEnergySource(), - OpenDelayMS: input.GetOpenDelayMs(), + FuelSource: input.GetFuelSource(), + LaunchDelayMS: input.GetLaunchDelayMs(), BroadcastEnabled: input.GetBroadcastEnabled(), BroadcastScope: input.GetBroadcastScope(), BroadcastDelayMS: input.GetBroadcastDelayMs(), RewardStackPolicy: input.GetRewardStackPolicy(), - Levels: roomTreasureLevelsFromProto(input.GetLevels()), - GiftEnergyRules: roomTreasureEnergyRulesFromProto(input.GetGiftEnergyRules()), + Levels: roomRocketLevelsFromProto(input.GetLevels()), + GiftFuelRules: roomRocketFuelRulesFromProto(input.GetGiftFuelRules()), UpdatedByAdminID: input.GetUpdatedByAdminId(), CreatedAtMS: input.GetCreatedAtMs(), UpdatedAtMS: input.GetUpdatedAtMs(), @@ -547,66 +547,66 @@ func roomPinFromProto(input *roomv1.AdminRoomPin) RoomPin { } } -func roomTreasureConfigToProto(input RoomTreasureConfig) *roomv1.AdminRoomTreasureConfig { - return &roomv1.AdminRoomTreasureConfig{ +func roomRocketConfigToProto(input RoomRocketConfig) *roomv1.AdminRoomRocketConfig { + return &roomv1.AdminRoomRocketConfig{ Enabled: input.Enabled, - EnergySource: input.EnergySource, - OpenDelayMs: input.OpenDelayMS, + FuelSource: input.FuelSource, + LaunchDelayMs: input.LaunchDelayMS, BroadcastEnabled: input.BroadcastEnabled, BroadcastScope: input.BroadcastScope, BroadcastDelayMs: input.BroadcastDelayMS, RewardStackPolicy: input.RewardStackPolicy, - Levels: roomTreasureLevelsToProto(input.Levels), - GiftEnergyRules: roomTreasureEnergyRulesToProto(input.GiftEnergyRules), + Levels: roomRocketLevelsToProto(input.Levels), + GiftFuelRules: roomRocketFuelRulesToProto(input.GiftFuelRules), } } -func roomTreasureLevelsFromProto(input []*roomv1.RoomTreasureLevel) []RoomTreasureLevelConfig { - out := make([]RoomTreasureLevelConfig, 0, len(input)) +func roomRocketLevelsFromProto(input []*roomv1.RoomRocketLevel) []RoomRocketLevelConfig { + out := make([]RoomRocketLevelConfig, 0, len(input)) for _, level := range input { if level == nil { continue } - out = append(out, RoomTreasureLevelConfig{ - Level: level.GetLevel(), - EnergyThreshold: level.GetEnergyThreshold(), - CoverURL: level.GetCoverUrl(), - AnimationURL: level.GetAnimationUrl(), - OpeningAnimationURL: level.GetOpeningAnimationUrl(), - OpenedImageURL: level.GetOpenedImageUrl(), - InRoomRewards: roomTreasureRewardsFromProto(level.GetInRoomRewards()), - Top1Rewards: roomTreasureRewardsFromProto(level.GetTop1Rewards()), - IgniterRewards: roomTreasureRewardsFromProto(level.GetIgniterRewards()), + out = append(out, RoomRocketLevelConfig{ + Level: level.GetLevel(), + FuelThreshold: level.GetFuelThreshold(), + CoverURL: level.GetCoverUrl(), + AnimationURL: level.GetAnimationUrl(), + LaunchAnimationURL: level.GetLaunchAnimationUrl(), + LaunchedImageURL: level.GetLaunchedImageUrl(), + InRoomRewards: roomRocketRewardsFromProto(level.GetInRoomRewards()), + Top1Rewards: roomRocketRewardsFromProto(level.GetTop1Rewards()), + IgniterRewards: roomRocketRewardsFromProto(level.GetIgniterRewards()), }) } return out } -func roomTreasureLevelsToProto(input []RoomTreasureLevelConfig) []*roomv1.RoomTreasureLevel { - out := make([]*roomv1.RoomTreasureLevel, 0, len(input)) +func roomRocketLevelsToProto(input []RoomRocketLevelConfig) []*roomv1.RoomRocketLevel { + out := make([]*roomv1.RoomRocketLevel, 0, len(input)) for _, level := range input { - out = append(out, &roomv1.RoomTreasureLevel{ - Level: level.Level, - EnergyThreshold: level.EnergyThreshold, - CoverUrl: level.CoverURL, - AnimationUrl: level.AnimationURL, - OpeningAnimationUrl: level.OpeningAnimationURL, - OpenedImageUrl: level.OpenedImageURL, - InRoomRewards: roomTreasureRewardsToProto(level.InRoomRewards), - Top1Rewards: roomTreasureRewardsToProto(level.Top1Rewards), - IgniterRewards: roomTreasureRewardsToProto(level.IgniterRewards), + out = append(out, &roomv1.RoomRocketLevel{ + Level: level.Level, + FuelThreshold: level.FuelThreshold, + CoverUrl: level.CoverURL, + AnimationUrl: level.AnimationURL, + LaunchAnimationUrl: level.LaunchAnimationURL, + LaunchedImageUrl: level.LaunchedImageURL, + InRoomRewards: roomRocketRewardsToProto(level.InRoomRewards), + Top1Rewards: roomRocketRewardsToProto(level.Top1Rewards), + IgniterRewards: roomRocketRewardsToProto(level.IgniterRewards), }) } return out } -func roomTreasureRewardsFromProto(input []*roomv1.RoomTreasureRewardItem) []RoomTreasureRewardItem { - out := make([]RoomTreasureRewardItem, 0, len(input)) +func roomRocketRewardsFromProto(input []*roomv1.RoomRocketRewardItem) []RoomRocketRewardItem { + out := make([]RoomRocketRewardItem, 0, len(input)) for _, reward := range input { if reward == nil { continue } - out = append(out, RoomTreasureRewardItem{ + out = append(out, RoomRocketRewardItem{ RewardItemID: reward.GetRewardItemId(), ResourceGroupID: reward.GetResourceGroupId(), Weight: reward.GetWeight(), @@ -617,10 +617,10 @@ func roomTreasureRewardsFromProto(input []*roomv1.RoomTreasureRewardItem) []Room return out } -func roomTreasureRewardsToProto(input []RoomTreasureRewardItem) []*roomv1.RoomTreasureRewardItem { - out := make([]*roomv1.RoomTreasureRewardItem, 0, len(input)) +func roomRocketRewardsToProto(input []RoomRocketRewardItem) []*roomv1.RoomRocketRewardItem { + out := make([]*roomv1.RoomRocketRewardItem, 0, len(input)) for _, reward := range input { - out = append(out, &roomv1.RoomTreasureRewardItem{ + out = append(out, &roomv1.RoomRocketRewardItem{ RewardItemId: reward.RewardItemID, ResourceGroupId: reward.ResourceGroupID, Weight: reward.Weight, @@ -631,33 +631,33 @@ func roomTreasureRewardsToProto(input []RoomTreasureRewardItem) []*roomv1.RoomTr return out } -func roomTreasureEnergyRulesFromProto(input []*roomv1.RoomTreasureGiftEnergyRule) []GiftEnergyRuleConfig { - out := make([]GiftEnergyRuleConfig, 0, len(input)) +func roomRocketFuelRulesFromProto(input []*roomv1.RoomRocketGiftFuelRule) []GiftFuelRuleConfig { + out := make([]GiftFuelRuleConfig, 0, len(input)) for _, rule := range input { if rule == nil { continue } - out = append(out, GiftEnergyRuleConfig{ + out = append(out, GiftFuelRuleConfig{ RuleID: rule.GetRuleId(), GiftID: rule.GetGiftId(), GiftTypeCode: rule.GetGiftTypeCode(), MultiplierPPM: rule.GetMultiplierPpm(), - FixedEnergy: rule.GetFixedEnergy(), + FixedFuel: rule.GetFixedFuel(), Excluded: rule.GetExcluded(), }) } return out } -func roomTreasureEnergyRulesToProto(input []GiftEnergyRuleConfig) []*roomv1.RoomTreasureGiftEnergyRule { - out := make([]*roomv1.RoomTreasureGiftEnergyRule, 0, len(input)) +func roomRocketFuelRulesToProto(input []GiftFuelRuleConfig) []*roomv1.RoomRocketGiftFuelRule { + out := make([]*roomv1.RoomRocketGiftFuelRule, 0, len(input)) for _, rule := range input { - out = append(out, &roomv1.RoomTreasureGiftEnergyRule{ + out = append(out, &roomv1.RoomRocketGiftFuelRule{ RuleId: rule.RuleID, GiftId: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPpm: rule.MultiplierPPM, - FixedEnergy: rule.FixedEnergy, + FixedFuel: rule.FixedFuel, Excluded: rule.Excluded, }) } diff --git a/server/admin/internal/modules/coinledger/dto.go b/server/admin/internal/modules/coinledger/dto.go index a2b31c56..6d0629c2 100644 --- a/server/admin/internal/modules/coinledger/dto.go +++ b/server/admin/internal/modules/coinledger/dto.go @@ -25,6 +25,23 @@ type coinLedgerEntryDTO struct { CreatedAtMS int64 `json:"createdAtMs"` } +type coinSellerLedgerDTO struct { + EntryID int64 `json:"entryId"` + TransactionID string `json:"transactionId"` + CommandID string `json:"commandId"` + LedgerType string `json:"ledgerType"` + BizType string `json:"bizType"` + Seller coinLedgerUserDTO `json:"seller"` + Receiver coinLedgerUserDTO `json:"receiver"` + Amount int64 `json:"amount"` + Direction string `json:"direction"` + AvailableDelta int64 `json:"availableDelta"` + SellerBalanceAfter int64 `json:"sellerBalanceAfter"` + CounterpartyUserID string `json:"counterpartyUserId"` + Metadata map[string]any `json:"metadata"` + CreatedAtMS int64 `json:"createdAtMs"` +} + type coinAdjustmentOperatorDTO struct { AdminID string `json:"adminId"` Username string `json:"username"` diff --git a/server/admin/internal/modules/coinledger/handler.go b/server/admin/internal/modules/coinledger/handler.go index 3001197f..75231536 100644 --- a/server/admin/internal/modules/coinledger/handler.go +++ b/server/admin/internal/modules/coinledger/handler.go @@ -38,6 +38,23 @@ func (h *Handler) ListCoinLedger(c *gin.Context) { response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total}) } +func (h *Handler) ListCoinSellerLedger(c *gin.Context) { + query, ok := parseCoinSellerLedgerQuery(c) + if !ok { + return + } + items, total, err := h.service.ListCoinSellerLedger(c.Request.Context(), appctx.FromContext(c.Request.Context()), query) + if err != nil { + if errors.Is(err, errInvalidCoinSellerLedgerType) { + response.BadRequest(c, "流水类型不正确") + return + } + response.ServerError(c, "获取币商流水失败") + return + } + response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total}) +} + func (h *Handler) ListCoinAdjustments(c *gin.Context) { query, ok := parseListQuery(c) if !ok { @@ -115,6 +132,48 @@ func parseListQuery(c *gin.Context) (listQuery, bool) { }), true } +func parseCoinSellerLedgerQuery(c *gin.Context) (coinSellerLedgerQuery, bool) { + options := shared.ListOptions(c) + // 行内抽屉传 seller_user_id 做精确锁定,二级页面不传该字段时才走 seller_keyword 的币商本人搜索; + // 两个入口共用同一个查询结构,可以保证页面筛选和行内抽屉使用完全一致的流水类型、时间边界和分页语义。 + sellerUserID, ok := optionalInt64(c, "seller_user_id", "sellerUserId") + if !ok { + response.BadRequest(c, "币商 ID 不正确") + return coinSellerLedgerQuery{}, false + } + startAtMS, ok := optionalInt64(c, "start_at_ms", "startAtMs") + if !ok { + response.BadRequest(c, "开始时间不正确") + return coinSellerLedgerQuery{}, false + } + endAtMS, ok := optionalInt64(c, "end_at_ms", "endAtMs") + if !ok { + response.BadRequest(c, "结束时间不正确") + return coinSellerLedgerQuery{}, false + } + if startAtMS > 0 && endAtMS > 0 && startAtMS >= endAtMS { + response.BadRequest(c, "时间区间不正确") + return coinSellerLedgerQuery{}, false + } + + // 列表时间统一保持 [start_at_ms, end_at_ms),开始毫秒包含、结束毫秒不包含,避免相邻筛选区间重复展示同一条分录; + // 非法流水类型在入口层直接拒绝,避免 SQL 拼出无意义类型条件,也让调用方尽早拿到明确的 400 错误。 + query := normalizeCoinSellerLedgerQuery(coinSellerLedgerQuery{ + Page: options.Page, + PageSize: options.PageSize, + SellerUserID: sellerUserID, + SellerKeyword: firstQuery(c, "seller_keyword", "sellerKeyword", "keyword"), + LedgerType: firstQuery(c, "ledger_type", "ledgerType"), + StartAtMS: startAtMS, + EndAtMS: endAtMS, + }) + if _, err := coinSellerLedgerBizTypes(query.LedgerType); err != nil { + response.BadRequest(c, "流水类型不正确") + return coinSellerLedgerQuery{}, false + } + return query, true +} + func optionalInt64(c *gin.Context, keys ...string) (int64, bool) { value := strings.TrimSpace(firstQuery(c, keys...)) if value == "" { diff --git a/server/admin/internal/modules/coinledger/request.go b/server/admin/internal/modules/coinledger/request.go index c8818421..7d5e9759 100644 --- a/server/admin/internal/modules/coinledger/request.go +++ b/server/admin/internal/modules/coinledger/request.go @@ -8,6 +8,16 @@ type listQuery struct { EndAtMS int64 } +type coinSellerLedgerQuery struct { + Page int + PageSize int + SellerUserID int64 + SellerKeyword string + LedgerType string + StartAtMS int64 + EndAtMS int64 +} + type coinAdjustmentRequest struct { CommandID string `json:"commandId"` TargetUserID any `json:"targetUserId"` diff --git a/server/admin/internal/modules/coinledger/routes.go b/server/admin/internal/modules/coinledger/routes.go index 113b0a34..7ce439be 100644 --- a/server/admin/internal/modules/coinledger/routes.go +++ b/server/admin/internal/modules/coinledger/routes.go @@ -12,6 +12,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { } protected.GET("/admin/operations/coin-ledger", middleware.RequirePermission("coin-ledger:view"), h.ListCoinLedger) + protected.GET("/admin/operations/coin-seller-ledger", middleware.RequirePermission("coin-seller-ledger:view"), h.ListCoinSellerLedger) protected.GET("/admin/operations/coin-adjustments", middleware.RequirePermission("coin-adjustment:view"), h.ListCoinAdjustments) protected.GET("/admin/operations/coin-adjustments/target", middleware.RequirePermission("coin-adjustment:create"), h.LookupCoinAdjustmentTarget) protected.POST("/admin/operations/coin-adjustments", middleware.RequirePermission("coin-adjustment:create"), h.CreateCoinAdjustment) diff --git a/server/admin/internal/modules/coinledger/service.go b/server/admin/internal/modules/coinledger/service.go index 7112c0a4..a8731ec8 100644 --- a/server/admin/internal/modules/coinledger/service.go +++ b/server/admin/internal/modules/coinledger/service.go @@ -15,13 +15,24 @@ import ( ) const ( - coinAssetType = "COIN" - coinManualCreditBizType = "manual_credit" - directionIn = "income" - directionOut = "expense" + coinAssetType = "COIN" + coinSellerAssetType = "COIN_SELLER_COIN" + coinManualCreditBizType = "manual_credit" + coinSellerTransferBizType = "coin_seller_transfer" + coinSellerStockPurchaseBizType = "coin_seller_stock_purchase" + coinSellerCoinCompensationBizType = "coin_seller_coin_compensation" + salaryTransferToCoinSellerBizType = "salary_transfer_to_coin_seller" + coinSellerLedgerTypeAdminStockCredit = "admin_stock_credit" + coinSellerLedgerTypeSellerTransfer = "seller_transfer" + coinSellerLedgerTypeSalaryTransferIncome = "salary_transfer_received" + directionIn = "income" + directionOut = "expense" ) -var errCoinAdjustmentTargetNotFound = errors.New("coin adjustment target user not found") +var ( + errCoinAdjustmentTargetNotFound = errors.New("coin adjustment target user not found") + errInvalidCoinSellerLedgerType = errors.New("coin seller ledger type is invalid") +) type Service struct { userDB *sql.DB @@ -142,6 +153,119 @@ func (s *Service) ListCoinLedger(ctx context.Context, appCode string, query list return items, total, nil } +func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, query coinSellerLedgerQuery) ([]coinSellerLedgerDTO, int64, error) { + query = normalizeCoinSellerLedgerQuery(query) + if s == nil || s.walletDB == nil { + return nil, 0, fmt.Errorf("wallet mysql is not configured") + } + + // 先把前端筛选解析成币商 user_id 集合,再进入 wallet_entries 查询; + // 这样 seller_keyword 只影响币商本人范围,不会因为收款用户昵称或短 ID 命中而把其他币商流水带出来。 + sellerIDs, sellerFiltered, err := s.resolveCoinSellerFilter(ctx, appCode, query) + if err != nil { + return nil, 0, err + } + if sellerFiltered && len(sellerIDs) == 0 { + // 用户库已经确认没有匹配币商时直接返回空分页,避免对 wallet 库做没有结果意义的全量账本扫描。 + return []coinSellerLedgerDTO{}, 0, nil + } + + // 币商流水只读币商专用金币分录;wallet-service 仍是账务事实 owner,后台不回写余额、不补账、不改变交易状态, + // 这里只按运营筛选把 wallet_entries 与 wallet_transactions 的事实组装成后台展示投影。 + whereSQL, args, err := coinSellerLedgerWhere(appCode, query, sellerIDs) + if err != nil { + return nil, 0, err + } + var total int64 + if err := s.walletDB.QueryRowContext(ctx, ` + SELECT COUNT(*) + FROM wallet_entries e + JOIN wallet_transactions wt ON wt.app_code = e.app_code AND wt.transaction_id = e.transaction_id + `+whereSQL, + args..., + ).Scan(&total); err != nil { + return nil, 0, err + } + + // 明细查询只取币商侧 COIN_SELLER_COIN 分录:available_delta 表示币商库存可用变化, + // available_after 表示该币商分录落账后的库存余额,receiver 再按 biz_type 从 metadata/counterparty 补出。 + rows, err := s.walletDB.QueryContext(ctx, ` + SELECT e.entry_id, e.transaction_id, wt.command_id, e.user_id, wt.biz_type, + e.available_delta, e.available_after, e.counterparty_user_id, + COALESCE(CAST(wt.metadata_json AS CHAR), '{}'), e.created_at_ms + FROM wallet_entries e + JOIN wallet_transactions wt ON wt.app_code = e.app_code AND wt.transaction_id = e.transaction_id + `+whereSQL+` + ORDER BY e.created_at_ms DESC, e.entry_id DESC + LIMIT ? OFFSET ?`, + append(args, query.PageSize, offset(query.Page, query.PageSize))..., + ) + if err != nil { + return nil, 0, err + } + defer rows.Close() + + items := make([]coinSellerLedgerDTO, 0, query.PageSize) + profileIDs := make([]int64, 0, query.PageSize*2) + for rows.Next() { + var item coinSellerLedgerDTO + var sellerUserID int64 + var counterpartyUserID int64 + var metadataJSON string + if err := rows.Scan( + &item.EntryID, + &item.TransactionID, + &item.CommandID, + &sellerUserID, + &item.BizType, + &item.AvailableDelta, + &item.SellerBalanceAfter, + &counterpartyUserID, + &metadataJSON, + &item.CreatedAtMS, + ); err != nil { + return nil, 0, err + } + metadata, err := parseMetadataJSON(metadataJSON) + if err != nil { + return nil, 0, err + } + // 收款人按产品口径取实际收款人:币商转用户优先取 metadata.target_user_id,老数据没有 metadata 时再用 counterparty_user_id; + // 后台入账和工资转币商的实际收款人都是币商本人,所以不能被 counterparty 字段误导成付款方或操作方。 + receiverUserID := coinSellerLedgerReceiverUserID(item.BizType, sellerUserID, counterpartyUserID, metadata) + item.LedgerType = coinSellerLedgerTypeForBizType(item.BizType) + item.Direction = directionForDelta(item.AvailableDelta) + item.Amount = absInt64(item.AvailableDelta) + item.CounterpartyUserID = formatOptionalID(counterpartyUserID) + item.Metadata = metadata + item.Seller = coinLedgerUserDTO{UserID: strconv.FormatInt(sellerUserID, 10)} + item.Receiver = coinLedgerUserDTO{UserID: strconv.FormatInt(receiverUserID, 10)} + items = append(items, item) + profileIDs = append(profileIDs, sellerUserID, receiverUserID) + } + if err := rows.Err(); err != nil { + return nil, 0, err + } + + profiles, err := s.userProfiles(ctx, appCode, profileIDs) + if err != nil { + return nil, 0, err + } + for i := range items { + sellerUserID, _ := strconv.ParseInt(items[i].Seller.UserID, 10, 64) + receiverUserID, _ := strconv.ParseInt(items[i].Receiver.UserID, 10, 64) + // 用户资料只做头像、短 ID 和昵称展示补全;资料缺失时仍返回账本里的 user_id, + // 避免用户资料迁移、删除或延迟同步把真实账务事实从后台列表里吞掉。 + if profile, ok := profiles[sellerUserID]; ok { + items[i].Seller = userDTOFromProfile(profile) + } + if profile, ok := profiles[receiverUserID]; ok { + items[i].Receiver = userDTOFromProfile(profile) + } + } + return items, total, nil +} + func (s *Service) ListCoinAdjustments(ctx context.Context, appCode string, query listQuery) ([]coinAdjustmentDTO, int64, error) { query = normalizeListQuery(query) if s == nil || s.walletDB == nil { @@ -396,6 +520,59 @@ func (s *Service) resolveUserFilter(ctx context.Context, appCode string, keyword return uniqueInt64s(userIDs), true, rows.Err() } +func (s *Service) resolveCoinSellerFilter(ctx context.Context, appCode string, query coinSellerLedgerQuery) ([]int64, bool, error) { + if query.SellerUserID > 0 { + // seller_user_id 是 Coin Saller 行按钮传入的精确条件,直接使用账本 user_id 过滤; + // 即使用户资料暂时查不到,也允许账本事实被查出来,避免抽屉入口被资料缺失阻断。 + return []int64{query.SellerUserID}, true, nil + } + keyword := strings.TrimSpace(query.SellerKeyword) + if keyword == "" { + // 未传币商筛选时返回 userFiltered=false,调用方会查询所有币商流水,但仍被 biz_type、asset_type 和分页限制住。 + return nil, false, nil + } + if s == nil || s.userDB == nil { + return nil, true, fmt.Errorf("user mysql is not configured") + } + + // 币商关键字只命中 coin_seller_profiles 里的币商本人,LEFT JOIN users 只用于短 ID 和昵称补充; + // 这里故意不搜索 receiver/counterparty,避免“收款用户命中”把其他币商的流水带进当前币商筛选结果。 + args := []any{appCode} + where := "WHERE csp.app_code = ? AND (u.current_display_user_id = ?" + args = append(args, keyword) + if numeric, err := strconv.ParseInt(keyword, 10, 64); err == nil && numeric > 0 { + // 数字关键字按币商长 ID 精确匹配,不做 LIKE,防止短数字造成过宽的 user_id 扫描。 + where += " OR csp.user_id = ?" + args = append(args, numeric) + } + where += " OR u.username LIKE ? ESCAPE '\\\\')" + args = append(args, "%"+escapeLike(keyword)+"%") + + rows, err := s.userDB.QueryContext(ctx, ` + SELECT csp.user_id + FROM coin_seller_profiles csp + LEFT JOIN users u ON u.app_code = csp.app_code AND u.user_id = csp.user_id + `+where+` + ORDER BY csp.updated_at_ms DESC, csp.user_id DESC + LIMIT 1000`, + args..., + ) + if err != nil { + return nil, true, err + } + defer rows.Close() + + userIDs := make([]int64, 0) + for rows.Next() { + var userID int64 + if err := rows.Scan(&userID); err != nil { + return nil, true, err + } + userIDs = append(userIDs, userID) + } + return uniqueInt64s(userIDs), true, rows.Err() +} + func (s *Service) userProfiles(ctx context.Context, appCode string, userIDs []int64) (map[int64]userProfile, error) { result := make(map[int64]userProfile, len(userIDs)) if s == nil || s.userDB == nil || len(userIDs) == 0 { @@ -427,6 +604,15 @@ func (s *Service) userProfiles(ctx context.Context, appCode string, userIDs []in return result, rows.Err() } +func userDTOFromProfile(profile userProfile) coinLedgerUserDTO { + return coinLedgerUserDTO{ + UserID: strconv.FormatInt(profile.UserID, 10), + DisplayUserID: profile.DisplayUserID, + Username: profile.Username, + Avatar: profile.Avatar, + } +} + func coinLedgerWhere(appCode string, query listQuery, userIDs []int64) (string, []any) { where := "WHERE e.app_code = ? AND e.asset_type = ?" args := []any{appCode, coinAssetType} @@ -447,6 +633,46 @@ func coinLedgerWhere(appCode string, query listQuery, userIDs []int64) (string, return where, args } +func coinSellerLedgerWhere(appCode string, query coinSellerLedgerQuery, sellerIDs []int64) (string, []any, error) { + // 所有币商流水都必须落在当前 app_code 和 COIN_SELLER_COIN 资产上; + // 普通 COIN 分录属于用户金币流水,不能混入币商库存流水展示。 + where := "WHERE e.app_code = ? AND e.asset_type = ?" + args := []any{appCode, coinSellerAssetType} + bizTypes, err := coinSellerLedgerBizTypes(query.LedgerType) + if err != nil { + return "", nil, err + } + if len(bizTypes) == 1 { + // 单一类型用等值条件,保持 SQL 简洁,也方便后续索引按 biz_type 命中。 + where += " AND wt.biz_type = ?" + args = append(args, bizTypes[0]) + } else { + // 后台入账和“全部”都可能映射多个底层 biz_type,只展开白名单占位符,不拼接用户输入。 + where += fmt.Sprintf(" AND wt.biz_type IN (%s)", placeholders(len(bizTypes))) + for _, bizType := range bizTypes { + args = append(args, bizType) + } + } + if query.StartAtMS > 0 { + // 开始边界包含,和所有后台列表的 [start_at_ms, end_at_ms) 约定保持一致。 + where += " AND e.created_at_ms >= ?" + args = append(args, query.StartAtMS) + } + if query.EndAtMS > 0 { + // 结束边界不包含,避免按小时/天连续筛选时重复命中边界毫秒的同一条账本分录。 + where += " AND e.created_at_ms < ?" + args = append(args, query.EndAtMS) + } + if len(sellerIDs) > 0 { + // sellerIDs 来自精确 seller_user_id 或 coin_seller_profiles 搜索结果,只用于限制币商分录的 e.user_id。 + where += fmt.Sprintf(" AND e.user_id IN (%s)", placeholders(len(sellerIDs))) + for _, id := range sellerIDs { + args = append(args, id) + } + } + return where, args, nil +} + func coinAdjustmentWhere(appCode string, query listQuery, userIDs []int64) (string, []any) { where := "WHERE e.app_code = ? AND e.asset_type = ? AND wt.biz_type = ?" args := []any{appCode, coinAssetType, coinManualCreditBizType} @@ -481,6 +707,73 @@ func normalizeListQuery(query listQuery) listQuery { return query } +func normalizeCoinSellerLedgerQuery(query coinSellerLedgerQuery) coinSellerLedgerQuery { + if query.Page < 1 { + query.Page = 1 + } + if query.PageSize < 1 { + query.PageSize = 20 + } + if query.PageSize > 100 { + query.PageSize = 100 + } + query.SellerKeyword = strings.TrimSpace(query.SellerKeyword) + query.LedgerType = strings.TrimSpace(query.LedgerType) + return query +} + +func coinSellerLedgerBizTypes(ledgerType string) ([]string, error) { + switch strings.TrimSpace(ledgerType) { + case "": + // 空类型表示“全部币商流水”,但仍只允许当前产品定义的三个类型口径,不能把其他币商库存内部账带出来。 + return []string{ + coinSellerStockPurchaseBizType, + coinSellerCoinCompensationBizType, + coinSellerTransferBizType, + salaryTransferToCoinSellerBizType, + }, nil + case coinSellerLedgerTypeAdminStockCredit: + // 后台入账是运营口径,底层包含正常进货和金币补偿两种账务 biz_type。 + return []string{coinSellerStockPurchaseBizType, coinSellerCoinCompensationBizType}, nil + case coinSellerLedgerTypeSellerTransfer: + // 币商转用户只展示币商侧出账分录,收款用户资料在展示投影里补齐。 + return []string{coinSellerTransferBizType}, nil + case coinSellerLedgerTypeSalaryTransferIncome: + // 工资转币商是用户工资资产换入币商库存,币商侧表现为 COIN_SELLER_COIN 入账。 + return []string{salaryTransferToCoinSellerBizType}, nil + default: + return nil, errInvalidCoinSellerLedgerType + } +} + +func coinSellerLedgerTypeForBizType(bizType string) string { + switch bizType { + case coinSellerStockPurchaseBizType, coinSellerCoinCompensationBizType: + return coinSellerLedgerTypeAdminStockCredit + case coinSellerTransferBizType: + return coinSellerLedgerTypeSellerTransfer + case salaryTransferToCoinSellerBizType: + return coinSellerLedgerTypeSalaryTransferIncome + default: + return bizType + } +} + +func coinSellerLedgerReceiverUserID(bizType string, sellerUserID int64, counterpartyUserID int64, metadata map[string]any) int64 { + if bizType == coinSellerTransferBizType { + // 新数据把真实收款用户写在 metadata.target_user_id,优先使用它,避免 counterparty 语义随老交易实现变化。 + if targetUserID := metadataInt64(metadata, "target_user_id", "targetUserId"); targetUserID > 0 { + return targetUserID + } + // 老数据没有 target_user_id 时使用 counterparty_user_id 兜底;只有币商转用户才允许这样兜底。 + if counterpartyUserID > 0 { + return counterpartyUserID + } + } + // 后台入账和工资转币商都展示币商本人为收款人,这是页面“实际收款人”的产品口径。 + return sellerUserID +} + func directionForDelta(delta int64) string { if delta < 0 { return directionOut diff --git a/server/admin/internal/modules/coinledger/service_test.go b/server/admin/internal/modules/coinledger/service_test.go index cbf74850..b7aa6aa7 100644 --- a/server/admin/internal/modules/coinledger/service_test.go +++ b/server/admin/internal/modules/coinledger/service_test.go @@ -31,6 +31,61 @@ func TestCoinAdjustmentWhereLimitsManualCreditCoinEntries(t *testing.T) { } } +func TestCoinSellerLedgerWhereUsesExactSellerAndType(t *testing.T) { + query := coinSellerLedgerQuery{SellerUserID: 3001, LedgerType: coinSellerLedgerTypeSellerTransfer, StartAtMS: 100, EndAtMS: 200} + where, args, err := coinSellerLedgerWhere("lalu", query, []int64{3001}) + if err != nil { + t.Fatalf("coin seller ledger where failed: %v", err) + } + if want := "WHERE e.app_code = ? AND e.asset_type = ? AND wt.biz_type = ? AND e.created_at_ms >= ? AND e.created_at_ms < ? AND e.user_id IN (?)"; where != want { + t.Fatalf("where mismatch:\nwant %s\n got %s", want, where) + } + if len(args) != 6 || args[0] != "lalu" || args[1] != coinSellerAssetType || args[2] != coinSellerTransferBizType || args[3] != int64(100) || args[4] != int64(200) || args[5] != int64(3001) { + t.Fatalf("args mismatch: %#v", args) + } +} + +func TestCoinSellerLedgerWhereMapsAdminStockCredit(t *testing.T) { + query := coinSellerLedgerQuery{LedgerType: coinSellerLedgerTypeAdminStockCredit} + where, args, err := coinSellerLedgerWhere("lalu", query, []int64{3001, 3002}) + if err != nil { + t.Fatalf("coin seller ledger where failed: %v", err) + } + if want := "WHERE e.app_code = ? AND e.asset_type = ? AND wt.biz_type IN (?,?) AND e.user_id IN (?,?)"; where != want { + t.Fatalf("where mismatch:\nwant %s\n got %s", want, where) + } + if len(args) != 6 || args[0] != "lalu" || args[1] != coinSellerAssetType || args[2] != coinSellerStockPurchaseBizType || args[3] != coinSellerCoinCompensationBizType || args[4] != int64(3001) || args[5] != int64(3002) { + t.Fatalf("args mismatch: %#v", args) + } +} + +func TestCoinSellerLedgerWhereRejectsInvalidType(t *testing.T) { + _, _, err := coinSellerLedgerWhere("lalu", coinSellerLedgerQuery{LedgerType: "bad_type"}, nil) + if err == nil { + t.Fatalf("expected invalid ledger type error") + } +} + +func TestCoinSellerLedgerReceiverUserIDUsesActualReceiver(t *testing.T) { + metadata := map[string]any{"target_user_id": float64(4001)} + if got := coinSellerLedgerReceiverUserID(coinSellerTransferBizType, 3001, 0, metadata); got != 4001 { + t.Fatalf("seller transfer receiver mismatch: %d", got) + } + if got := coinSellerLedgerReceiverUserID(coinSellerStockPurchaseBizType, 3001, 4001, metadata); got != 3001 { + t.Fatalf("admin stock receiver mismatch: %d", got) + } + if got := coinSellerLedgerReceiverUserID(salaryTransferToCoinSellerBizType, 3001, 4001, metadata); got != 3001 { + t.Fatalf("salary transfer receiver mismatch: %d", got) + } +} + +func TestNormalizeCoinSellerLedgerQueryCapsPageSize(t *testing.T) { + query := normalizeCoinSellerLedgerQuery(coinSellerLedgerQuery{Page: -1, PageSize: 1000, SellerKeyword: " 164425 ", LedgerType: " seller_transfer "}) + if query.Page != 1 || query.PageSize != 100 || query.SellerKeyword != "164425" || query.LedgerType != coinSellerLedgerTypeSellerTransfer { + t.Fatalf("normalized query mismatch: %+v", query) + } +} + func TestDirectionAndAmountForDelta(t *testing.T) { if directionForDelta(-9) != directionOut || absInt64(-9) != 9 { t.Fatalf("expense projection mismatch") diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index e8c5f702..851e6a92 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -141,6 +141,26 @@ func (h *Handler) SetBDStatus(c *gin.Context) { response.OK(c, profile) } +func (h *Handler) UpdateBDLeaderPositionAlias(c *gin.Context) { + targetUserID, ok := parseInt64ID(c, "user_id") + if !ok { + return + } + var req bdLeaderPositionAliasRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "职位别名参数不正确") + return + } + profile, err := h.service.UpdateBDLeaderPositionAlias(c.Request.Context(), adminActorID(c), targetUserID, req) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + writeHostOrgAuditLog(c, h.audit, "set-bd-leader-position-alias", "admin_bd_leader_position_aliases", profile.UserID, + fmt.Sprintf("command_id=%s user_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.PositionAlias, strings.TrimSpace(req.Reason))) + response.OK(c, profile) +} + func (h *Handler) DeleteBDLeader(c *gin.Context) { targetUserID, ok := parseInt64ID(c, "user_id") if !ok { diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index e1d536d1..59f06056 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -154,6 +154,65 @@ func (r *Reader) ListBDProfiles(ctx context.Context, query listQuery, role strin return items, total, nil } +func (r *Reader) GetBDLeader(ctx context.Context, userID int64) (*userclient.BDProfile, error) { + if r == nil || r.db == nil { + return nil, errUserDBNotConfigured() + } + appCode := appctx.FromContext(ctx) + item := &userclient.BDProfile{} + err := r.db.QueryRowContext(ctx, ` + SELECT bp.user_id, bp.role, bp.region_id, COALESCE(bp.parent_leader_user_id, 0), + bp.status, bp.created_by_user_id, bp.created_at_ms, bp.updated_at_ms, + COALESCE(u.current_display_user_id, ''), COALESCE(u.username, ''), + COALESCE(u.avatar, ''), COALESCE(r.name, ''), + COALESCE(creator.current_display_user_id, ''), COALESCE(creator.username, ''), + COALESCE(creator.avatar, ''), + ( + SELECT COUNT(1) + FROM bd_profiles child + WHERE child.app_code = bp.app_code + AND child.role = 'bd' + AND child.parent_leader_user_id = bp.user_id + ) + FROM bd_profiles bp + LEFT JOIN users u ON u.app_code = bp.app_code AND u.user_id = bp.user_id + LEFT JOIN users creator ON creator.app_code = bp.app_code AND creator.user_id = bp.created_by_user_id + LEFT JOIN regions r ON r.app_code = bp.app_code AND r.region_id = bp.region_id + WHERE bp.app_code = ? AND bp.user_id = ? AND bp.role = 'bd_leader' + `, appCode, userID).Scan( + &item.UserID, + &item.Role, + &item.RegionID, + &item.ParentLeaderUserID, + &item.Status, + &item.CreatedByUserID, + &item.CreatedAtMs, + &item.UpdatedAtMs, + &item.DisplayUserID, + &item.Username, + &item.Avatar, + &item.RegionName, + &item.CreatedByDisplayUserID, + &item.CreatedByUsername, + &item.CreatedByAvatar, + &item.SubBDCount, + ) + if err == sql.ErrNoRows { + return nil, fmt.Errorf("bd leader not found") + } + if err != nil { + return nil, err + } + items := []*userclient.BDProfile{item} + if err := r.fillBDProfileCreators(ctx, items); err != nil { + return nil, err + } + if err := r.fillBDLeaderPositionAliases(ctx, appCode, items); err != nil { + return nil, err + } + return item, nil +} + func (r *Reader) fillBDProfileCreators(ctx context.Context, items []*userclient.BDProfile) error { if r == nil || r.adminDB == nil || len(items) == 0 { return nil diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index 1373b5af..ed964a3f 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -34,6 +34,12 @@ type bdStatusRequest struct { Reason string `json:"reason"` } +type bdLeaderPositionAliasRequest struct { + CommandID string `json:"commandId" binding:"required"` + PositionAlias string `json:"positionAlias"` + Reason string `json:"reason"` +} + type createCoinSellerRequest struct { CommandID string `json:"commandId" binding:"required"` Contact string `json:"contact"` diff --git a/server/admin/internal/modules/hostorg/routes.go b/server/admin/internal/modules/hostorg/routes.go index 82d7a2fb..1c0fb302 100644 --- a/server/admin/internal/modules/hostorg/routes.go +++ b/server/admin/internal/modules/hostorg/routes.go @@ -10,6 +10,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/admin/bd-leaders", middleware.RequirePermission("bd:view"), h.ListBDLeaders) protected.POST("/admin/bd-leaders", middleware.RequirePermission("bd:create"), h.CreateBDLeader) protected.PATCH("/admin/bd-leaders/:user_id/status", middleware.RequirePermission("bd:update"), h.SetBDStatus) + protected.PATCH("/admin/bd-leaders/:user_id/position-alias", middleware.RequirePermission("bd:update"), h.UpdateBDLeaderPositionAlias) protected.DELETE("/admin/bd-leaders/:user_id", middleware.RequirePermission("bd:update"), h.DeleteBDLeader) protected.GET("/admin/bds", middleware.RequirePermission("bd:view"), h.ListBDs) protected.POST("/admin/bds", middleware.RequirePermission("bd:create"), h.CreateBD) diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index df0abf5e..8ddebd59 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -119,9 +119,9 @@ func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID s if err != nil { return nil, err } - positionAlias := strings.TrimSpace(req.PositionAlias) - if len([]rune(positionAlias)) > bdLeaderPositionAliasMaxRunes { - return nil, fmt.Errorf("position_alias must not exceed %d characters", bdLeaderPositionAliasMaxRunes) + positionAlias, err := normalizeBDLeaderPositionAlias(req.PositionAlias) + if err != nil { + return nil, err } // BD Leader 创建时后台选择的区域是显式运营归属,由 user-service 在同一事务里更新 users.region_id 和 bd_profiles.region_id。 profile, err := s.userClient.CreateBDLeader(ctx, userclient.CreateBDLeaderRequest{ @@ -144,6 +144,26 @@ func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID s return profile, nil } +func (s *Service) UpdateBDLeaderPositionAlias(ctx context.Context, actorID int64, targetUserID int64, req bdLeaderPositionAliasRequest) (*userclient.BDProfile, error) { + if targetUserID <= 0 { + return nil, fmt.Errorf("target_user_id is required") + } + positionAlias, err := normalizeBDLeaderPositionAlias(req.PositionAlias) + if err != nil { + return nil, err + } + profile, err := s.reader.GetBDLeader(ctx, targetUserID) + if err != nil { + return nil, err + } + // 行内编辑只修改后台维护的展示别名;先确认 BD Leader 身份存在,再写覆盖表,避免产生无法在列表里追踪的孤立别名。 + if err := s.reader.SaveBDLeaderPositionAlias(ctx, targetUserID, actorID, positionAlias); err != nil { + return nil, err + } + profile.PositionAlias = positionAlias + return profile, nil +} + func (s *Service) CreateBD(ctx context.Context, actorID int64, requestID string, req createBDRequest) (*userclient.BDProfile, error) { targetUserID, err := s.resolveDisplayUserID(ctx, requestID, req.TargetUserID) if err != nil { @@ -360,6 +380,14 @@ func (s *Service) resolveDisplayUserID(ctx context.Context, requestID string, di return identity.UserID, nil } +func normalizeBDLeaderPositionAlias(value string) (string, error) { + positionAlias := strings.TrimSpace(value) + if len([]rune(positionAlias)) > bdLeaderPositionAliasMaxRunes { + return "", fmt.Errorf("position_alias must not exceed %d characters", bdLeaderPositionAliasMaxRunes) + } + return positionAlias, nil +} + func (s *Service) SetAgencyJoinEnabled(ctx context.Context, actorID int64, agencyID int64, requestID string, req agencyJoinEnabledRequest) (*userclient.Agency, error) { joinEnabled := false if req.JoinEnabled != nil { diff --git a/server/admin/internal/modules/roomtreasure/handler.go b/server/admin/internal/modules/roomrocket/handler.go similarity index 63% rename from server/admin/internal/modules/roomtreasure/handler.go rename to server/admin/internal/modules/roomrocket/handler.go index 24d3521e..8746de50 100644 --- a/server/admin/internal/modules/roomtreasure/handler.go +++ b/server/admin/internal/modules/roomrocket/handler.go @@ -1,4 +1,4 @@ -package roomtreasure +package roomrocket import ( "errors" @@ -20,19 +20,19 @@ func New(roomClient roomclient.Client, audit shared.OperationLogger) *Handler { return &Handler{service: NewService(roomClient), audit: audit} } -func (h *Handler) GetRoomTreasureConfig(c *gin.Context) { +func (h *Handler) GetRoomRocketConfig(c *gin.Context) { config, err := h.service.GetConfig(c.Request.Context()) if err != nil { - response.ServerError(c, "获取房间宝箱配置失败") + response.ServerError(c, "获取房间火箭配置失败") return } response.OK(c, config) } -func (h *Handler) UpdateRoomTreasureConfig(c *gin.Context) { - var req updateRoomTreasureConfigRequest +func (h *Handler) UpdateRoomRocketConfig(c *gin.Context) { + var req updateRoomRocketConfigRequest if err := c.ShouldBindJSON(&req); err != nil { - response.BadRequest(c, "房间宝箱配置参数不正确") + response.BadRequest(c, "房间火箭配置参数不正确") return } config, err := h.service.UpdateConfig(c.Request.Context(), req, int64(middleware.CurrentUserID(c))) @@ -41,9 +41,9 @@ func (h *Handler) UpdateRoomTreasureConfig(c *gin.Context) { response.BadRequest(c, err.Error()) return } - response.ServerError(c, "更新房间宝箱配置失败") + response.ServerError(c, "更新房间火箭配置失败") return } - shared.OperationLogWithResourceID(c, h.audit, "update-room-treasure-config", "room_treasure_configs", config.AppCode, "success", "") + shared.OperationLogWithResourceID(c, h.audit, "update-room-rocket-config", "room_rocket_configs", config.AppCode, "success", "") response.OK(c, config) } diff --git a/server/admin/internal/modules/roomrocket/routes.go b/server/admin/internal/modules/roomrocket/routes.go new file mode 100644 index 00000000..9a63cd9c --- /dev/null +++ b/server/admin/internal/modules/roomrocket/routes.go @@ -0,0 +1,16 @@ +package roomrocket + +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/room-rocket/config", middleware.RequirePermission("room-rocket:view"), h.GetRoomRocketConfig) + protected.PUT("/admin/activity/room-rocket/config", middleware.RequirePermission("room-rocket:update"), h.UpdateRoomRocketConfig) +} diff --git a/server/admin/internal/modules/roomrocket/service.go b/server/admin/internal/modules/roomrocket/service.go new file mode 100644 index 00000000..910d093b --- /dev/null +++ b/server/admin/internal/modules/roomrocket/service.go @@ -0,0 +1,431 @@ +package roomrocket + +import ( + "context" + "errors" + "fmt" + "slices" + "strings" + + "hyapp-admin-server/internal/integration/roomclient" +) + +const ( + roomRocketLevelCount = 5 + + defaultFuelSource = "heat_value" + defaultLaunchDelayMS = int64(30_000) + defaultBroadcastScope = "region" + defaultRewardStackPolicy = "allow_stack" +) + +var ( + ErrInvalidArgument = errors.New("invalid argument") + + defaultLevelFuelThresholds = []int64{1_000, 3_000, 6_000, 10_000, 15_000} +) + +type Service struct { + roomClient roomclient.Client +} + +type RoomRocketConfig struct { + AppCode string `json:"appCode"` + Enabled bool `json:"enabled"` + ConfigVersion int64 `json:"configVersion"` + FuelSource string `json:"fuelSource"` + LaunchDelayMS int64 `json:"launchDelayMs"` + BroadcastEnabled bool `json:"broadcastEnabled"` + BroadcastScope string `json:"broadcastScope"` + BroadcastDelayMS int64 `json:"broadcastDelayMs"` + RewardStackPolicy string `json:"rewardStackPolicy"` + Levels []RoomRocketLevelConfig `json:"levels"` + GiftFuelRules []GiftFuelRuleConfig `json:"giftFuelRules"` + UpdatedByAdminID int64 `json:"updatedByAdminId"` + CreatedAtMS int64 `json:"createdAtMs"` + UpdatedAtMS int64 `json:"updatedAtMs"` +} + +type RoomRocketLevelConfig struct { + Level int32 `json:"level"` + FuelThreshold int64 `json:"fuelThreshold"` + CoverURL string `json:"coverUrl"` + AnimationURL string `json:"animationUrl"` + LaunchAnimationURL string `json:"launchAnimationUrl"` + LaunchedImageURL string `json:"launchedImageUrl"` + InRoomRewards []RoomRocketRewardItem `json:"inRoomRewards"` + Top1Rewards []RoomRocketRewardItem `json:"top1Rewards"` + IgniterRewards []RoomRocketRewardItem `json:"igniterRewards"` +} + +type RoomRocketRewardItem struct { + RewardItemID string `json:"rewardItemId"` + ResourceGroupID int64 `json:"resourceGroupId"` + Weight int64 `json:"weight"` + DisplayName string `json:"displayName"` + IconURL string `json:"iconUrl"` +} + +type GiftFuelRuleConfig struct { + RuleID string `json:"ruleId"` + GiftID string `json:"giftId"` + GiftTypeCode string `json:"giftTypeCode"` + MultiplierPPM int64 `json:"multiplierPpm"` + FixedFuel int64 `json:"fixedFuel"` + Excluded bool `json:"excluded"` +} + +type updateRoomRocketConfigRequest struct { + Enabled bool `json:"enabled"` + FuelSource string `json:"fuelSource"` + LaunchDelayMS int64 `json:"launchDelayMs"` + BroadcastEnabled bool `json:"broadcastEnabled"` + BroadcastScope string `json:"broadcastScope"` + BroadcastDelayMS int64 `json:"broadcastDelayMs"` + RewardStackPolicy string `json:"rewardStackPolicy"` + Levels []RoomRocketLevelConfig `json:"levels"` + GiftFuelRules []GiftFuelRuleConfig `json:"giftFuelRules"` +} + +func NewService(roomClient roomclient.Client) *Service { + return &Service{roomClient: roomClient} +} + +// GetConfig 读取当前 App 的语音房火箭配置;缺行时返回关闭态默认配置,便于首次进入后台页面。 +func (s *Service) GetConfig(ctx context.Context) (RoomRocketConfig, error) { + if s.roomClient == nil { + return RoomRocketConfig{}, fmt.Errorf("room service client is not configured") + } + config, err := s.roomClient.GetRoomRocketConfig(ctx) + if err != nil { + return RoomRocketConfig{}, err + } + return configFromClient(config) +} + +// UpdateConfig 保存房间火箭低频配置;版本号由后台递增,运行时只使用已提交版本。 +func (s *Service) UpdateConfig(ctx context.Context, req updateRoomRocketConfigRequest, operatorAdminID int64) (RoomRocketConfig, error) { + if s.roomClient == nil { + return RoomRocketConfig{}, fmt.Errorf("room service client is not configured") + } + config, err := normalizeConfig(RoomRocketConfig{ + Enabled: req.Enabled, + FuelSource: req.FuelSource, + LaunchDelayMS: req.LaunchDelayMS, + BroadcastEnabled: req.BroadcastEnabled, + BroadcastScope: req.BroadcastScope, + BroadcastDelayMS: req.BroadcastDelayMS, + RewardStackPolicy: req.RewardStackPolicy, + Levels: req.Levels, + GiftFuelRules: req.GiftFuelRules, + }) + if err != nil { + return RoomRocketConfig{}, err + } + saved, err := s.roomClient.UpdateRoomRocketConfig(ctx, roomclient.UpdateRoomRocketConfigRequest{ + Config: configToClient(config), + AdminID: operatorAdminID, + }) + if err != nil { + return RoomRocketConfig{}, err + } + return configFromClient(saved) +} + +func defaultConfig(appCode string) RoomRocketConfig { + levels := make([]RoomRocketLevelConfig, 0, roomRocketLevelCount) + for index, threshold := range defaultLevelFuelThresholds { + levels = append(levels, RoomRocketLevelConfig{ + Level: int32(index + 1), + FuelThreshold: threshold, + }) + } + return RoomRocketConfig{ + AppCode: appCode, + FuelSource: defaultFuelSource, + LaunchDelayMS: defaultLaunchDelayMS, + BroadcastEnabled: true, + BroadcastScope: defaultBroadcastScope, + RewardStackPolicy: defaultRewardStackPolicy, + Levels: levels, + GiftFuelRules: []GiftFuelRuleConfig{}, + } +} + +func normalizeConfig(config RoomRocketConfig) (RoomRocketConfig, error) { + config.AppCode = strings.TrimSpace(config.AppCode) + if config.AppCode == "" { + return RoomRocketConfig{}, fmt.Errorf("%w: app_code 不能为空", ErrInvalidArgument) + } + if config.ConfigVersion < 0 { + return RoomRocketConfig{}, fmt.Errorf("%w: 配置版本不能小于 0", ErrInvalidArgument) + } + config.FuelSource = defaultString(strings.TrimSpace(config.FuelSource), defaultFuelSource) + if config.FuelSource == "gift_point_added" { + // gift_point_added 是历史配置值;GIFT_POINT 已下线,后台读取旧配置时统一切到真实礼物贡献口径。 + config.FuelSource = defaultFuelSource + } + if config.FuelSource != defaultFuelSource { + return RoomRocketConfig{}, fmt.Errorf("%w: 燃料来源不支持", ErrInvalidArgument) + } + if config.LaunchDelayMS < 0 { + return RoomRocketConfig{}, fmt.Errorf("%w: 发射倒计时不能小于 0", ErrInvalidArgument) + } + config.BroadcastScope = defaultString(strings.TrimSpace(config.BroadcastScope), defaultBroadcastScope) + if !stringIn(config.BroadcastScope, "none", "region", "global") { + return RoomRocketConfig{}, fmt.Errorf("%w: 广播范围不支持", ErrInvalidArgument) + } + if config.BroadcastDelayMS < 0 { + return RoomRocketConfig{}, fmt.Errorf("%w: 广播延迟不能小于 0", ErrInvalidArgument) + } + config.RewardStackPolicy = defaultString(strings.TrimSpace(config.RewardStackPolicy), defaultRewardStackPolicy) + if !stringIn(config.RewardStackPolicy, "allow_stack", "priority_only") { + return RoomRocketConfig{}, fmt.Errorf("%w: 奖励叠加策略不支持", ErrInvalidArgument) + } + levels, err := normalizeLevels(config.Levels) + if err != nil { + return RoomRocketConfig{}, err + } + config.Levels = levels + giftFuelRules, err := normalizeGiftFuelRules(config.GiftFuelRules) + if err != nil { + return RoomRocketConfig{}, err + } + config.GiftFuelRules = giftFuelRules + return config, nil +} + +func normalizeLevels(levels []RoomRocketLevelConfig) ([]RoomRocketLevelConfig, error) { + if len(levels) == 0 { + return defaultConfig("placeholder").Levels, nil + } + if len(levels) != roomRocketLevelCount { + return nil, fmt.Errorf("%w: 火箭等级必须配置 5 级", ErrInvalidArgument) + } + seen := make(map[int32]bool, roomRocketLevelCount) + normalized := make([]RoomRocketLevelConfig, 0, roomRocketLevelCount) + for _, level := range levels { + if level.Level < 1 || level.Level > roomRocketLevelCount { + return nil, fmt.Errorf("%w: 火箭等级只能是 1 到 5", ErrInvalidArgument) + } + if seen[level.Level] { + return nil, fmt.Errorf("%w: 火箭等级不能重复", ErrInvalidArgument) + } + seen[level.Level] = true + if level.FuelThreshold <= 0 { + return nil, fmt.Errorf("%w: 第 %d 级燃料阈值必须大于 0", ErrInvalidArgument, level.Level) + } + level.CoverURL = strings.TrimSpace(level.CoverURL) + level.AnimationURL = strings.TrimSpace(level.AnimationURL) + level.LaunchAnimationURL = strings.TrimSpace(level.LaunchAnimationURL) + level.LaunchedImageURL = strings.TrimSpace(level.LaunchedImageURL) + var err error + if level.InRoomRewards, err = normalizeRewardPool(level.Level, "in_room", level.InRoomRewards); err != nil { + return nil, err + } + if level.Top1Rewards, err = normalizeRewardPool(level.Level, "top1", level.Top1Rewards); err != nil { + return nil, err + } + if level.IgniterRewards, err = normalizeRewardPool(level.Level, "igniter", level.IgniterRewards); err != nil { + return nil, err + } + normalized = append(normalized, level) + } + slices.SortFunc(normalized, func(left, right RoomRocketLevelConfig) int { + return int(left.Level - right.Level) + }) + return normalized, nil +} + +func normalizeRewardPool(level int32, role string, rewards []RoomRocketRewardItem) ([]RoomRocketRewardItem, error) { + normalized := make([]RoomRocketRewardItem, 0, len(rewards)) + for index, reward := range rewards { + reward.RewardItemID = strings.TrimSpace(reward.RewardItemID) + reward.DisplayName = strings.TrimSpace(reward.DisplayName) + reward.IconURL = strings.TrimSpace(reward.IconURL) + if reward.RewardItemID == "" && reward.ResourceGroupID == 0 && reward.Weight == 0 && reward.DisplayName == "" && reward.IconURL == "" { + continue + } + if reward.ResourceGroupID <= 0 { + return nil, fmt.Errorf("%w: 第 %d 级奖励资源组不能为空", ErrInvalidArgument, level) + } + if reward.Weight <= 0 { + return nil, fmt.Errorf("%w: 第 %d 级奖励权重必须大于 0", ErrInvalidArgument, level) + } + if reward.RewardItemID == "" { + reward.RewardItemID = fmt.Sprintf("level_%d_%s_%d", level, role, index+1) + } + normalized = append(normalized, reward) + } + return normalized, nil +} + +func normalizeGiftFuelRules(rules []GiftFuelRuleConfig) ([]GiftFuelRuleConfig, error) { + normalized := make([]GiftFuelRuleConfig, 0, len(rules)) + for index, rule := range rules { + rule.RuleID = strings.TrimSpace(rule.RuleID) + rule.GiftID = strings.TrimSpace(rule.GiftID) + rule.GiftTypeCode = strings.TrimSpace(rule.GiftTypeCode) + if rule.RuleID == "" && rule.GiftID == "" && rule.GiftTypeCode == "" && rule.MultiplierPPM == 0 && rule.FixedFuel == 0 && !rule.Excluded { + continue + } + if rule.GiftID == "" && rule.GiftTypeCode == "" { + return nil, fmt.Errorf("%w: 礼物燃料规则必须选择礼物或礼物类型", ErrInvalidArgument) + } + if rule.MultiplierPPM < 0 || rule.FixedFuel < 0 { + return nil, fmt.Errorf("%w: 礼物燃料规则不能配置负数", ErrInvalidArgument) + } + if !rule.Excluded && rule.MultiplierPPM == 0 && rule.FixedFuel == 0 { + return nil, fmt.Errorf("%w: 礼物燃料规则必须配置倍率或固定燃料", ErrInvalidArgument) + } + if rule.RuleID == "" { + rule.RuleID = fmt.Sprintf("gift_fuel_rule_%d", index+1) + } + normalized = append(normalized, rule) + } + return normalized, nil +} + +func defaultString(value string, fallback string) string { + if value == "" { + return fallback + } + return value +} + +func stringIn(value string, candidates ...string) bool { + for _, candidate := range candidates { + if value == candidate { + return true + } + } + return false +} + +func configFromClient(input roomclient.RoomRocketConfig) (RoomRocketConfig, error) { + config := RoomRocketConfig{ + AppCode: input.AppCode, + Enabled: input.Enabled, + ConfigVersion: input.ConfigVersion, + FuelSource: input.FuelSource, + LaunchDelayMS: input.LaunchDelayMS, + BroadcastEnabled: input.BroadcastEnabled, + BroadcastScope: input.BroadcastScope, + BroadcastDelayMS: input.BroadcastDelayMS, + RewardStackPolicy: input.RewardStackPolicy, + Levels: levelsFromClient(input.Levels), + GiftFuelRules: fuelRulesFromClient(input.GiftFuelRules), + UpdatedByAdminID: input.UpdatedByAdminID, + CreatedAtMS: input.CreatedAtMS, + UpdatedAtMS: input.UpdatedAtMS, + } + return normalizeConfig(config) +} + +func configToClient(input RoomRocketConfig) roomclient.RoomRocketConfig { + return roomclient.RoomRocketConfig{ + Enabled: input.Enabled, + FuelSource: input.FuelSource, + LaunchDelayMS: input.LaunchDelayMS, + BroadcastEnabled: input.BroadcastEnabled, + BroadcastScope: input.BroadcastScope, + BroadcastDelayMS: input.BroadcastDelayMS, + RewardStackPolicy: input.RewardStackPolicy, + Levels: levelsToClient(input.Levels), + GiftFuelRules: fuelRulesToClient(input.GiftFuelRules), + } +} + +func levelsFromClient(input []roomclient.RoomRocketLevelConfig) []RoomRocketLevelConfig { + out := make([]RoomRocketLevelConfig, 0, len(input)) + for _, level := range input { + out = append(out, RoomRocketLevelConfig{ + Level: level.Level, + FuelThreshold: level.FuelThreshold, + CoverURL: level.CoverURL, + AnimationURL: level.AnimationURL, + LaunchAnimationURL: level.LaunchAnimationURL, + LaunchedImageURL: level.LaunchedImageURL, + InRoomRewards: rewardsFromClient(level.InRoomRewards), + Top1Rewards: rewardsFromClient(level.Top1Rewards), + IgniterRewards: rewardsFromClient(level.IgniterRewards), + }) + } + return out +} + +func levelsToClient(input []RoomRocketLevelConfig) []roomclient.RoomRocketLevelConfig { + out := make([]roomclient.RoomRocketLevelConfig, 0, len(input)) + for _, level := range input { + out = append(out, roomclient.RoomRocketLevelConfig{ + Level: level.Level, + FuelThreshold: level.FuelThreshold, + CoverURL: level.CoverURL, + AnimationURL: level.AnimationURL, + LaunchAnimationURL: level.LaunchAnimationURL, + LaunchedImageURL: level.LaunchedImageURL, + InRoomRewards: rewardsToClient(level.InRoomRewards), + Top1Rewards: rewardsToClient(level.Top1Rewards), + IgniterRewards: rewardsToClient(level.IgniterRewards), + }) + } + return out +} + +func rewardsFromClient(input []roomclient.RoomRocketRewardItem) []RoomRocketRewardItem { + out := make([]RoomRocketRewardItem, 0, len(input)) + for _, reward := range input { + out = append(out, RoomRocketRewardItem{ + RewardItemID: reward.RewardItemID, + ResourceGroupID: reward.ResourceGroupID, + Weight: reward.Weight, + DisplayName: reward.DisplayName, + IconURL: reward.IconURL, + }) + } + return out +} + +func rewardsToClient(input []RoomRocketRewardItem) []roomclient.RoomRocketRewardItem { + out := make([]roomclient.RoomRocketRewardItem, 0, len(input)) + for _, reward := range input { + out = append(out, roomclient.RoomRocketRewardItem{ + RewardItemID: reward.RewardItemID, + ResourceGroupID: reward.ResourceGroupID, + Weight: reward.Weight, + DisplayName: reward.DisplayName, + IconURL: reward.IconURL, + }) + } + return out +} + +func fuelRulesFromClient(input []roomclient.GiftFuelRuleConfig) []GiftFuelRuleConfig { + out := make([]GiftFuelRuleConfig, 0, len(input)) + for _, rule := range input { + out = append(out, GiftFuelRuleConfig{ + RuleID: rule.RuleID, + GiftID: rule.GiftID, + GiftTypeCode: rule.GiftTypeCode, + MultiplierPPM: rule.MultiplierPPM, + FixedFuel: rule.FixedFuel, + Excluded: rule.Excluded, + }) + } + return out +} + +func fuelRulesToClient(input []GiftFuelRuleConfig) []roomclient.GiftFuelRuleConfig { + out := make([]roomclient.GiftFuelRuleConfig, 0, len(input)) + for _, rule := range input { + out = append(out, roomclient.GiftFuelRuleConfig{ + RuleID: rule.RuleID, + GiftID: rule.GiftID, + GiftTypeCode: rule.GiftTypeCode, + MultiplierPPM: rule.MultiplierPPM, + FixedFuel: rule.FixedFuel, + Excluded: rule.Excluded, + }) + } + return out +} diff --git a/server/admin/internal/modules/roomrocket/service_test.go b/server/admin/internal/modules/roomrocket/service_test.go new file mode 100644 index 00000000..888dd4e6 --- /dev/null +++ b/server/admin/internal/modules/roomrocket/service_test.go @@ -0,0 +1,79 @@ +package roomrocket + +import ( + "errors" + "testing" +) + +func TestNormalizeConfigDefaultsAndSortsLevels(t *testing.T) { + config, err := normalizeConfig(RoomRocketConfig{ + AppCode: "lalu", + LaunchDelayMS: defaultLaunchDelayMS, + Levels: []RoomRocketLevelConfig{ + {Level: 2, FuelThreshold: 300}, + {Level: 1, FuelThreshold: 100}, + {Level: 3, FuelThreshold: 600}, + {Level: 4, FuelThreshold: 1_000}, + {Level: 5, FuelThreshold: 1_500}, + {Level: 6, FuelThreshold: 2_100}, + {Level: 7, FuelThreshold: 2_800}, + }, + }) + if err != nil { + t.Fatalf("normalizeConfig failed: %v", err) + } + if config.FuelSource != defaultFuelSource || config.LaunchDelayMS != defaultLaunchDelayMS || config.BroadcastScope != defaultBroadcastScope { + t.Fatalf("default fields mismatch: %+v", config) + } + if config.Levels[0].Level != 1 || config.Levels[6].Level != 7 { + t.Fatalf("levels should be sorted by level: %+v", config.Levels) + } +} + +func TestDefaultConfigKeepsOperationalDefaults(t *testing.T) { + config, err := normalizeConfig(defaultConfig("lalu")) + if err != nil { + t.Fatalf("normalizeConfig(defaultConfig) failed: %v", err) + } + if !config.BroadcastEnabled || config.LaunchDelayMS != defaultLaunchDelayMS || len(config.Levels) != roomRocketLevelCount { + t.Fatalf("default config mismatch: %+v", config) + } +} + +func TestNormalizeConfigRejectsInvalidLevels(t *testing.T) { + tests := []struct { + name string + config RoomRocketConfig + }{ + {name: "missing_level", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{{Level: 1, FuelThreshold: 1}}}}, + {name: "duplicate", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ + {Level: 1, FuelThreshold: 1}, {Level: 1, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, + }}}, + {name: "zero_threshold", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ + {Level: 1, FuelThreshold: 0}, {Level: 2, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, + }}}, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := normalizeConfig(test.config) + if !errors.Is(err, ErrInvalidArgument) { + t.Fatalf("normalizeConfig should reject %s with ErrInvalidArgument, got %v", test.name, err) + } + }) + } +} + +func TestNormalizeConfigRejectsIncompleteRewardAndFuelRule(t *testing.T) { + config := defaultConfig("lalu") + config.Levels[0].InRoomRewards = []RoomRocketRewardItem{{ResourceGroupID: 0, Weight: 100}} + if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { + t.Fatalf("reward without resource group should be invalid, got %v", err) + } + + config = defaultConfig("lalu") + config.GiftFuelRules = []GiftFuelRuleConfig{{GiftID: "gift-1"}} + if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { + t.Fatalf("energy rule without multiplier or fixed energy should be invalid, got %v", err) + } +} diff --git a/server/admin/internal/modules/roomtreasure/routes.go b/server/admin/internal/modules/roomtreasure/routes.go deleted file mode 100644 index 17e2d5e4..00000000 --- a/server/admin/internal/modules/roomtreasure/routes.go +++ /dev/null @@ -1,16 +0,0 @@ -package roomtreasure - -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/room-treasure/config", middleware.RequirePermission("room-treasure:view"), h.GetRoomTreasureConfig) - protected.PUT("/admin/activity/room-treasure/config", middleware.RequirePermission("room-treasure:update"), h.UpdateRoomTreasureConfig) -} diff --git a/server/admin/internal/modules/roomtreasure/service.go b/server/admin/internal/modules/roomtreasure/service.go deleted file mode 100644 index 93516f7e..00000000 --- a/server/admin/internal/modules/roomtreasure/service.go +++ /dev/null @@ -1,431 +0,0 @@ -package roomtreasure - -import ( - "context" - "errors" - "fmt" - "slices" - "strings" - - "hyapp-admin-server/internal/integration/roomclient" -) - -const ( - roomTreasureLevelCount = 7 - - defaultEnergySource = "heat_value" - defaultOpenDelayMS = int64(30_000) - defaultBroadcastScope = "region" - defaultRewardStackPolicy = "allow_stack" -) - -var ( - ErrInvalidArgument = errors.New("invalid argument") - - defaultLevelEnergyThresholds = []int64{1_000, 3_000, 6_000, 10_000, 15_000, 21_000, 28_000} -) - -type Service struct { - roomClient roomclient.Client -} - -type RoomTreasureConfig struct { - AppCode string `json:"appCode"` - Enabled bool `json:"enabled"` - ConfigVersion int64 `json:"configVersion"` - EnergySource string `json:"energySource"` - OpenDelayMS int64 `json:"openDelayMs"` - BroadcastEnabled bool `json:"broadcastEnabled"` - BroadcastScope string `json:"broadcastScope"` - BroadcastDelayMS int64 `json:"broadcastDelayMs"` - RewardStackPolicy string `json:"rewardStackPolicy"` - Levels []RoomTreasureLevelConfig `json:"levels"` - GiftEnergyRules []GiftEnergyRuleConfig `json:"giftEnergyRules"` - UpdatedByAdminID int64 `json:"updatedByAdminId"` - CreatedAtMS int64 `json:"createdAtMs"` - UpdatedAtMS int64 `json:"updatedAtMs"` -} - -type RoomTreasureLevelConfig struct { - Level int32 `json:"level"` - EnergyThreshold int64 `json:"energyThreshold"` - CoverURL string `json:"coverUrl"` - AnimationURL string `json:"animationUrl"` - OpeningAnimationURL string `json:"openingAnimationUrl"` - OpenedImageURL string `json:"openedImageUrl"` - InRoomRewards []RoomTreasureRewardItem `json:"inRoomRewards"` - Top1Rewards []RoomTreasureRewardItem `json:"top1Rewards"` - IgniterRewards []RoomTreasureRewardItem `json:"igniterRewards"` -} - -type RoomTreasureRewardItem struct { - RewardItemID string `json:"rewardItemId"` - ResourceGroupID int64 `json:"resourceGroupId"` - Weight int64 `json:"weight"` - DisplayName string `json:"displayName"` - IconURL string `json:"iconUrl"` -} - -type GiftEnergyRuleConfig struct { - RuleID string `json:"ruleId"` - GiftID string `json:"giftId"` - GiftTypeCode string `json:"giftTypeCode"` - MultiplierPPM int64 `json:"multiplierPpm"` - FixedEnergy int64 `json:"fixedEnergy"` - Excluded bool `json:"excluded"` -} - -type updateRoomTreasureConfigRequest struct { - Enabled bool `json:"enabled"` - EnergySource string `json:"energySource"` - OpenDelayMS int64 `json:"openDelayMs"` - BroadcastEnabled bool `json:"broadcastEnabled"` - BroadcastScope string `json:"broadcastScope"` - BroadcastDelayMS int64 `json:"broadcastDelayMs"` - RewardStackPolicy string `json:"rewardStackPolicy"` - Levels []RoomTreasureLevelConfig `json:"levels"` - GiftEnergyRules []GiftEnergyRuleConfig `json:"giftEnergyRules"` -} - -func NewService(roomClient roomclient.Client) *Service { - return &Service{roomClient: roomClient} -} - -// GetConfig 读取当前 App 的语音房宝箱配置;缺行时返回关闭态默认配置,便于首次进入后台页面。 -func (s *Service) GetConfig(ctx context.Context) (RoomTreasureConfig, error) { - if s.roomClient == nil { - return RoomTreasureConfig{}, fmt.Errorf("room service client is not configured") - } - config, err := s.roomClient.GetRoomTreasureConfig(ctx) - if err != nil { - return RoomTreasureConfig{}, err - } - return configFromClient(config) -} - -// UpdateConfig 保存房间宝箱低频配置;版本号由后台递增,运行时只使用已提交版本。 -func (s *Service) UpdateConfig(ctx context.Context, req updateRoomTreasureConfigRequest, operatorAdminID int64) (RoomTreasureConfig, error) { - if s.roomClient == nil { - return RoomTreasureConfig{}, fmt.Errorf("room service client is not configured") - } - config, err := normalizeConfig(RoomTreasureConfig{ - Enabled: req.Enabled, - EnergySource: req.EnergySource, - OpenDelayMS: req.OpenDelayMS, - BroadcastEnabled: req.BroadcastEnabled, - BroadcastScope: req.BroadcastScope, - BroadcastDelayMS: req.BroadcastDelayMS, - RewardStackPolicy: req.RewardStackPolicy, - Levels: req.Levels, - GiftEnergyRules: req.GiftEnergyRules, - }) - if err != nil { - return RoomTreasureConfig{}, err - } - saved, err := s.roomClient.UpdateRoomTreasureConfig(ctx, roomclient.UpdateRoomTreasureConfigRequest{ - Config: configToClient(config), - AdminID: operatorAdminID, - }) - if err != nil { - return RoomTreasureConfig{}, err - } - return configFromClient(saved) -} - -func defaultConfig(appCode string) RoomTreasureConfig { - levels := make([]RoomTreasureLevelConfig, 0, roomTreasureLevelCount) - for index, threshold := range defaultLevelEnergyThresholds { - levels = append(levels, RoomTreasureLevelConfig{ - Level: int32(index + 1), - EnergyThreshold: threshold, - }) - } - return RoomTreasureConfig{ - AppCode: appCode, - EnergySource: defaultEnergySource, - OpenDelayMS: defaultOpenDelayMS, - BroadcastEnabled: true, - BroadcastScope: defaultBroadcastScope, - RewardStackPolicy: defaultRewardStackPolicy, - Levels: levels, - GiftEnergyRules: []GiftEnergyRuleConfig{}, - } -} - -func normalizeConfig(config RoomTreasureConfig) (RoomTreasureConfig, error) { - config.AppCode = strings.TrimSpace(config.AppCode) - if config.AppCode == "" { - return RoomTreasureConfig{}, fmt.Errorf("%w: app_code 不能为空", ErrInvalidArgument) - } - if config.ConfigVersion < 0 { - return RoomTreasureConfig{}, fmt.Errorf("%w: 配置版本不能小于 0", ErrInvalidArgument) - } - config.EnergySource = defaultString(strings.TrimSpace(config.EnergySource), defaultEnergySource) - if config.EnergySource == "gift_point_added" { - // gift_point_added 是历史配置值;GIFT_POINT 已下线,后台读取旧配置时统一切到真实礼物贡献口径。 - config.EnergySource = defaultEnergySource - } - if config.EnergySource != defaultEnergySource { - return RoomTreasureConfig{}, fmt.Errorf("%w: 能量来源不支持", ErrInvalidArgument) - } - if config.OpenDelayMS < 0 { - return RoomTreasureConfig{}, fmt.Errorf("%w: 开箱倒计时不能小于 0", ErrInvalidArgument) - } - config.BroadcastScope = defaultString(strings.TrimSpace(config.BroadcastScope), defaultBroadcastScope) - if !stringIn(config.BroadcastScope, "none", "region", "global") { - return RoomTreasureConfig{}, fmt.Errorf("%w: 广播范围不支持", ErrInvalidArgument) - } - if config.BroadcastDelayMS < 0 { - return RoomTreasureConfig{}, fmt.Errorf("%w: 广播延迟不能小于 0", ErrInvalidArgument) - } - config.RewardStackPolicy = defaultString(strings.TrimSpace(config.RewardStackPolicy), defaultRewardStackPolicy) - if !stringIn(config.RewardStackPolicy, "allow_stack", "priority_only") { - return RoomTreasureConfig{}, fmt.Errorf("%w: 奖励叠加策略不支持", ErrInvalidArgument) - } - levels, err := normalizeLevels(config.Levels) - if err != nil { - return RoomTreasureConfig{}, err - } - config.Levels = levels - giftEnergyRules, err := normalizeGiftEnergyRules(config.GiftEnergyRules) - if err != nil { - return RoomTreasureConfig{}, err - } - config.GiftEnergyRules = giftEnergyRules - return config, nil -} - -func normalizeLevels(levels []RoomTreasureLevelConfig) ([]RoomTreasureLevelConfig, error) { - if len(levels) == 0 { - return defaultConfig("placeholder").Levels, nil - } - if len(levels) != roomTreasureLevelCount { - return nil, fmt.Errorf("%w: 宝箱等级必须配置 7 级", ErrInvalidArgument) - } - seen := make(map[int32]bool, roomTreasureLevelCount) - normalized := make([]RoomTreasureLevelConfig, 0, roomTreasureLevelCount) - for _, level := range levels { - if level.Level < 1 || level.Level > roomTreasureLevelCount { - return nil, fmt.Errorf("%w: 宝箱等级只能是 1 到 7", ErrInvalidArgument) - } - if seen[level.Level] { - return nil, fmt.Errorf("%w: 宝箱等级不能重复", ErrInvalidArgument) - } - seen[level.Level] = true - if level.EnergyThreshold <= 0 { - return nil, fmt.Errorf("%w: 第 %d 级能量阈值必须大于 0", ErrInvalidArgument, level.Level) - } - level.CoverURL = strings.TrimSpace(level.CoverURL) - level.AnimationURL = strings.TrimSpace(level.AnimationURL) - level.OpeningAnimationURL = strings.TrimSpace(level.OpeningAnimationURL) - level.OpenedImageURL = strings.TrimSpace(level.OpenedImageURL) - var err error - if level.InRoomRewards, err = normalizeRewardPool(level.Level, "in_room", level.InRoomRewards); err != nil { - return nil, err - } - if level.Top1Rewards, err = normalizeRewardPool(level.Level, "top1", level.Top1Rewards); err != nil { - return nil, err - } - if level.IgniterRewards, err = normalizeRewardPool(level.Level, "igniter", level.IgniterRewards); err != nil { - return nil, err - } - normalized = append(normalized, level) - } - slices.SortFunc(normalized, func(left, right RoomTreasureLevelConfig) int { - return int(left.Level - right.Level) - }) - return normalized, nil -} - -func normalizeRewardPool(level int32, role string, rewards []RoomTreasureRewardItem) ([]RoomTreasureRewardItem, error) { - normalized := make([]RoomTreasureRewardItem, 0, len(rewards)) - for index, reward := range rewards { - reward.RewardItemID = strings.TrimSpace(reward.RewardItemID) - reward.DisplayName = strings.TrimSpace(reward.DisplayName) - reward.IconURL = strings.TrimSpace(reward.IconURL) - if reward.RewardItemID == "" && reward.ResourceGroupID == 0 && reward.Weight == 0 && reward.DisplayName == "" && reward.IconURL == "" { - continue - } - if reward.ResourceGroupID <= 0 { - return nil, fmt.Errorf("%w: 第 %d 级奖励资源组不能为空", ErrInvalidArgument, level) - } - if reward.Weight <= 0 { - return nil, fmt.Errorf("%w: 第 %d 级奖励权重必须大于 0", ErrInvalidArgument, level) - } - if reward.RewardItemID == "" { - reward.RewardItemID = fmt.Sprintf("level_%d_%s_%d", level, role, index+1) - } - normalized = append(normalized, reward) - } - return normalized, nil -} - -func normalizeGiftEnergyRules(rules []GiftEnergyRuleConfig) ([]GiftEnergyRuleConfig, error) { - normalized := make([]GiftEnergyRuleConfig, 0, len(rules)) - for index, rule := range rules { - rule.RuleID = strings.TrimSpace(rule.RuleID) - rule.GiftID = strings.TrimSpace(rule.GiftID) - rule.GiftTypeCode = strings.TrimSpace(rule.GiftTypeCode) - if rule.RuleID == "" && rule.GiftID == "" && rule.GiftTypeCode == "" && rule.MultiplierPPM == 0 && rule.FixedEnergy == 0 && !rule.Excluded { - continue - } - if rule.GiftID == "" && rule.GiftTypeCode == "" { - return nil, fmt.Errorf("%w: 礼物能量规则必须选择礼物或礼物类型", ErrInvalidArgument) - } - if rule.MultiplierPPM < 0 || rule.FixedEnergy < 0 { - return nil, fmt.Errorf("%w: 礼物能量规则不能配置负数", ErrInvalidArgument) - } - if !rule.Excluded && rule.MultiplierPPM == 0 && rule.FixedEnergy == 0 { - return nil, fmt.Errorf("%w: 礼物能量规则必须配置倍率或固定能量", ErrInvalidArgument) - } - if rule.RuleID == "" { - rule.RuleID = fmt.Sprintf("gift_energy_rule_%d", index+1) - } - normalized = append(normalized, rule) - } - return normalized, nil -} - -func defaultString(value string, fallback string) string { - if value == "" { - return fallback - } - return value -} - -func stringIn(value string, candidates ...string) bool { - for _, candidate := range candidates { - if value == candidate { - return true - } - } - return false -} - -func configFromClient(input roomclient.RoomTreasureConfig) (RoomTreasureConfig, error) { - config := RoomTreasureConfig{ - AppCode: input.AppCode, - Enabled: input.Enabled, - ConfigVersion: input.ConfigVersion, - EnergySource: input.EnergySource, - OpenDelayMS: input.OpenDelayMS, - BroadcastEnabled: input.BroadcastEnabled, - BroadcastScope: input.BroadcastScope, - BroadcastDelayMS: input.BroadcastDelayMS, - RewardStackPolicy: input.RewardStackPolicy, - Levels: levelsFromClient(input.Levels), - GiftEnergyRules: energyRulesFromClient(input.GiftEnergyRules), - UpdatedByAdminID: input.UpdatedByAdminID, - CreatedAtMS: input.CreatedAtMS, - UpdatedAtMS: input.UpdatedAtMS, - } - return normalizeConfig(config) -} - -func configToClient(input RoomTreasureConfig) roomclient.RoomTreasureConfig { - return roomclient.RoomTreasureConfig{ - Enabled: input.Enabled, - EnergySource: input.EnergySource, - OpenDelayMS: input.OpenDelayMS, - BroadcastEnabled: input.BroadcastEnabled, - BroadcastScope: input.BroadcastScope, - BroadcastDelayMS: input.BroadcastDelayMS, - RewardStackPolicy: input.RewardStackPolicy, - Levels: levelsToClient(input.Levels), - GiftEnergyRules: energyRulesToClient(input.GiftEnergyRules), - } -} - -func levelsFromClient(input []roomclient.RoomTreasureLevelConfig) []RoomTreasureLevelConfig { - out := make([]RoomTreasureLevelConfig, 0, len(input)) - for _, level := range input { - out = append(out, RoomTreasureLevelConfig{ - Level: level.Level, - EnergyThreshold: level.EnergyThreshold, - CoverURL: level.CoverURL, - AnimationURL: level.AnimationURL, - OpeningAnimationURL: level.OpeningAnimationURL, - OpenedImageURL: level.OpenedImageURL, - InRoomRewards: rewardsFromClient(level.InRoomRewards), - Top1Rewards: rewardsFromClient(level.Top1Rewards), - IgniterRewards: rewardsFromClient(level.IgniterRewards), - }) - } - return out -} - -func levelsToClient(input []RoomTreasureLevelConfig) []roomclient.RoomTreasureLevelConfig { - out := make([]roomclient.RoomTreasureLevelConfig, 0, len(input)) - for _, level := range input { - out = append(out, roomclient.RoomTreasureLevelConfig{ - Level: level.Level, - EnergyThreshold: level.EnergyThreshold, - CoverURL: level.CoverURL, - AnimationURL: level.AnimationURL, - OpeningAnimationURL: level.OpeningAnimationURL, - OpenedImageURL: level.OpenedImageURL, - InRoomRewards: rewardsToClient(level.InRoomRewards), - Top1Rewards: rewardsToClient(level.Top1Rewards), - IgniterRewards: rewardsToClient(level.IgniterRewards), - }) - } - return out -} - -func rewardsFromClient(input []roomclient.RoomTreasureRewardItem) []RoomTreasureRewardItem { - out := make([]RoomTreasureRewardItem, 0, len(input)) - for _, reward := range input { - out = append(out, RoomTreasureRewardItem{ - RewardItemID: reward.RewardItemID, - ResourceGroupID: reward.ResourceGroupID, - Weight: reward.Weight, - DisplayName: reward.DisplayName, - IconURL: reward.IconURL, - }) - } - return out -} - -func rewardsToClient(input []RoomTreasureRewardItem) []roomclient.RoomTreasureRewardItem { - out := make([]roomclient.RoomTreasureRewardItem, 0, len(input)) - for _, reward := range input { - out = append(out, roomclient.RoomTreasureRewardItem{ - RewardItemID: reward.RewardItemID, - ResourceGroupID: reward.ResourceGroupID, - Weight: reward.Weight, - DisplayName: reward.DisplayName, - IconURL: reward.IconURL, - }) - } - return out -} - -func energyRulesFromClient(input []roomclient.GiftEnergyRuleConfig) []GiftEnergyRuleConfig { - out := make([]GiftEnergyRuleConfig, 0, len(input)) - for _, rule := range input { - out = append(out, GiftEnergyRuleConfig{ - RuleID: rule.RuleID, - GiftID: rule.GiftID, - GiftTypeCode: rule.GiftTypeCode, - MultiplierPPM: rule.MultiplierPPM, - FixedEnergy: rule.FixedEnergy, - Excluded: rule.Excluded, - }) - } - return out -} - -func energyRulesToClient(input []GiftEnergyRuleConfig) []roomclient.GiftEnergyRuleConfig { - out := make([]roomclient.GiftEnergyRuleConfig, 0, len(input)) - for _, rule := range input { - out = append(out, roomclient.GiftEnergyRuleConfig{ - RuleID: rule.RuleID, - GiftID: rule.GiftID, - GiftTypeCode: rule.GiftTypeCode, - MultiplierPPM: rule.MultiplierPPM, - FixedEnergy: rule.FixedEnergy, - Excluded: rule.Excluded, - }) - } - return out -} diff --git a/server/admin/internal/modules/roomtreasure/service_test.go b/server/admin/internal/modules/roomtreasure/service_test.go deleted file mode 100644 index 07d7001c..00000000 --- a/server/admin/internal/modules/roomtreasure/service_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package roomtreasure - -import ( - "errors" - "testing" -) - -func TestNormalizeConfigDefaultsAndSortsLevels(t *testing.T) { - config, err := normalizeConfig(RoomTreasureConfig{ - AppCode: "lalu", - OpenDelayMS: defaultOpenDelayMS, - Levels: []RoomTreasureLevelConfig{ - {Level: 2, EnergyThreshold: 300}, - {Level: 1, EnergyThreshold: 100}, - {Level: 3, EnergyThreshold: 600}, - {Level: 4, EnergyThreshold: 1_000}, - {Level: 5, EnergyThreshold: 1_500}, - {Level: 6, EnergyThreshold: 2_100}, - {Level: 7, EnergyThreshold: 2_800}, - }, - }) - if err != nil { - t.Fatalf("normalizeConfig failed: %v", err) - } - if config.EnergySource != defaultEnergySource || config.OpenDelayMS != defaultOpenDelayMS || config.BroadcastScope != defaultBroadcastScope { - t.Fatalf("default fields mismatch: %+v", config) - } - if config.Levels[0].Level != 1 || config.Levels[6].Level != 7 { - t.Fatalf("levels should be sorted by level: %+v", config.Levels) - } -} - -func TestDefaultConfigKeepsOperationalDefaults(t *testing.T) { - config, err := normalizeConfig(defaultConfig("lalu")) - if err != nil { - t.Fatalf("normalizeConfig(defaultConfig) failed: %v", err) - } - if !config.BroadcastEnabled || config.OpenDelayMS != defaultOpenDelayMS || len(config.Levels) != roomTreasureLevelCount { - t.Fatalf("default config mismatch: %+v", config) - } -} - -func TestNormalizeConfigRejectsInvalidLevels(t *testing.T) { - tests := []struct { - name string - config RoomTreasureConfig - }{ - {name: "missing_level", config: RoomTreasureConfig{AppCode: "lalu", Levels: []RoomTreasureLevelConfig{{Level: 1, EnergyThreshold: 1}}}}, - {name: "duplicate", config: RoomTreasureConfig{AppCode: "lalu", Levels: []RoomTreasureLevelConfig{ - {Level: 1, EnergyThreshold: 1}, {Level: 1, EnergyThreshold: 2}, {Level: 3, EnergyThreshold: 3}, {Level: 4, EnergyThreshold: 4}, {Level: 5, EnergyThreshold: 5}, {Level: 6, EnergyThreshold: 6}, {Level: 7, EnergyThreshold: 7}, - }}}, - {name: "zero_threshold", config: RoomTreasureConfig{AppCode: "lalu", Levels: []RoomTreasureLevelConfig{ - {Level: 1, EnergyThreshold: 0}, {Level: 2, EnergyThreshold: 2}, {Level: 3, EnergyThreshold: 3}, {Level: 4, EnergyThreshold: 4}, {Level: 5, EnergyThreshold: 5}, {Level: 6, EnergyThreshold: 6}, {Level: 7, EnergyThreshold: 7}, - }}}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - _, err := normalizeConfig(test.config) - if !errors.Is(err, ErrInvalidArgument) { - t.Fatalf("normalizeConfig should reject %s with ErrInvalidArgument, got %v", test.name, err) - } - }) - } -} - -func TestNormalizeConfigRejectsIncompleteRewardAndEnergyRule(t *testing.T) { - config := defaultConfig("lalu") - config.Levels[0].InRoomRewards = []RoomTreasureRewardItem{{ResourceGroupID: 0, Weight: 100}} - if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { - t.Fatalf("reward without resource group should be invalid, got %v", err) - } - - config = defaultConfig("lalu") - config.GiftEnergyRules = []GiftEnergyRuleConfig{{GiftID: "gift-1"}} - if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { - t.Fatalf("energy rule without multiplier or fixed energy should be invalid, got %v", err) - } -} diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 877c122b..9ebf7071 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -86,6 +86,7 @@ var defaultPermissions = []model.Permission{ {Name: "币商进货", Code: "coin-seller:stock-credit", Kind: "button"}, {Name: "币商工资兑换比例", Code: "coin-seller:exchange-rate", Kind: "button"}, {Name: "金币流水查看", Code: "coin-ledger:view", Kind: "menu"}, + {Name: "币商流水查看", Code: "coin-seller-ledger:view", Kind: "menu"}, {Name: "金币增减查看", Code: "coin-adjustment:view", Kind: "menu"}, {Name: "金币增减创建", Code: "coin-adjustment:create", Kind: "button"}, {Name: "举报列表查看", Code: "report:view", Kind: "menu"}, @@ -114,8 +115,8 @@ var defaultPermissions = []model.Permission{ {Name: "七日签到更新", Code: "seven-day-checkin:update", Kind: "button"}, {Name: "幸运礼物查看", Code: "lucky-gift:view", Kind: "menu"}, {Name: "幸运礼物更新", Code: "lucky-gift:update", Kind: "button"}, - {Name: "房间宝箱查看", Code: "room-treasure:view", Kind: "menu"}, - {Name: "房间宝箱更新", Code: "room-treasure:update", Kind: "button"}, + {Name: "房间火箭查看", Code: "room-rocket:view", Kind: "menu"}, + {Name: "房间火箭更新", Code: "room-rocket:update", Kind: "button"}, {Name: "用户榜单查看", Code: "user-leaderboard:view", Kind: "menu"}, {Name: "红包配置查看", Code: "red-packet:view", Kind: "menu"}, {Name: "红包配置更新", Code: "red-packet:update", Kind: "button"}, @@ -251,16 +252,17 @@ func (s *Store) seedMenus() error { {ParentID: &resourceID, Title: "资源赠送", Code: "resource-grant-list", Path: "/resource-grants", Icon: "send", PermissionCode: "resource-grant:view", Sort: 71, Visible: true}, {ParentID: &resourceID, Title: "表情包列表", Code: "emoji-pack-list", Path: "/emoji-packs", Icon: "image", PermissionCode: "emoji-pack:view", Sort: 72, Visible: true}, {ParentID: &operationsID, Title: "金币流水", Code: "operation-coin-ledger", Path: "/operations/coin-ledger", Icon: "receipt", PermissionCode: "coin-ledger:view", Sort: 68, Visible: true}, - {ParentID: &operationsID, Title: "金币增减", Code: "operation-coin-adjustment", Path: "/operations/coin-adjustments", Icon: "wallet", PermissionCode: "coin-adjustment:view", Sort: 69, Visible: true}, - {ParentID: &operationsID, Title: "幸运礼物", Code: "lucky-gift", Path: "/operations/lucky-gift", Icon: "redeem", PermissionCode: "lucky-gift:view", Sort: 70, Visible: true}, - {ParentID: &operationsID, Title: "举报列表", Code: "operation-reports", Path: "/operations/reports", Icon: "flag", PermissionCode: "report:view", Sort: 71, Visible: true}, - {ParentID: &operationsID, Title: "礼物钻石", Code: "operation-gift-diamond", Path: "/operations/gift-diamonds", Icon: "diamond", PermissionCode: "gift-diamond:view", Sort: 72, Visible: true}, + {ParentID: &operationsID, Title: "币商流水", Code: "operation-coin-seller-ledger", Path: "/operations/coin-seller-ledger", Icon: "receipt", PermissionCode: "coin-seller-ledger:view", Sort: 69, Visible: true}, + {ParentID: &operationsID, Title: "金币增减", Code: "operation-coin-adjustment", Path: "/operations/coin-adjustments", Icon: "wallet", PermissionCode: "coin-adjustment:view", Sort: 70, Visible: true}, + {ParentID: &operationsID, Title: "幸运礼物", Code: "lucky-gift", Path: "/operations/lucky-gift", Icon: "redeem", PermissionCode: "lucky-gift:view", Sort: 71, Visible: true}, + {ParentID: &operationsID, Title: "举报列表", Code: "operation-reports", Path: "/operations/reports", Icon: "flag", PermissionCode: "report:view", Sort: 72, Visible: true}, + {ParentID: &operationsID, Title: "礼物钻石", Code: "operation-gift-diamond", Path: "/operations/gift-diamonds", Icon: "diamond", PermissionCode: "gift-diamond:view", Sort: 73, Visible: true}, {ParentID: &paymentID, Title: "账单列表", Code: "payment-bill-list", Path: "/payment/bills", Icon: "receipt", PermissionCode: "payment-bill:view", Sort: 68, Visible: true}, {ParentID: &activityID, Title: "每日任务", Code: "daily-task-list", Path: "/activities/daily-tasks", Icon: "task", PermissionCode: "daily-task:view", Sort: 69, Visible: true}, {ParentID: &activityID, Title: "注册奖励", Code: "registration-reward", Path: "/activities/registration-reward", Icon: "gift", PermissionCode: "registration-reward:view", Sort: 70, Visible: true}, {ParentID: &activityID, Title: "成就配置", Code: "achievement-config", Path: "/activities/achievements", Icon: "military_tech", PermissionCode: "achievement:view", Sort: 71, Visible: true}, {ParentID: &activityID, Title: "七日签到", Code: "seven-day-checkin", Path: "/activities/seven-day-checkin", Icon: "event_available", PermissionCode: "seven-day-checkin:view", Sort: 72, Visible: true}, - {ParentID: &activityID, Title: "房间宝箱", Code: "room-treasure", Path: "/activities/room-treasure", Icon: "redeem", PermissionCode: "room-treasure:view", Sort: 73, Visible: true}, + {ParentID: &activityID, Title: "房间火箭", Code: "room-rocket", Path: "/activities/room-rocket", Icon: "redeem", PermissionCode: "room-rocket:view", Sort: 73, Visible: true}, {ParentID: &activityID, Title: "用户榜单", Code: "user-leaderboard", Path: "/activities/user-leaderboards", Icon: "leaderboard", PermissionCode: "user-leaderboard:view", Sort: 74, Visible: true}, {ParentID: &activityID, Title: "红包配置", Code: "red-packet", Path: "/activities/red-packets", Icon: "redeem", PermissionCode: "red-packet:view", Sort: 75, Visible: true}, {ParentID: &activityID, Title: "VIP配置", Code: "vip-config", Path: "/activities/vip-config", Icon: "workspace_premium", PermissionCode: "vip-config:view", Sort: 76, Visible: true}, @@ -501,13 +503,13 @@ func defaultRolePermissionCodes(code string) []string { "agency:view", "agency:create", "agency:status", "bd:view", "bd:create", "bd:update", "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", "coin-seller:exchange-rate", - "coin-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", + "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", "lucky-gift:view", "lucky-gift:update", "game:view", "game:create", "game:update", "game:status", "game:delete", "daily-task:view", "daily-task:create", "daily-task:update", "daily-task:status", "achievement:view", "achievement:create", "achievement:update", "seven-day-checkin:view", "seven-day-checkin:update", - "room-treasure:view", "room-treasure:update", + "room-rocket:view", "room-rocket:update", "red-packet:view", "red-packet:update", "vip-config:view", "vip-config:update", "vip-config:grant", "log:view", @@ -515,7 +517,7 @@ func defaultRolePermissionCodes(code string) []string { "upload:create", } case "auditor": - return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-treasure:view", "red-packet:view", "vip-config:view", "role:view", "permission:view", "job:view"} + return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view", "role:view", "permission:view", "job:view"} case "readonly": return []string{ "overview:view", @@ -544,6 +546,7 @@ func defaultRolePermissionCodes(code string) []string { "bd:view", "coin-seller:view", "coin-ledger:view", + "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", @@ -554,7 +557,7 @@ func defaultRolePermissionCodes(code string) []string { "daily-task:view", "achievement:view", "seven-day-checkin:view", - "room-treasure:view", + "room-rocket:view", "red-packet:view", "vip-config:view", "role:view", @@ -589,18 +592,18 @@ func defaultRolePermissionMigrationCodes(code string) []string { "region:view", "region:create", "region:update", "region:status", "host-agency-policy:view", "host-agency-policy:create", "host-agency-policy:update", "host-agency-policy:delete", "host-agency-policy:publish", "team-salary-policy:view", "team-salary-policy:create", "team-salary-policy:update", "team-salary-policy:delete", "host-salary-settlement:view", "host-salary-settlement:settle", "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", "coin-seller:exchange-rate", - "coin-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", + "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", "lucky-gift:view", "lucky-gift:update", "game:view", "game:create", "game:update", "game:status", "game:delete", "daily-task:view", "daily-task:create", "daily-task:update", "daily-task:status", "achievement:view", "achievement:create", "achievement:update", "seven-day-checkin:view", "seven-day-checkin:update", - "room-treasure:view", "room-treasure:update", + "room-rocket:view", "room-rocket:update", "red-packet:view", "red-packet:update", "vip-config:view", "vip-config:update", "vip-config:grant", } case "auditor", "readonly": - return []string{"level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-treasure:view", "red-packet:view", "vip-config:view"} + return []string{"level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view"} default: return nil } diff --git a/server/admin/internal/router/router.go b/server/admin/internal/router/router.go index b8cf75d4..40a4b2bc 100644 --- a/server/admin/internal/router/router.go +++ b/server/admin/internal/router/router.go @@ -33,7 +33,7 @@ import ( reportmodule "hyapp-admin-server/internal/modules/report" resourcemodule "hyapp-admin-server/internal/modules/resource" "hyapp-admin-server/internal/modules/roomadmin" - "hyapp-admin-server/internal/modules/roomtreasure" + "hyapp-admin-server/internal/modules/roomrocket" "hyapp-admin-server/internal/modules/search" "hyapp-admin-server/internal/modules/sevendaycheckin" "hyapp-admin-server/internal/modules/teamsalarypolicy" @@ -78,7 +78,7 @@ type Handlers struct { RegionBlock *regionblock.Handler Resource *resourcemodule.Handler RoomAdmin *roomadmin.Handler - RoomTreasure *roomtreasure.Handler + RoomRocket *roomrocket.Handler Search *search.Handler SevenDayCheckIn *sevendaycheckin.Handler TeamSalaryPolicy *teamsalarypolicy.Handler @@ -119,7 +119,7 @@ func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { gamemanagement.RegisterRoutes(protected, h.Game) giftdiamond.RegisterRoutes(protected, h.GiftDiamond) roomadmin.RegisterRoutes(protected, h.RoomAdmin) - roomtreasure.RegisterRoutes(protected, h.RoomTreasure) + roomrocket.RegisterRoutes(protected, h.RoomRocket) dashboard.RegisterRoutes(protected, h.Dashboard) hostagencypolicy.RegisterRoutes(protected, h.HostAgencyPolicy) hostsalarysettlement.RegisterRoutes(protected, h.HostSalarySettlement) diff --git a/server/admin/migrations/018_room_treasure_navigation.sql b/server/admin/migrations/018_room_treasure_navigation.sql index e831fe11..26f7a9e4 100644 --- a/server/admin/migrations/018_room_treasure_navigation.sql +++ b/server/admin/migrations/018_room_treasure_navigation.sql @@ -1,11 +1,11 @@ SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; --- 房间宝箱后台只维护 room-service 的低频配置,不拥有 Room Cell 运行时进度和发奖事实。 +-- 房间火箭后台只维护 room-service 的低频配置,不拥有 Room Cell 运行时进度和发奖事实。 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 - ('房间宝箱查看', 'room-treasure:view', 'menu', '', @now_ms, @now_ms), - ('房间宝箱更新', 'room-treasure:update', 'button', '', @now_ms, @now_ms) + ('房间火箭查看', 'room-rocket:view', 'menu', '', @now_ms, @now_ms), + ('房间火箭更新', 'room-rocket:update', 'button', '', @now_ms, @now_ms) ON DUPLICATE KEY UPDATE name = VALUES(name), kind = VALUES(kind), @@ -24,7 +24,7 @@ ON DUPLICATE KEY UPDATE 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, '房间宝箱', 'room-treasure', '/activities/room-treasure', 'redeem', 'room-treasure:view', 73, TRUE, @now_ms, @now_ms +SELECT parent.id, '房间火箭', 'room-rocket', '/activities/room-rocket', 'redeem', 'room-rocket:view', 73, TRUE, @now_ms, @now_ms FROM admin_menus parent WHERE parent.code = 'activities' ON DUPLICATE KEY UPDATE @@ -42,18 +42,29 @@ 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 ('room-treasure:view', 'room-treasure:update'); + AND admin_permission.code IN ('room-rocket:view', 'room-rocket: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 ('room-treasure:view', 'room-treasure:update'); + AND admin_permission.code IN ('room-rocket:view', 'room-rocket: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 = 'room-treasure:view'; + AND admin_permission.code = 'room-rocket:view'; + +DELETE role_permission +FROM admin_role_permissions role_permission +JOIN admin_permissions permission ON permission.id = role_permission.permission_id +WHERE permission.code IN ('room-treasure:view', 'room-treasure:update'); + +DELETE FROM admin_menus +WHERE code = 'room-treasure'; + +DELETE FROM admin_permissions +WHERE code IN ('room-treasure:view', 'room-treasure:update'); diff --git a/server/admin/migrations/035_coin_seller_ledger_navigation.sql b/server/admin/migrations/035_coin_seller_ledger_navigation.sql new file mode 100644 index 00000000..1c9498b2 --- /dev/null +++ b/server/admin/migrations/035_coin_seller_ledger_navigation.sql @@ -0,0 +1,56 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 币商流水只读 wallet-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 + ('币商流水查看', 'coin-seller-ledger:view', 'menu', '', @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, '运营管理', 'operations', '', 'operations', '', 68, 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, '币商流水', 'operation-coin-seller-ledger', '/operations/coin-seller-ledger', 'receipt', 'coin-seller-ledger:view', 69, TRUE, @now_ms, @now_ms +FROM admin_menus parent +WHERE parent.code = 'operations' +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; + +UPDATE admin_menus child +JOIN admin_menus parent ON parent.code = 'operations' AND child.parent_id = parent.id +SET child.sort = CASE child.code + WHEN 'operation-coin-adjustment' THEN 70 + WHEN 'lucky-gift' THEN 71 + WHEN 'operation-reports' THEN 72 + WHEN 'operation-gift-diamond' THEN 73 + ELSE child.sort +END, +child.updated_at_ms = @now_ms +WHERE child.code IN ('operation-coin-adjustment', 'lucky-gift', 'operation-reports', 'operation-gift-diamond'); + +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 ('platform-admin', 'ops-admin', 'auditor', 'readonly') + AND admin_permission.code = 'coin-seller-ledger:view'; diff --git a/services/activity-service/internal/domain/broadcast/broadcast.go b/services/activity-service/internal/domain/broadcast/broadcast.go index 503275fe..61ef4106 100644 --- a/services/activity-service/internal/domain/broadcast/broadcast.go +++ b/services/activity-service/internal/domain/broadcast/broadcast.go @@ -14,8 +14,10 @@ const ( TypeSuperGift = "super_gift" // TypeRedPacket 是红包入口播报,资金事实必须由 wallet/red-packet 领域持久化。 TypeRedPacket = "red_packet" - // TypeRoomTreasure 是语音房宝箱满能量后的开箱倒计时播报。 - TypeRoomTreasure = "room_treasure" + // TypeRoomRocket 是语音房火箭燃料满后的发射倒计时播报。 + TypeRoomRocket = "room_rocket" + // TypeRoomRocketReward 是语音房火箭发射后中奖明细房间播报。 + TypeRoomRocketReward = "room_rocket_reward_granted" // TypeRoomPasswordChanged 是锁房状态变化的区域通知,客户端用它刷新房间锁状态入口。 TypeRoomPasswordChanged = "room_password_changed" // TypeLuckyGiftBigWin 是幸运礼物中奖区域飘屏;当前默认 1 倍及以上即进入播报 outbox。 diff --git a/services/activity-service/internal/service/broadcast/service.go b/services/activity-service/internal/service/broadcast/service.go index 087726c6..6596d8e7 100644 --- a/services/activity-service/internal/service/broadcast/service.go +++ b/services/activity-service/internal/service/broadcast/service.go @@ -46,14 +46,14 @@ type RegionSource interface { ListActiveRegionIDs(ctx context.Context) ([]int64, error) } -// SenderProfileSource 只读取红包 IM 展示所需的公开资料快照。 +// SenderProfileSource 只读取播报 IM 展示所需的公开资料快照。 // 资金和红包状态仍来自 wallet outbox,用户资料 owner 仍是 user-service。 type SenderProfileSource interface { GetSenderProfile(ctx context.Context, userID int64) (SenderProfile, error) } -// SenderProfile 是红包 IM payload 的发送者展示字段。 -// activity-service 不持久化该资料,只在消费 wallet 事实时组装一次播报消息。 +// SenderProfile 是播报 IM payload 的发送者展示字段。 +// activity-service 不持久化该资料,只在消费事实时组装一次播报消息。 type SenderProfile struct { UserID int64 Account string @@ -298,21 +298,24 @@ func (s *Service) ProcessPendingBroadcasts(ctx context.Context, options WorkerOp } // HandleRoomEvent 把已提交的 room outbox 事实转换为服务端播报。 -// 礼物、宝箱和锁房只使用 room outbox 中的稳定事实,避免把展示策略侵入 Room Cell 主链路。 +// 礼物、火箭和锁房只使用 room outbox 中的稳定事实,避免把展示策略侵入 Room Cell 主链路。 func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { if envelope == nil { return broadcastdomain.ConsumeRoomEventResult{}, xerr.New(xerr.InvalidArgument, "room event envelope is required") } eventCtx := appcode.WithContext(ctx, envelope.GetAppCode()) result := broadcastdomain.ConsumeRoomEventResult{EventID: envelope.GetEventId(), Status: broadcastdomain.StatusSkipped} - if envelope.GetEventType() == "RoomTreasureCountdownStarted" { - return s.handleRoomTreasureCountdown(eventCtx, envelope) + if envelope.GetEventType() == "RoomRocketIgnited" { + return s.handleRoomRocketIgnited(eventCtx, envelope) + } + if envelope.GetEventType() == "RoomRocketRewardGranted" { + return s.handleRoomRocketRewardGranted(eventCtx, envelope) } if envelope.GetEventType() == "RoomPasswordChanged" { return s.handleRoomPasswordChanged(eventCtx, envelope) } if envelope.GetEventType() != "RoomGiftSent" { - // 当前只消费礼物、房间宝箱和锁房事实;未来运营事件应显式增加事件类型分支和测试。 + // 当前只消费礼物、房间火箭和锁房事实;未来运营事件应显式增加事件类型分支和测试。 return result, nil } var gift roomeventsv1.RoomGiftSent @@ -378,15 +381,15 @@ func (s *Service) handleRoomPasswordChanged(ctx context.Context, envelope *roome }, nil } -func (s *Service) handleRoomTreasureCountdown(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { +func (s *Service) handleRoomRocketIgnited(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { result := broadcastdomain.ConsumeRoomEventResult{EventID: envelope.GetEventId(), Status: broadcastdomain.StatusSkipped} - var treasure roomeventsv1.RoomTreasureCountdownStarted - if err := proto.Unmarshal(envelope.GetBody(), &treasure); err != nil { + var rocket roomeventsv1.RoomRocketIgnited + if err := proto.Unmarshal(envelope.GetBody(), &rocket); err != nil { return broadcastdomain.ConsumeRoomEventResult{}, err } - switch treasure.GetBroadcastScope() { + switch rocket.GetBroadcastScope() { case broadcastdomain.ScopeRegion: - if treasure.GetVisibleRegionId() <= 0 { + if rocket.GetVisibleRegionId() <= 0 { return result, nil } case broadcastdomain.ScopeGlobal: @@ -394,23 +397,31 @@ func (s *Service) handleRoomTreasureCountdown(ctx context.Context, envelope *roo return result, nil } - broadcastEventID := roomTreasureBroadcastEventID(envelope, &treasure) - payloadJSON, err := roomTreasurePayload(envelope, &treasure, broadcastEventID, s.now().UTC().UnixMilli()) + broadcastEventID := roomRocketBroadcastEventID(envelope, &rocket) + igniterProfile := SenderProfile{UserID: rocket.GetIgniterUserId()} + if rocket.GetIgniterUserId() > 0 && s.senderProfileSource != nil { + profile, err := s.senderProfileSource.GetSenderProfile(ctx, rocket.GetIgniterUserId()) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + igniterProfile = profile + } + payloadJSON, err := roomRocketPayload(envelope, &rocket, broadcastEventID, s.now().UTC().UnixMilli(), igniterProfile) if err != nil { return broadcastdomain.ConsumeRoomEventResult{}, err } var published broadcastdomain.PublishResult - if treasure.GetBroadcastScope() == broadcastdomain.ScopeGlobal { + if rocket.GetBroadcastScope() == broadcastdomain.ScopeGlobal { published, err = s.PublishGlobalBroadcast(ctx, PublishInput{ EventID: broadcastEventID, - BroadcastType: broadcastdomain.TypeRoomTreasure, + BroadcastType: broadcastdomain.TypeRoomRocket, PayloadJSON: payloadJSON, }) } else { published, err = s.PublishRegionBroadcast(ctx, PublishInput{ EventID: broadcastEventID, - BroadcastType: broadcastdomain.TypeRoomTreasure, - RegionID: treasure.GetVisibleRegionId(), + BroadcastType: broadcastdomain.TypeRoomRocket, + RegionID: rocket.GetVisibleRegionId(), PayloadJSON: payloadJSON, }) } @@ -425,6 +436,55 @@ func (s *Service) handleRoomTreasureCountdown(ctx context.Context, envelope *roo }, nil } +func (s *Service) handleRoomRocketRewardGranted(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (broadcastdomain.ConsumeRoomEventResult, error) { + result := broadcastdomain.ConsumeRoomEventResult{EventID: envelope.GetEventId(), Status: broadcastdomain.StatusSkipped} + var event roomeventsv1.RoomRocketRewardGranted + if err := proto.Unmarshal(envelope.GetBody(), &event); err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + if envelope.GetRoomId() == "" || event.GetRocketId() == "" || len(event.GetRewards()) == 0 { + return result, nil + } + + profiles := make(map[int64]SenderProfile, len(event.GetRewards())) + if s.senderProfileSource != nil { + for _, reward := range event.GetRewards() { + userID := reward.GetUserId() + if userID <= 0 { + continue + } + if _, exists := profiles[userID]; exists { + continue + } + profile, err := s.senderProfileSource.GetSenderProfile(ctx, userID) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + profiles[userID] = profile + } + } + + broadcastEventID := roomRocketRewardBroadcastEventID(envelope, &event) + payloadJSON, err := roomRocketRewardPayload(envelope, &event, broadcastEventID, s.now().UTC().UnixMilli(), profiles) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + published, err := s.PublishRoomBroadcast(ctx, envelope.GetRoomId(), PublishInput{ + EventID: broadcastEventID, + BroadcastType: broadcastdomain.TypeRoomRocketReward, + PayloadJSON: payloadJSON, + }) + if err != nil { + return broadcastdomain.ConsumeRoomEventResult{}, err + } + return broadcastdomain.ConsumeRoomEventResult{ + EventID: envelope.GetEventId(), + Status: published.Status, + BroadcastEventID: published.EventID, + BroadcastCreated: published.Created, + }, nil +} + // WorkerOptions 描述一次 worker 批处理请求;cron 和常驻 worker 都走同一套参数归一化。 type WorkerOptions struct { WorkerID string @@ -547,11 +607,18 @@ func superGiftPayload(envelope *roomeventsv1.EventEnvelope, gift *roomeventsv1.R return string(encoded), err } -func roomTreasureBroadcastEventID(envelope *roomeventsv1.EventEnvelope, treasure *roomeventsv1.RoomTreasureCountdownStarted) string { - if strings.TrimSpace(treasure.GetBoxId()) != "" { - return fmt.Sprintf("room_treasure_broadcast:%s:%s", envelope.GetRoomId(), treasure.GetBoxId()) +func roomRocketBroadcastEventID(envelope *roomeventsv1.EventEnvelope, rocket *roomeventsv1.RoomRocketIgnited) string { + if strings.TrimSpace(rocket.GetRocketId()) != "" { + return fmt.Sprintf("room_rocket_broadcast:%s:%s", envelope.GetRoomId(), rocket.GetRocketId()) } - return "room_treasure_broadcast:" + envelope.GetEventId() + return "room_rocket_broadcast:" + envelope.GetEventId() +} + +func roomRocketRewardBroadcastEventID(envelope *roomeventsv1.EventEnvelope, event *roomeventsv1.RoomRocketRewardGranted) string { + if strings.TrimSpace(event.GetRocketId()) != "" { + return fmt.Sprintf("room_rocket_reward:%s:%s", envelope.GetRoomId(), event.GetRocketId()) + } + return "room_rocket_reward:" + envelope.GetEventId() } func roomPasswordChangedBroadcastEventID(envelope *roomeventsv1.EventEnvelope) string { @@ -580,25 +647,33 @@ func roomPasswordChangedPayload(envelope *roomeventsv1.EventEnvelope, event *roo return string(encoded), err } -func roomTreasurePayload(envelope *roomeventsv1.EventEnvelope, treasure *roomeventsv1.RoomTreasureCountdownStarted, eventID string, sentAtMS int64) (string, error) { +func roomRocketPayload(envelope *roomeventsv1.EventEnvelope, rocket *roomeventsv1.RoomRocketIgnited, eventID string, sentAtMS int64, igniter SenderProfile) (string, error) { payload := map[string]any{ - "event_id": eventID, - "broadcast_type": broadcastdomain.TypeRoomTreasure, - "scope": treasure.GetBroadcastScope(), - "app_code": envelope.GetAppCode(), - "region_id": treasure.GetVisibleRegionId(), - "room_id": envelope.GetRoomId(), - "box_id": treasure.GetBoxId(), - "level": treasure.GetLevel(), - "open_at_ms": treasure.GetOpenAtMs(), - "top1_user_id": treasure.GetTop1UserId(), - "igniter_user_id": treasure.GetIgniterUserId(), - "sent_at_ms": sentAtMS, - "room_version": envelope.GetRoomVersion(), - "source_event_id": envelope.GetEventId(), - "current_progress": treasure.GetCurrentProgress(), - "energy_threshold": treasure.GetEnergyThreshold(), - "countdown_started_at_ms": treasure.GetCountdownStartedAtMs(), + "event_id": eventID, + "broadcast_type": broadcastdomain.TypeRoomRocket, + "scope": rocket.GetBroadcastScope(), + "app_code": envelope.GetAppCode(), + "region_id": rocket.GetVisibleRegionId(), + "room_id": envelope.GetRoomId(), + "room_short_id": rocket.GetRoomShortId(), + "rocket_id": rocket.GetRocketId(), + "rocket_level": rocket.GetLevel(), + "rocket_cover_url": rocket.GetRocketCoverUrl(), + "launch_at_ms": rocket.GetLaunchAtMs(), + "top1_user_id": rocket.GetTop1UserId(), + "igniter_user_id": rocket.GetIgniterUserId(), + "igniter": map[string]any{ + "user_id": fmt.Sprintf("%d", rocket.GetIgniterUserId()), + "short_id": strings.TrimSpace(igniter.Account), + "nickname": strings.TrimSpace(igniter.Nickname), + "avatar": strings.TrimSpace(igniter.Avatar), + }, + "sent_at_ms": sentAtMS, + "room_version": envelope.GetRoomVersion(), + "source_event_id": envelope.GetEventId(), + "current_fuel": rocket.GetCurrentFuel(), + "fuel_threshold": rocket.GetFuelThreshold(), + "ignited_at_ms": rocket.GetIgnitedAtMs(), "action": map[string]any{ "type": "enter_room", "room_id": envelope.GetRoomId(), @@ -608,6 +683,45 @@ func roomTreasurePayload(envelope *roomeventsv1.EventEnvelope, treasure *roomeve return string(encoded), err } +func roomRocketRewardPayload(envelope *roomeventsv1.EventEnvelope, event *roomeventsv1.RoomRocketRewardGranted, eventID string, sentAtMS int64, profiles map[int64]SenderProfile) (string, error) { + rewards := make([]map[string]any, 0, len(event.GetRewards())) + for _, reward := range event.GetRewards() { + userID := reward.GetUserId() + profile := profiles[userID] + rewards = append(rewards, map[string]any{ + "reward_role": reward.GetRewardRole(), + "user_id": fmt.Sprintf("%d", userID), + "user": map[string]any{ + "user_id": fmt.Sprintf("%d", userID), + "short_id": strings.TrimSpace(profile.Account), + "nickname": strings.TrimSpace(profile.Nickname), + "avatar": strings.TrimSpace(profile.Avatar), + }, + "reward_item_id": reward.GetRewardItemId(), + "resource_group_id": reward.GetResourceGroupId(), + "display_name": reward.GetDisplayName(), + "icon_url": reward.GetIconUrl(), + "grant_id": reward.GetGrantId(), + "status": reward.GetStatus(), + }) + } + payload := map[string]any{ + "event_id": eventID, + "broadcast_type": broadcastdomain.TypeRoomRocketReward, + "scope": broadcastdomain.ScopeRoom, + "app_code": envelope.GetAppCode(), + "room_id": envelope.GetRoomId(), + "rocket_id": event.GetRocketId(), + "rocket_level": event.GetLevel(), + "rewards": rewards, + "sent_at_ms": sentAtMS, + "room_version": envelope.GetRoomVersion(), + "source_event_id": envelope.GetEventId(), + } + encoded, err := json.Marshal(payload) + return string(encoded), err +} + func trimError(value string) string { value = strings.TrimSpace(value) if len(value) > 512 { diff --git a/services/gateway-service/internal/client/room_client.go b/services/gateway-service/internal/client/room_client.go index 7f514d34..a0f0dc26 100644 --- a/services/gateway-service/internal/client/room_client.go +++ b/services/gateway-service/internal/client/room_client.go @@ -51,7 +51,7 @@ type RoomQueryClient interface { GetCurrentRoom(ctx context.Context, req *roomv1.GetCurrentRoomRequest) (*roomv1.GetCurrentRoomResponse, error) GetRoomSnapshot(ctx context.Context, req *roomv1.GetRoomSnapshotRequest) (*roomv1.GetRoomSnapshotResponse, error) ListRoomBackgrounds(ctx context.Context, req *roomv1.ListRoomBackgroundsRequest) (*roomv1.ListRoomBackgroundsResponse, error) - GetRoomTreasure(ctx context.Context, req *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) + GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) ListRoomOnlineUsers(ctx context.Context, req *roomv1.ListRoomOnlineUsersRequest) (*roomv1.ListRoomOnlineUsersResponse, error) ListRoomBannedUsers(ctx context.Context, req *roomv1.ListRoomBannedUsersRequest) (*roomv1.ListRoomBannedUsersResponse, error) } @@ -221,8 +221,8 @@ func (c *grpcRoomQueryClient) ListRoomBackgrounds(ctx context.Context, req *room return c.client.ListRoomBackgrounds(ctx, req) } -func (c *grpcRoomQueryClient) GetRoomTreasure(ctx context.Context, req *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) { - return c.client.GetRoomTreasure(ctx, req) +func (c *grpcRoomQueryClient) GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) { + return c.client.GetRoomRocket(ctx, req) } func (c *grpcRoomQueryClient) ListRoomOnlineUsers(ctx context.Context, req *roomv1.ListRoomOnlineUsersRequest) (*roomv1.ListRoomOnlineUsersResponse, error) { diff --git a/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler_test.go b/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler_test.go index 64dea58a..1fc4402b 100644 --- a/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler_test.go +++ b/services/gateway-service/internal/transport/http/activityapi/user_leaderboard_handler_test.go @@ -116,8 +116,8 @@ func (f *fakeUserLeaderboardRoomQueryClient) GetRoomSnapshot(context.Context, *r return &roomv1.GetRoomSnapshotResponse{}, nil } -func (f *fakeUserLeaderboardRoomQueryClient) GetRoomTreasure(context.Context, *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) { - return &roomv1.GetRoomTreasureResponse{}, nil +func (f *fakeUserLeaderboardRoomQueryClient) GetRoomRocket(context.Context, *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) { + return &roomv1.GetRoomRocketResponse{}, nil } func (f *fakeUserLeaderboardRoomQueryClient) ListRoomBackgrounds(context.Context, *roomv1.ListRoomBackgroundsRequest) (*roomv1.ListRoomBackgroundsResponse, error) { diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 4a938c0a..445fa9bb 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -123,7 +123,7 @@ type RoomHandlers struct { ListRoomOnlineUsers http.HandlerFunc ListRoomBannedUsers http.HandlerFunc GetRoomGiftPanel http.HandlerFunc - GetRoomTreasure http.HandlerFunc + GetRoomRocket http.HandlerFunc FollowRoom http.HandlerFunc CreateRoom http.HandlerFunc UpdateRoomProfile http.HandlerFunc @@ -369,7 +369,7 @@ func (r routes) registerRoomRoutes() { r.profile("/rooms/{room_id}/online-users", http.MethodGet, h.ListRoomOnlineUsers) r.profile("/rooms/{room_id}/banned-users", http.MethodGet, h.ListRoomBannedUsers) r.profile("/rooms/{room_id}/gift-panel", http.MethodGet, h.GetRoomGiftPanel) - r.profile("/rooms/{room_id}/treasure", http.MethodGet, h.GetRoomTreasure) + r.profile("/rooms/{room_id}/rocket", http.MethodGet, h.GetRoomRocket) r.profile("/rooms/{room_id}/follow", "", h.FollowRoom) r.profile("/rooms/{room_id}/backgrounds", http.MethodGet, h.ListRoomBackgrounds) r.profile("/rooms/create", http.MethodPost, h.CreateRoom) diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 2fa2293c..20ed2895 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -349,7 +349,7 @@ type fakeRoomQueryClient struct { lastCurrent *roomv1.GetCurrentRoomRequest lastSnapshot *roomv1.GetRoomSnapshotRequest lastBackgrounds *roomv1.ListRoomBackgroundsRequest - lastTreasure *roomv1.GetRoomTreasureRequest + lastRocket *roomv1.GetRoomRocketRequest lastOnline *roomv1.ListRoomOnlineUsersRequest lastBannedUsers *roomv1.ListRoomBannedUsersRequest resp *roomv1.ListRoomsResponse @@ -358,7 +358,7 @@ type fakeRoomQueryClient struct { currentResp *roomv1.GetCurrentRoomResponse snapshotResp *roomv1.GetRoomSnapshotResponse backgroundsResp *roomv1.ListRoomBackgroundsResponse - treasureResp *roomv1.GetRoomTreasureResponse + rocketResp *roomv1.GetRoomRocketResponse onlineResp *roomv1.ListRoomOnlineUsersResponse bannedUsersResp *roomv1.ListRoomBannedUsersResponse err error @@ -367,7 +367,7 @@ type fakeRoomQueryClient struct { currentErr error snapshotErr error backgroundsErr error - treasureErr error + rocketErr error onlineErr error bannedUsersErr error } @@ -892,15 +892,15 @@ func (f *fakeRoomQueryClient) ListRoomBackgrounds(_ context.Context, req *roomv1 return &roomv1.ListRoomBackgroundsResponse{}, nil } -func (f *fakeRoomQueryClient) GetRoomTreasure(_ context.Context, req *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) { - f.lastTreasure = req - if f.treasureErr != nil { - return nil, f.treasureErr +func (f *fakeRoomQueryClient) GetRoomRocket(_ context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) { + f.lastRocket = req + if f.rocketErr != nil { + return nil, f.rocketErr } - if f.treasureResp != nil { - return f.treasureResp, nil + if f.rocketResp != nil { + return f.rocketResp, nil } - return &roomv1.GetRoomTreasureResponse{}, nil + return &roomv1.GetRoomRocketResponse{}, nil } func (f *fakeRoomQueryClient) ListRoomOnlineUsers(_ context.Context, req *roomv1.ListRoomOnlineUsersRequest) (*roomv1.ListRoomOnlineUsersResponse, error) { diff --git a/services/gateway-service/internal/transport/http/roomapi/handler.go b/services/gateway-service/internal/transport/http/roomapi/handler.go index 6c5a534c..1eb1be17 100644 --- a/services/gateway-service/internal/transport/http/roomapi/handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/handler.go @@ -62,7 +62,7 @@ func (h *Handler) RoomHandlers() httproutes.RoomHandlers { ListRoomOnlineUsers: h.listRoomOnlineUsers, ListRoomBannedUsers: h.listRoomBannedUsers, GetRoomGiftPanel: h.getRoomGiftPanel, - GetRoomTreasure: h.getRoomTreasure, + GetRoomRocket: h.getRoomRocket, FollowRoom: h.handleRoomFollow, CreateRoom: h.createRoom, UpdateRoomProfile: h.updateRoomProfile, diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_handler.go index 915536c1..3405fac5 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler.go @@ -591,8 +591,8 @@ func (h *Handler) getRoomGiftPanel(writer http.ResponseWriter, request *http.Req }) } -// getRoomTreasure 返回房间宝箱物料配置和当前进度。 -func (h *Handler) getRoomTreasure(writer http.ResponseWriter, request *http.Request) { +// getRoomRocket 返回房间火箭物料配置和当前进度。 +func (h *Handler) getRoomRocket(writer http.ResponseWriter, request *http.Request) { if h.roomQueryClient == nil { httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") return @@ -602,7 +602,7 @@ func (h *Handler) getRoomTreasure(writer http.ResponseWriter, request *http.Requ httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } - resp, err := h.roomQueryClient.GetRoomTreasure(request.Context(), &roomv1.GetRoomTreasureRequest{ + resp, err := h.roomQueryClient.GetRoomRocket(request.Context(), &roomv1.GetRoomRocketRequest{ Meta: httpkit.RoomMeta(request, roomID, ""), RoomId: roomID, ViewerUserId: auth.UserIDFromContext(request.Context()), @@ -611,7 +611,7 @@ func (h *Handler) getRoomTreasure(writer http.ResponseWriter, request *http.Requ httpkit.WriteRPCError(writer, request, err) return } - httpkit.WriteOK(writer, request, roomTreasureDataFromProto(resp)) + httpkit.WriteOK(writer, request, roomRocketDataFromProto(resp)) } // handleRoomFollow 建立或取消当前用户对房间的关注关系。 diff --git a/services/gateway-service/internal/transport/http/roomapi/room_view.go b/services/gateway-service/internal/transport/http/roomapi/room_view.go index 34e8cbce..094097d6 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_view.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_view.go @@ -167,30 +167,30 @@ type roomGiftPanelData struct { QuantityPresets []int32 `json:"quantity_presets"` } -type roomTreasureData struct { - Enabled bool `json:"enabled"` - Levels []roomTreasureLevelData `json:"levels"` - State roomTreasureStateData `json:"state"` - BroadcastScope string `json:"broadcast_scope"` - OpenDelayMS int64 `json:"open_delay_ms"` - BroadcastDelayMS int64 `json:"broadcast_delay_ms"` - RewardStackPolicy string `json:"reward_stack_policy"` - ServerTimeMS int64 `json:"server_time_ms"` +type roomRocketData struct { + Enabled bool `json:"enabled"` + Levels []roomRocketLevelData `json:"levels"` + State roomRocketStateData `json:"state"` + BroadcastScope string `json:"broadcast_scope"` + LaunchDelayMS int64 `json:"launch_delay_ms"` + BroadcastDelayMS int64 `json:"broadcast_delay_ms"` + RewardStackPolicy string `json:"reward_stack_policy"` + ServerTimeMS int64 `json:"server_time_ms"` } -type roomTreasureLevelData struct { - Level int32 `json:"level"` - EnergyThreshold int64 `json:"energy_threshold"` - CoverURL string `json:"cover_url,omitempty"` - AnimationURL string `json:"animation_url,omitempty"` - OpeningAnimationURL string `json:"opening_animation_url,omitempty"` - OpenedImageURL string `json:"opened_image_url,omitempty"` - InRoomRewards []roomTreasureRewardData `json:"in_room_rewards"` - Top1Rewards []roomTreasureRewardData `json:"top1_rewards"` - IgniterRewards []roomTreasureRewardData `json:"igniter_rewards"` +type roomRocketLevelData struct { + Level int32 `json:"level"` + FuelThreshold int64 `json:"fuel_threshold"` + CoverURL string `json:"cover_url,omitempty"` + AnimationURL string `json:"animation_url,omitempty"` + LaunchAnimationURL string `json:"launch_animation_url,omitempty"` + LaunchedImageURL string `json:"launched_image_url,omitempty"` + InRoomRewards []roomRocketRewardData `json:"in_room_rewards"` + Top1Rewards []roomRocketRewardData `json:"top1_rewards"` + IgniterRewards []roomRocketRewardData `json:"igniter_rewards"` } -type roomTreasureRewardData struct { +type roomRocketRewardData struct { RewardItemID string `json:"reward_item_id"` ResourceGroupID int64 `json:"resource_group_id"` Weight int64 `json:"weight,omitempty"` @@ -198,23 +198,37 @@ type roomTreasureRewardData struct { IconURL string `json:"icon_url,omitempty"` } -type roomTreasureStateData struct { - CurrentLevel int32 `json:"current_level"` - CurrentProgress int64 `json:"current_progress"` - EnergyThreshold int64 `json:"energy_threshold"` - Status string `json:"status"` - CountdownStartedAtMS int64 `json:"countdown_started_at_ms,omitempty"` - OpenAtMS int64 `json:"open_at_ms,omitempty"` - OpenedAtMS int64 `json:"opened_at_ms,omitempty"` - ResetAtMS int64 `json:"reset_at_ms"` - Top1UserID string `json:"top1_user_id,omitempty"` - IgniterUserID string `json:"igniter_user_id,omitempty"` - BoxID string `json:"box_id,omitempty"` - ConfigVersion int64 `json:"config_version,omitempty"` - LastRewards []roomTreasureRewardGrantData `json:"last_rewards,omitempty"` +type roomRocketStateData struct { + CurrentLevel int32 `json:"current_level"` + CurrentFuel int64 `json:"current_fuel"` + FuelThreshold int64 `json:"fuel_threshold"` + Status string `json:"status"` + IgnitedAtMS int64 `json:"ignited_at_ms,omitempty"` + LaunchAtMS int64 `json:"launch_at_ms,omitempty"` + LaunchedAtMS int64 `json:"launched_at_ms,omitempty"` + ResetAtMS int64 `json:"reset_at_ms"` + Top1UserID string `json:"top1_user_id,omitempty"` + IgniterUserID string `json:"igniter_user_id,omitempty"` + RocketID string `json:"rocket_id,omitempty"` + ConfigVersion int64 `json:"config_version,omitempty"` + LastRewards []roomRocketRewardGrantData `json:"last_rewards,omitempty"` + PendingLaunches []roomRocketPendingLaunchData `json:"pending_launches,omitempty"` } -type roomTreasureRewardGrantData struct { +type roomRocketPendingLaunchData struct { + RocketID string `json:"rocket_id"` + Level int32 `json:"level"` + FuelThreshold int64 `json:"fuel_threshold"` + IgnitedAtMS int64 `json:"ignited_at_ms"` + LaunchAtMS int64 `json:"launch_at_ms"` + ResetAtMS int64 `json:"reset_at_ms"` + Top1UserID string `json:"top1_user_id,omitempty"` + IgniterUserID string `json:"igniter_user_id,omitempty"` + ConfigVersion int64 `json:"config_version,omitempty"` + CoverURL string `json:"cover_url,omitempty"` +} + +type roomRocketRewardGrantData struct { RewardRole string `json:"reward_role"` UserID string `json:"user_id"` RewardItemID string `json:"reward_item_id"` @@ -392,45 +406,45 @@ func createRoomDataFromProto(resp *roomv1.CreateRoomResponse) createRoomData { } } -func roomTreasureDataFromProto(resp *roomv1.GetRoomTreasureResponse) roomTreasureData { - if resp == nil || resp.GetTreasure() == nil { - return roomTreasureData{} +func roomRocketDataFromProto(resp *roomv1.GetRoomRocketResponse) roomRocketData { + if resp == nil || resp.GetRocket() == nil { + return roomRocketData{} } - treasure := resp.GetTreasure() - return roomTreasureData{ - Enabled: treasure.GetEnabled(), - Levels: roomTreasureLevelsFromProto(treasure.GetLevels()), - State: roomTreasureStateFromProto(treasure.GetState()), - BroadcastScope: treasure.GetBroadcastScope(), - OpenDelayMS: treasure.GetOpenDelayMs(), - BroadcastDelayMS: treasure.GetBroadcastDelayMs(), - RewardStackPolicy: treasure.GetRewardStackPolicy(), + rocket := resp.GetRocket() + return roomRocketData{ + Enabled: rocket.GetEnabled(), + Levels: roomRocketLevelsFromProto(rocket.GetLevels()), + State: roomRocketStateFromProto(rocket.GetState()), + BroadcastScope: rocket.GetBroadcastScope(), + LaunchDelayMS: rocket.GetLaunchDelayMs(), + BroadcastDelayMS: rocket.GetBroadcastDelayMs(), + RewardStackPolicy: rocket.GetRewardStackPolicy(), ServerTimeMS: resp.GetServerTimeMs(), } } -func roomTreasureLevelsFromProto(levels []*roomv1.RoomTreasureLevel) []roomTreasureLevelData { - out := make([]roomTreasureLevelData, 0, len(levels)) +func roomRocketLevelsFromProto(levels []*roomv1.RoomRocketLevel) []roomRocketLevelData { + out := make([]roomRocketLevelData, 0, len(levels)) for _, level := range levels { - out = append(out, roomTreasureLevelData{ - Level: level.GetLevel(), - EnergyThreshold: level.GetEnergyThreshold(), - CoverURL: level.GetCoverUrl(), - AnimationURL: level.GetAnimationUrl(), - OpeningAnimationURL: level.GetOpeningAnimationUrl(), - OpenedImageURL: level.GetOpenedImageUrl(), - InRoomRewards: roomTreasureRewardsFromProto(level.GetInRoomRewards()), - Top1Rewards: roomTreasureRewardsFromProto(level.GetTop1Rewards()), - IgniterRewards: roomTreasureRewardsFromProto(level.GetIgniterRewards()), + out = append(out, roomRocketLevelData{ + Level: level.GetLevel(), + FuelThreshold: level.GetFuelThreshold(), + CoverURL: level.GetCoverUrl(), + AnimationURL: level.GetAnimationUrl(), + LaunchAnimationURL: level.GetLaunchAnimationUrl(), + LaunchedImageURL: level.GetLaunchedImageUrl(), + InRoomRewards: roomRocketRewardsFromProto(level.GetInRoomRewards()), + Top1Rewards: roomRocketRewardsFromProto(level.GetTop1Rewards()), + IgniterRewards: roomRocketRewardsFromProto(level.GetIgniterRewards()), }) } return out } -func roomTreasureRewardsFromProto(rewards []*roomv1.RoomTreasureRewardItem) []roomTreasureRewardData { - out := make([]roomTreasureRewardData, 0, len(rewards)) +func roomRocketRewardsFromProto(rewards []*roomv1.RoomRocketRewardItem) []roomRocketRewardData { + out := make([]roomRocketRewardData, 0, len(rewards)) for _, reward := range rewards { - out = append(out, roomTreasureRewardData{ + out = append(out, roomRocketRewardData{ RewardItemID: reward.GetRewardItemId(), ResourceGroupID: reward.GetResourceGroupId(), Weight: reward.GetWeight(), @@ -441,31 +455,51 @@ func roomTreasureRewardsFromProto(rewards []*roomv1.RoomTreasureRewardItem) []ro return out } -func roomTreasureStateFromProto(state *roomv1.RoomTreasureState) roomTreasureStateData { +func roomRocketStateFromProto(state *roomv1.RoomRocketState) roomRocketStateData { if state == nil { - return roomTreasureStateData{} + return roomRocketStateData{} } - return roomTreasureStateData{ - CurrentLevel: state.GetCurrentLevel(), - CurrentProgress: state.GetCurrentProgress(), - EnergyThreshold: state.GetEnergyThreshold(), - Status: state.GetStatus(), - CountdownStartedAtMS: state.GetCountdownStartedAtMs(), - OpenAtMS: state.GetOpenAtMs(), - OpenedAtMS: state.GetOpenedAtMs(), - ResetAtMS: state.GetResetAtMs(), - Top1UserID: formatOptionalUserID(state.GetTop1UserId()), - IgniterUserID: formatOptionalUserID(state.GetIgniterUserId()), - BoxID: state.GetBoxId(), - ConfigVersion: state.GetConfigVersion(), - LastRewards: roomTreasureRewardGrantsFromProto(state.GetLastRewards()), + return roomRocketStateData{ + CurrentLevel: state.GetCurrentLevel(), + CurrentFuel: state.GetCurrentFuel(), + FuelThreshold: state.GetFuelThreshold(), + Status: state.GetStatus(), + IgnitedAtMS: state.GetIgnitedAtMs(), + LaunchAtMS: state.GetLaunchAtMs(), + LaunchedAtMS: state.GetLaunchedAtMs(), + ResetAtMS: state.GetResetAtMs(), + Top1UserID: formatOptionalUserID(state.GetTop1UserId()), + IgniterUserID: formatOptionalUserID(state.GetIgniterUserId()), + RocketID: state.GetRocketId(), + ConfigVersion: state.GetConfigVersion(), + LastRewards: roomRocketRewardGrantsFromProto(state.GetLastRewards()), + PendingLaunches: roomRocketPendingLaunchesFromProto(state.GetPendingLaunches()), } } -func roomTreasureRewardGrantsFromProto(rewards []*roomv1.RoomTreasureRewardGrant) []roomTreasureRewardGrantData { - out := make([]roomTreasureRewardGrantData, 0, len(rewards)) +func roomRocketPendingLaunchesFromProto(launches []*roomv1.RoomRocketPendingLaunch) []roomRocketPendingLaunchData { + out := make([]roomRocketPendingLaunchData, 0, len(launches)) + for _, launch := range launches { + out = append(out, roomRocketPendingLaunchData{ + RocketID: launch.GetRocketId(), + Level: launch.GetLevel(), + FuelThreshold: launch.GetFuelThreshold(), + IgnitedAtMS: launch.GetIgnitedAtMs(), + LaunchAtMS: launch.GetLaunchAtMs(), + ResetAtMS: launch.GetResetAtMs(), + Top1UserID: formatOptionalUserID(launch.GetTop1UserId()), + IgniterUserID: formatOptionalUserID(launch.GetIgniterUserId()), + ConfigVersion: launch.GetConfigVersion(), + CoverURL: launch.GetCoverUrl(), + }) + } + return out +} + +func roomRocketRewardGrantsFromProto(rewards []*roomv1.RoomRocketRewardGrant) []roomRocketRewardGrantData { + out := make([]roomRocketRewardGrantData, 0, len(rewards)) for _, reward := range rewards { - out = append(out, roomTreasureRewardGrantData{ + out = append(out, roomRocketRewardGrantData{ RewardRole: reward.GetRewardRole(), UserID: formatOptionalUserID(reward.GetUserId()), RewardItemID: reward.GetRewardItemId(), diff --git a/services/room-service/configs/config.docker.yaml b/services/room-service/configs/config.docker.yaml index 54be4d00..799a8dbc 100644 --- a/services/room-service/configs/config.docker.yaml +++ b/services/room-service/configs/config.docker.yaml @@ -49,7 +49,7 @@ presence_stale_after: "2m" presence_stale_scan_interval: "30s" mic_publish_timeout: "15s" mic_publish_scan_interval: "1s" -room_treasure_open_scan_interval: "1s" +room_rocket_launch_scan_interval: "1s" rocketmq: # Docker 本地使用 compose RocketMQ 验证 owner outbox 到下游读模型的真实链路。 enabled: true @@ -67,11 +67,11 @@ rocketmq: tencent_im_consumer_enabled: true tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - treasure_open: + rocket_open: enabled: false - topic: "hyapp_room_treasure_open" - producer_group: "hyapp-room-treasure-open-producer" - consumer_group: "hyapp-room-treasure-open" + topic: "hyapp_room_rocket_launch" + producer_group: "hyapp-room-rocket-open-producer" + consumer_group: "hyapp-room-rocket-open" consumer_max_reconsume_times: 16 outbox_worker: # Docker 和 testbox 走 MQ;room-service 同进程启动 IM bridge consumer 补偿房间群消息。 diff --git a/services/room-service/configs/config.tencent.example.yaml b/services/room-service/configs/config.tencent.example.yaml index 405066f8..0a136145 100644 --- a/services/room-service/configs/config.tencent.example.yaml +++ b/services/room-service/configs/config.tencent.example.yaml @@ -58,7 +58,7 @@ presence_stale_after: "2m" presence_stale_scan_interval: "30s" mic_publish_timeout: "15s" mic_publish_scan_interval: "1s" -room_treasure_open_scan_interval: "1s" +room_rocket_launch_scan_interval: "1s" rocketmq: # 线上建议开启:room_outbox 只投 MQ,activity/notice/IM bridge 各自用 consumer group 解耦消费。 enabled: true @@ -77,14 +77,14 @@ rocketmq: tencent_im_consumer_enabled: true tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - treasure_open: + rocket_open: enabled: true - topic: "hyapp_room_treasure_open" - producer_group: "hyapp-room-treasure-open-producer" - consumer_group: "hyapp-room-treasure-open" + topic: "hyapp_room_rocket_launch" + producer_group: "hyapp-room-rocket-open-producer" + consumer_group: "hyapp-room-rocket-open" consumer_max_reconsume_times: 16 outbox_worker: - # mq 模式下 outbox worker 只把事实投 MQ,并顺带安排宝箱延迟开箱唤醒。 + # mq 模式下 outbox worker 只把事实投 MQ,并顺带安排火箭延迟发射唤醒。 enabled: true publish_mode: "mq" poll_interval: "1s" diff --git a/services/room-service/configs/config.yaml b/services/room-service/configs/config.yaml index c21d9718..6789596d 100644 --- a/services/room-service/configs/config.yaml +++ b/services/room-service/configs/config.yaml @@ -52,9 +52,9 @@ presence_stale_after: "2m" presence_stale_scan_interval: "30s" mic_publish_timeout: "15s" mic_publish_scan_interval: "1s" -room_treasure_open_scan_interval: "1s" +room_rocket_launch_scan_interval: "1s" rocketmq: - # 本地默认关闭;开启后 room_outbox 可投 MQ,宝箱倒计时用延迟消息到点唤醒。 + # 本地默认关闭;开启后 room_outbox 可投 MQ,火箭倒计时用延迟消息到点唤醒。 enabled: false name_servers: [] name_server_domain: "" @@ -70,11 +70,11 @@ rocketmq: tencent_im_consumer_enabled: false tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - treasure_open: + rocket_open: enabled: false - topic: "hyapp_room_treasure_open" - producer_group: "hyapp-room-treasure-open-producer" - consumer_group: "hyapp-room-treasure-open" + topic: "hyapp_room_rocket_launch" + producer_group: "hyapp-room-rocket-open-producer" + consumer_group: "hyapp-room-rocket-open" consumer_max_reconsume_times: 16 outbox_worker: # room_outbox 是腾讯云 IM 和 activity-service 的异步投递通道;失败退避重试,超过上限转死信。 diff --git a/services/room-service/deploy/mysql/initdb/001_room_service.sql b/services/room-service/deploy/mysql/initdb/001_room_service.sql index b267839d..39e13e12 100644 --- a/services/room-service/deploy/mysql/initdb/001_room_service.sql +++ b/services/room-service/deploy/mysql/initdb/001_room_service.sql @@ -202,24 +202,24 @@ CREATE TABLE IF NOT EXISTS room_seat_configs ( PRIMARY KEY (app_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间麦位配置表'; -CREATE TABLE IF NOT EXISTS room_treasure_configs ( +CREATE TABLE IF NOT EXISTS room_rocket_configs ( app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', - enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用房间宝箱', + enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否启用房间火箭', config_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本,后台每次保存递增', - energy_source VARCHAR(32) NOT NULL COMMENT '能量来源,默认按送礼价值累计', - open_delay_ms BIGINT NOT NULL COMMENT '能量满后开箱倒计时,UTC 毫秒时长', + fuel_source VARCHAR(32) NOT NULL COMMENT '燃料来源,默认按送礼价值累计', + launch_delay_ms BIGINT NOT NULL COMMENT '燃料满后发射倒计时,UTC 毫秒时长', broadcast_enabled TINYINT(1) NOT NULL DEFAULT 1 COMMENT '倒计时开始后是否广播', broadcast_scope VARCHAR(32) NOT NULL COMMENT '广播范围:none/region/global', - broadcast_delay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '广播后到开箱的延迟,UTC 毫秒时长', + broadcast_delay_ms BIGINT NOT NULL DEFAULT 0 COMMENT '广播后到发射的延迟,UTC 毫秒时长', reward_stack_policy VARCHAR(32) NOT NULL COMMENT '同一用户多角色命中奖励时的叠加策略', - levels_json JSON NOT NULL COMMENT '7 级宝箱物料、阈值和奖励池配置', - gift_energy_rules_json JSON NOT NULL COMMENT '礼物能量倍率、固定能量和排除规则', + levels_json JSON NOT NULL COMMENT '5 级火箭物料、阈值和奖励池配置', + gift_fuel_rules_json JSON NOT NULL COMMENT '礼物燃料倍率、固定燃料和排除规则', updated_by_admin_id BIGINT UNSIGNED 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), - KEY idx_room_treasure_enabled (app_code, enabled) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='语音房宝箱后台配置表'; + KEY idx_room_rocket_enabled (app_code, enabled) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='语音房火箭后台配置表'; INSERT IGNORE INTO room_seat_configs ( app_code, @@ -235,18 +235,21 @@ INSERT IGNORE INTO room_seat_configs ( 0 ); -INSERT IGNORE INTO room_treasure_configs ( +ALTER TABLE room_rocket_configs + MODIFY COLUMN levels_json JSON NOT NULL COMMENT '5 级火箭物料、阈值和奖励池配置'; + +INSERT IGNORE INTO room_rocket_configs ( app_code, enabled, config_version, - energy_source, - open_delay_ms, + fuel_source, + launch_delay_ms, broadcast_enabled, broadcast_scope, broadcast_delay_ms, reward_stack_policy, levels_json, - gift_energy_rules_json, + gift_fuel_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms @@ -261,13 +264,11 @@ INSERT IGNORE INTO room_treasure_configs ( 0, 'allow_stack', JSON_ARRAY( - JSON_OBJECT('level', 1, 'energyThreshold', 1000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 2, 'energyThreshold', 3000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 3, 'energyThreshold', 6000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 4, 'energyThreshold', 10000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 5, 'energyThreshold', 15000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 6, 'energyThreshold', 21000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 7, 'energyThreshold', 28000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()) + JSON_OBJECT('level', 1, 'fuelThreshold', 1000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 2, 'fuelThreshold', 3000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 3, 'fuelThreshold', 6000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 4, 'fuelThreshold', 10000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 5, 'fuelThreshold', 15000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()) ), JSON_ARRAY(), 0, diff --git a/services/room-service/internal/app/app.go b/services/room-service/internal/app/app.go index 3a32c120..0c38884b 100644 --- a/services/room-service/internal/app/app.go +++ b/services/room-service/internal/app/app.go @@ -56,7 +56,7 @@ type App struct { health *healthcheck.State // healthHTTP 给 CLB 和发布脚本提供 HTTP readiness,不承载业务请求。 healthHTTP *healthhttp.Server - // mqProducers 在 outbox worker 启动前打开,承载 fanout 和延迟开箱唤醒。 + // mqProducers 在 outbox worker 启动前打开,承载 fanout 和延迟发射唤醒。 mqProducers []*rocketmqx.Producer // mqConsumers 在 gRPC 服务启动前订阅,承接 room_outbox fanout 和 delayed open。 mqConsumers []*rocketmqx.Consumer @@ -154,7 +154,7 @@ func New(cfg config.Config) (*App, error) { mqProducers := make([]*rocketmqx.Producer, 0, 2) mqConsumers := make([]*rocketmqx.Consumer, 0, 2) - var treasureOpenScheduler integration.RoomTreasureOpenScheduler + var rocketLaunchScheduler integration.RoomRocketLaunchScheduler if cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDirect || cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDual { if activityConn != nil { activityPublisher := integration.NewActivityOutboxPublisher(activityv1.NewRoomEventConsumerServiceClient(activityConn), time.Second) @@ -176,8 +176,8 @@ func New(cfg config.Config) (*App, error) { mqProducers = append(mqProducers, outboxProducer) outboxPublishers = append(outboxPublishers, integration.NewRocketMQOutboxPublisher(outboxProducer, cfg.RocketMQ.RoomOutbox.Topic)) } - if cfg.RocketMQ.TreasureOpen.Enabled { - treasureProducer, err := rocketmqx.NewProducer(rocketMQProducerConfig(cfg.RocketMQ, cfg.RocketMQ.TreasureOpen.ProducerGroup)) + if cfg.RocketMQ.RocketLaunch.Enabled { + rocketProducer, err := rocketmqx.NewProducer(rocketMQProducerConfig(cfg.RocketMQ, cfg.RocketMQ.RocketLaunch.ProducerGroup)) if err != nil { _ = repository.Close() closeClientConn(activityConn) @@ -185,8 +185,8 @@ func New(cfg config.Config) (*App, error) { _ = redisClient.Close() return nil, err } - mqProducers = append(mqProducers, treasureProducer) - treasureOpenScheduler = integration.NewRocketMQTreasureOpenScheduler(treasureProducer, cfg.RocketMQ.TreasureOpen.Topic) + mqProducers = append(mqProducers, rocketProducer) + rocketLaunchScheduler = integration.NewRocketMQRocketLaunchScheduler(rocketProducer, cfg.RocketMQ.RocketLaunch.Topic) } outboxPublisher := integration.NewCompositeOutboxPublisher(outboxPublishers...) var luckyGiftClient integration.LuckyGiftClient @@ -203,13 +203,13 @@ func New(cfg config.Config) (*App, error) { PresenceStaleAfter: cfg.PresenceStaleAfter, MicPublishTimeout: cfg.MicPublishTimeout, RTCUserRemover: rtcUserRemover, - RoomTreasureOpenScheduler: treasureOpenScheduler, + RoomRocketLaunchScheduler: rocketLaunchScheduler, RoomGiftLeaderboard: roomservice.NewRedisRoomGiftLeaderboardStore(redisClient), LuckyGiftSendLocker: roomservice.NewRedisLuckyGiftSendLocker(redisClient), LuckyGiftSendLockTTL: cfg.LuckyGiftSendLockTTL, }, directory, repository, integration.NewGRPCWalletClient(walletConn), roomPublisher, outboxPublisher, luckyGiftClient) - if cfg.RocketMQ.TreasureOpen.Enabled { - treasureConsumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.TreasureOpen.ConsumerGroup, cfg.RocketMQ.TreasureOpen.ConsumerMaxReconsumeTimes)) + if cfg.RocketMQ.RocketLaunch.Enabled { + rocketConsumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.RocketLaunch.ConsumerGroup, cfg.RocketMQ.RocketLaunch.ConsumerMaxReconsumeTimes)) if err != nil { _ = repository.Close() closeClientConn(activityConn) @@ -217,12 +217,12 @@ func New(cfg config.Config) (*App, error) { _ = redisClient.Close() return nil, err } - if err := treasureConsumer.Subscribe(cfg.RocketMQ.TreasureOpen.Topic, roommq.TagRoomTreasureOpenDue, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { - due, err := roommq.DecodeRoomTreasureOpenDueMessage(message.Body) + if err := rocketConsumer.Subscribe(cfg.RocketMQ.RocketLaunch.Topic, roommq.TagRoomRocketLaunchDue, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + due, err := roommq.DecodeRoomRocketLaunchDueMessage(message.Body) if err != nil { return err } - return svc.HandleRoomTreasureOpenDue(ctx, due) + return svc.HandleRoomRocketLaunchDue(ctx, due) }); err != nil { _ = repository.Close() closeClientConn(activityConn) @@ -230,7 +230,7 @@ func New(cfg config.Config) (*App, error) { _ = redisClient.Close() return nil, err } - mqConsumers = append(mqConsumers, treasureConsumer) + mqConsumers = append(mqConsumers, rocketConsumer) } if cfg.RocketMQ.RoomOutbox.TencentIMConsumerEnabled && tencentPublisher == nil { _ = repository.Close() @@ -347,10 +347,10 @@ func (a *App) Run() error { a.service.RunMicPublishTimeoutWorker(a.workerCtx, a.cfg.MicPublishScanInterval) }) } - if a.cfg.RoomTreasureOpenScanInterval > 0 { - // 宝箱开箱仍通过 Room Cell 命令链路提交,worker 只负责触发到点的系统命令。 + if a.cfg.RoomRocketLaunchScanInterval > 0 { + // 火箭发射仍通过 Room Cell 命令链路提交,worker 只负责触发到点的系统命令。 a.workerWG.Go(func() { - a.service.RunRoomTreasureOpenWorker(a.workerCtx, a.cfg.RoomTreasureOpenScanInterval) + a.service.RunRoomRocketLaunchWorker(a.workerCtx, a.cfg.RoomRocketLaunchScanInterval) }) } if a.cfg.OutboxWorker.Enabled { diff --git a/services/room-service/internal/config/config.go b/services/room-service/internal/config/config.go index 616d2cf9..d69dd2dd 100644 --- a/services/room-service/internal/config/config.go +++ b/services/room-service/internal/config/config.go @@ -78,9 +78,9 @@ type Config struct { MicPublishTimeout time.Duration `yaml:"mic_publish_timeout"` // MicPublishScanInterval 是本节点扫描 pending_publish 超时麦位的周期。 MicPublishScanInterval time.Duration `yaml:"mic_publish_scan_interval"` - // RoomTreasureOpenScanInterval 是本节点扫描到点开箱宝箱的周期。 - RoomTreasureOpenScanInterval time.Duration `yaml:"room_treasure_open_scan_interval"` - // RocketMQ 承载 room_outbox 事件分发和语音房宝箱延迟开箱唤醒。 + // RoomRocketLaunchScanInterval 是本节点扫描到点发射火箭的周期。 + RoomRocketLaunchScanInterval time.Duration `yaml:"room_rocket_launch_scan_interval"` + // RocketMQ 承载 room_outbox 事件分发和语音房火箭延迟发射唤醒。 RocketMQ RocketMQConfig `yaml:"rocketmq"` // OutboxWorker 控制 room_outbox 到腾讯云 IM 补偿投递 worker。 OutboxWorker OutboxWorkerConfig `yaml:"outbox_worker"` @@ -123,7 +123,7 @@ type RocketMQConfig struct { SendTimeout time.Duration `yaml:"send_timeout"` Retry int `yaml:"retry"` RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"` - TreasureOpen TreasureOpenMQConfig `yaml:"treasure_open"` + RocketLaunch RocketLaunchMQConfig `yaml:"rocket_open"` } // RoomOutboxMQConfig 控制 room_outbox fanout topic。 @@ -136,8 +136,8 @@ type RoomOutboxMQConfig struct { ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` } -// TreasureOpenMQConfig 控制宝箱延迟开箱唤醒 topic。 -type TreasureOpenMQConfig struct { +// RocketLaunchMQConfig 控制火箭延迟发射唤醒 topic。 +type RocketLaunchMQConfig struct { Enabled bool `yaml:"enabled"` Topic string `yaml:"topic"` ProducerGroup string `yaml:"producer_group"` @@ -260,7 +260,7 @@ func Default() Config { PresenceStaleScanInterval: 30 * time.Second, MicPublishTimeout: 15 * time.Second, MicPublishScanInterval: time.Second, - RoomTreasureOpenScanInterval: time.Second, + RoomRocketLaunchScanInterval: time.Second, RocketMQ: defaultRocketMQConfig(), OutboxWorker: defaultOutboxWorkerConfig(), Log: logx.Config{ @@ -299,11 +299,11 @@ func defaultRocketMQConfig() RocketMQConfig { TencentIMConsumerGroup: "hyapp-room-im-bridge", ConsumerMaxReconsumeTimes: 16, }, - TreasureOpen: TreasureOpenMQConfig{ + RocketLaunch: RocketLaunchMQConfig{ Enabled: false, - Topic: "hyapp_room_treasure_open", - ProducerGroup: "hyapp-room-treasure-open-producer", - ConsumerGroup: "hyapp-room-treasure-open", + Topic: "hyapp_room_rocket_launch", + ProducerGroup: "hyapp-room-rocket-open-producer", + ConsumerGroup: "hyapp-room-rocket-open", ConsumerMaxReconsumeTimes: 16, }, } @@ -473,19 +473,19 @@ func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQCo if cfg.RoomOutbox.ConsumerMaxReconsumeTimes <= 0 { cfg.RoomOutbox.ConsumerMaxReconsumeTimes = defaults.RoomOutbox.ConsumerMaxReconsumeTimes } - if cfg.TreasureOpen.Topic = strings.TrimSpace(cfg.TreasureOpen.Topic); cfg.TreasureOpen.Topic == "" { - cfg.TreasureOpen.Topic = defaults.TreasureOpen.Topic + if cfg.RocketLaunch.Topic = strings.TrimSpace(cfg.RocketLaunch.Topic); cfg.RocketLaunch.Topic == "" { + cfg.RocketLaunch.Topic = defaults.RocketLaunch.Topic } - if cfg.TreasureOpen.ProducerGroup = strings.TrimSpace(cfg.TreasureOpen.ProducerGroup); cfg.TreasureOpen.ProducerGroup == "" { - cfg.TreasureOpen.ProducerGroup = defaults.TreasureOpen.ProducerGroup + if cfg.RocketLaunch.ProducerGroup = strings.TrimSpace(cfg.RocketLaunch.ProducerGroup); cfg.RocketLaunch.ProducerGroup == "" { + cfg.RocketLaunch.ProducerGroup = defaults.RocketLaunch.ProducerGroup } - if cfg.TreasureOpen.ConsumerGroup = strings.TrimSpace(cfg.TreasureOpen.ConsumerGroup); cfg.TreasureOpen.ConsumerGroup == "" { - cfg.TreasureOpen.ConsumerGroup = defaults.TreasureOpen.ConsumerGroup + if cfg.RocketLaunch.ConsumerGroup = strings.TrimSpace(cfg.RocketLaunch.ConsumerGroup); cfg.RocketLaunch.ConsumerGroup == "" { + cfg.RocketLaunch.ConsumerGroup = defaults.RocketLaunch.ConsumerGroup } - if cfg.TreasureOpen.ConsumerMaxReconsumeTimes <= 0 { - cfg.TreasureOpen.ConsumerMaxReconsumeTimes = defaults.TreasureOpen.ConsumerMaxReconsumeTimes + if cfg.RocketLaunch.ConsumerMaxReconsumeTimes <= 0 { + cfg.RocketLaunch.ConsumerMaxReconsumeTimes = defaults.RocketLaunch.ConsumerMaxReconsumeTimes } - if cfg.RoomOutbox.Enabled || cfg.TreasureOpen.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled { + if cfg.RoomOutbox.Enabled || cfg.RocketLaunch.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled { cfg.Enabled = true } if publishMode == OutboxPublishModeMQ || publishMode == OutboxPublishModeDual { diff --git a/services/room-service/internal/config/config_test.go b/services/room-service/internal/config/config_test.go index f8bbd9ef..e71868c2 100644 --- a/services/room-service/internal/config/config_test.go +++ b/services/room-service/internal/config/config_test.go @@ -37,7 +37,7 @@ func TestLoad(t *testing.T) { if !cfg.OutboxWorker.Enabled || cfg.OutboxWorker.PublishMode != OutboxPublishModeDirect || cfg.OutboxWorker.PollInterval != time.Second || cfg.OutboxWorker.BatchSize != 100 || cfg.OutboxWorker.PublishTimeout != 3*time.Second || cfg.OutboxWorker.RetryStrategy != "exponential_backoff" || cfg.OutboxWorker.MaxRetryCount != 10 || cfg.OutboxWorker.InitialBackoff != 5*time.Second || cfg.OutboxWorker.MaxBackoff != 5*time.Minute { t.Fatalf("unexpected outbox worker config: %+v", cfg.OutboxWorker) } - if cfg.RocketMQ.Enabled || cfg.RocketMQ.RoomOutbox.Enabled || cfg.RocketMQ.TreasureOpen.Enabled { + if cfg.RocketMQ.Enabled || cfg.RocketMQ.RoomOutbox.Enabled || cfg.RocketMQ.RocketLaunch.Enabled { t.Fatalf("local config must not require RocketMQ: %+v", cfg.RocketMQ) } } @@ -70,8 +70,8 @@ func TestLoadTencentExample(t *testing.T) { if !cfg.OutboxWorker.Enabled || cfg.OutboxWorker.RetryStrategy != "exponential_backoff" || cfg.OutboxWorker.MaxRetryCount != 10 { t.Fatalf("tencent example must configure outbox worker: %+v", cfg.OutboxWorker) } - if cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.TreasureOpen.Enabled { - t.Fatalf("tencent example must route room outbox and treasure open through RocketMQ: mode=%s mq=%+v", cfg.OutboxWorker.PublishMode, cfg.RocketMQ) + if cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RocketLaunch.Enabled { + t.Fatalf("tencent example must route room outbox and rocket open through RocketMQ: mode=%s mq=%+v", cfg.OutboxWorker.PublishMode, cfg.RocketMQ) } } diff --git a/services/room-service/internal/integration/clients.go b/services/room-service/internal/integration/clients.go index d76677b7..770351a6 100644 --- a/services/room-service/internal/integration/clients.go +++ b/services/room-service/internal/integration/clients.go @@ -16,7 +16,7 @@ type WalletClient interface { DebitGift(ctx context.Context, req *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) // BatchDebitGift 在 wallet-service 单事务内结算多目标送礼;任一目标失败时整批失败。 BatchDebitGift(ctx context.Context, req *walletv1.BatchDebitGiftRequest) (*walletv1.BatchDebitGiftResponse, error) - // GrantResourceGroup 发放宝箱奖励资源组;命令 ID 必须由 room-service 按宝箱结算事实生成。 + // GrantResourceGroup 发放火箭奖励资源组;命令 ID 必须由 room-service 按火箭结算事实生成。 GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) } @@ -48,19 +48,19 @@ type OutboxPublisher interface { PublishOutboxEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) error } -// RoomTreasureOpenSchedule 是 RoomTreasureCountdownStarted 派生出的延迟开箱唤醒任务。 -type RoomTreasureOpenSchedule struct { - AppCode string - RoomID string - BoxID string - Level int32 - OpenAtMS int64 - ResetAtMS int64 - CommandID string +// RoomRocketLaunchSchedule 是 RoomRocketIgnited 派生出的延迟发射唤醒任务。 +type RoomRocketLaunchSchedule struct { + AppCode string + RoomID string + RocketID string + Level int32 + LaunchAtMS int64 + ResetAtMS int64 + CommandID string } -// RoomTreasureOpenScheduler 抽象“到 open_at_ms 唤醒 room-service”的外部延迟通道。 -type RoomTreasureOpenScheduler interface { - // ScheduleRoomTreasureOpen 只负责安排唤醒;真正开箱仍由 room-service 命令链路校验并提交。 - ScheduleRoomTreasureOpen(ctx context.Context, schedule RoomTreasureOpenSchedule) error +// RoomRocketLaunchScheduler 抽象“到 launch_at_ms 唤醒 room-service”的外部延迟通道。 +type RoomRocketLaunchScheduler interface { + // ScheduleRoomRocketLaunch 只负责安排唤醒;真正发射仍由 room-service 命令链路校验并提交。 + ScheduleRoomRocketLaunch(ctx context.Context, schedule RoomRocketLaunchSchedule) error } diff --git a/services/room-service/internal/integration/rocketmq_outbox.go b/services/room-service/internal/integration/rocketmq_outbox.go index b753cf40..963d3ee3 100644 --- a/services/room-service/internal/integration/rocketmq_outbox.go +++ b/services/room-service/internal/integration/rocketmq_outbox.go @@ -46,44 +46,44 @@ func (p *RocketMQOutboxPublisher) PublishOutboxEvent(ctx context.Context, envelo }) } -// RocketMQTreasureOpenScheduler publishes exact-time treasure wakeup messages. -type RocketMQTreasureOpenScheduler struct { +// RocketMQRocketLaunchScheduler publishes exact-time rocket wakeup messages. +type RocketMQRocketLaunchScheduler struct { producer *rocketmqx.Producer topic string } -// NewRocketMQTreasureOpenScheduler creates the delayed open scheduler. -func NewRocketMQTreasureOpenScheduler(producer *rocketmqx.Producer, topic string) *RocketMQTreasureOpenScheduler { - return &RocketMQTreasureOpenScheduler{producer: producer, topic: topic} +// NewRocketMQRocketLaunchScheduler creates the delayed open scheduler. +func NewRocketMQRocketLaunchScheduler(producer *rocketmqx.Producer, topic string) *RocketMQRocketLaunchScheduler { + return &RocketMQRocketLaunchScheduler{producer: producer, topic: topic} } -// ScheduleRoomTreasureOpen implements RoomTreasureOpenScheduler. -func (s *RocketMQTreasureOpenScheduler) ScheduleRoomTreasureOpen(ctx context.Context, schedule RoomTreasureOpenSchedule) error { - body, err := roommq.EncodeRoomTreasureOpenDueMessage(roommq.RoomTreasureOpenDueMessage{ - AppCode: schedule.AppCode, - RoomID: schedule.RoomID, - BoxID: schedule.BoxID, - Level: schedule.Level, - OpenAtMS: schedule.OpenAtMS, - ResetAtMS: schedule.ResetAtMS, - CommandID: schedule.CommandID, +// ScheduleRoomRocketLaunch implements RoomRocketLaunchScheduler. +func (s *RocketMQRocketLaunchScheduler) ScheduleRoomRocketLaunch(ctx context.Context, schedule RoomRocketLaunchSchedule) error { + body, err := roommq.EncodeRoomRocketLaunchDueMessage(roommq.RoomRocketLaunchDueMessage{ + AppCode: schedule.AppCode, + RoomID: schedule.RoomID, + RocketID: schedule.RocketID, + Level: schedule.Level, + LaunchAtMS: schedule.LaunchAtMS, + ResetAtMS: schedule.ResetAtMS, + CommandID: schedule.CommandID, }) if err != nil { return err } return s.producer.SendSync(ctx, rocketmqx.Message{ Topic: s.topic, - Tag: roommq.TagRoomTreasureOpenDue, - Keys: []string{schedule.BoxID, schedule.RoomID}, + Tag: roommq.TagRoomRocketLaunchDue, + Keys: []string{schedule.RocketID, schedule.RoomID}, Body: body, - DeliveryAtMS: schedule.OpenAtMS, + DeliveryAtMS: schedule.LaunchAtMS, Properties: map[string]string{ - "message_type": roommq.MessageTypeRoomTreasureOpenDue, + "message_type": roommq.MessageTypeRoomRocketLaunchDue, "app_code": schedule.AppCode, "room_id": schedule.RoomID, - "box_id": schedule.BoxID, + "rocket_id": schedule.RocketID, "level": strconv.FormatInt(int64(schedule.Level), 10), - "open_at_ms": strconv.FormatInt(schedule.OpenAtMS, 10), + "launch_at_ms": strconv.FormatInt(schedule.LaunchAtMS, 10), "reset_at_ms": strconv.FormatInt(schedule.ResetAtMS, 10), }, }) diff --git a/services/room-service/internal/integration/tencent_im.go b/services/room-service/internal/integration/tencent_im.go index f53870c7..ead2452d 100644 --- a/services/room-service/internal/integration/tencent_im.go +++ b/services/room-service/internal/integration/tencent_im.go @@ -271,50 +271,50 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room "billing_receipt_id": body.GetBillingReceiptId(), } return base, true, nil - case "RoomTreasureProgressChanged": - var body roomeventsv1.RoomTreasureProgressChanged + case "RoomRocketFuelChanged": + var body roomeventsv1.RoomRocketFuelChanged if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { return tencentim.RoomEvent{}, false, err } base.ActorUserID = body.GetSenderUserId() base.Attributes = map[string]string{ - "box_id": body.GetBoxId(), - "level": fmt.Sprintf("%d", body.GetLevel()), - "added_energy": fmt.Sprintf("%d", body.GetAddedEnergy()), - "effective_added_energy": fmt.Sprintf("%d", body.GetEffectiveAddedEnergy()), - "overflow_energy": fmt.Sprintf("%d", body.GetOverflowEnergy()), - "current_progress": fmt.Sprintf("%d", body.GetCurrentProgress()), - "energy_threshold": fmt.Sprintf("%d", body.GetEnergyThreshold()), - "status": body.GetStatus(), - "reset_at_ms": fmt.Sprintf("%d", body.GetResetAtMs()), - "gift_id": body.GetGiftId(), - "gift_count": fmt.Sprintf("%d", body.GetGiftCount()), - "command_id": body.GetCommandId(), + "rocket_id": body.GetRocketId(), + "level": fmt.Sprintf("%d", body.GetLevel()), + "added_fuel": fmt.Sprintf("%d", body.GetAddedFuel()), + "effective_added_fuel": fmt.Sprintf("%d", body.GetEffectiveAddedFuel()), + "overflow_fuel": fmt.Sprintf("%d", body.GetOverflowFuel()), + "current_fuel": fmt.Sprintf("%d", body.GetCurrentFuel()), + "fuel_threshold": fmt.Sprintf("%d", body.GetFuelThreshold()), + "status": body.GetStatus(), + "reset_at_ms": fmt.Sprintf("%d", body.GetResetAtMs()), + "gift_id": body.GetGiftId(), + "gift_count": fmt.Sprintf("%d", body.GetGiftCount()), + "command_id": body.GetCommandId(), } return base, true, nil - case "RoomTreasureCountdownStarted": - var body roomeventsv1.RoomTreasureCountdownStarted + case "RoomRocketIgnited": + var body roomeventsv1.RoomRocketIgnited if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { return tencentim.RoomEvent{}, false, err } base.ActorUserID = body.GetIgniterUserId() base.TargetUserID = body.GetTop1UserId() base.Attributes = map[string]string{ - "box_id": body.GetBoxId(), - "level": fmt.Sprintf("%d", body.GetLevel()), - "current_progress": fmt.Sprintf("%d", body.GetCurrentProgress()), - "energy_threshold": fmt.Sprintf("%d", body.GetEnergyThreshold()), - "countdown_start_ms": fmt.Sprintf("%d", body.GetCountdownStartedAtMs()), - "open_at_ms": fmt.Sprintf("%d", body.GetOpenAtMs()), - "broadcast_scope": body.GetBroadcastScope(), - "visible_region_id": fmt.Sprintf("%d", body.GetVisibleRegionId()), - "top1_user_id": fmt.Sprintf("%d", body.GetTop1UserId()), - "igniter_user_id": fmt.Sprintf("%d", body.GetIgniterUserId()), - "command_id": body.GetCommandId(), + "rocket_id": body.GetRocketId(), + "level": fmt.Sprintf("%d", body.GetLevel()), + "current_fuel": fmt.Sprintf("%d", body.GetCurrentFuel()), + "fuel_threshold": fmt.Sprintf("%d", body.GetFuelThreshold()), + "ignited_at_ms": fmt.Sprintf("%d", body.GetIgnitedAtMs()), + "launch_at_ms": fmt.Sprintf("%d", body.GetLaunchAtMs()), + "broadcast_scope": body.GetBroadcastScope(), + "visible_region_id": fmt.Sprintf("%d", body.GetVisibleRegionId()), + "top1_user_id": fmt.Sprintf("%d", body.GetTop1UserId()), + "igniter_user_id": fmt.Sprintf("%d", body.GetIgniterUserId()), + "command_id": body.GetCommandId(), } return base, true, nil - case "RoomTreasureOpened": - var body roomeventsv1.RoomTreasureOpened + case "RoomRocketLaunched": + var body roomeventsv1.RoomRocketLaunched if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { return tencentim.RoomEvent{}, false, err } @@ -325,18 +325,18 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room base.ActorUserID = body.GetIgniterUserId() base.TargetUserID = body.GetTop1UserId() base.Attributes = map[string]string{ - "box_id": body.GetBoxId(), + "rocket_id": body.GetRocketId(), "level": fmt.Sprintf("%d", body.GetLevel()), "next_level": fmt.Sprintf("%d", body.GetNextLevel()), - "opened_at_ms": fmt.Sprintf("%d", body.GetOpenedAtMs()), + "launched_at_ms": fmt.Sprintf("%d", body.GetLaunchedAtMs()), "reset_at_ms": fmt.Sprintf("%d", body.GetResetAtMs()), "top1_user_id": fmt.Sprintf("%d", body.GetTop1UserId()), "igniter_user_id": fmt.Sprintf("%d", body.GetIgniterUserId()), "rewards_json": string(rewardsJSON), } return base, true, nil - case "RoomTreasureRewardGranted": - var body roomeventsv1.RoomTreasureRewardGranted + case "RoomRocketRewardGranted": + var body roomeventsv1.RoomRocketRewardGranted if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { return tencentim.RoomEvent{}, false, err } @@ -345,7 +345,7 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room return tencentim.RoomEvent{}, false, err } base.Attributes = map[string]string{ - "box_id": body.GetBoxId(), + "rocket_id": body.GetRocketId(), "level": fmt.Sprintf("%d", body.GetLevel()), "rewards_json": string(rewardsJSON), } @@ -404,14 +404,14 @@ func eventTypeForClient(eventType string) string { return "room_user_unbanned" case "RoomGiftSent": return "room_gift_sent" - case "RoomTreasureProgressChanged": - return "room_treasure_progress_changed" - case "RoomTreasureCountdownStarted": - return "room_treasure_countdown_started" - case "RoomTreasureOpened": - return "room_treasure_opened" - case "RoomTreasureRewardGranted": - return "room_treasure_reward_granted" + case "RoomRocketFuelChanged": + return "room_rocket_fuel_changed" + case "RoomRocketIgnited": + return "room_rocket_ignited" + case "RoomRocketLaunched": + return "room_rocket_launched" + case "RoomRocketRewardGranted": + return "room_rocket_reward_granted" default: return eventType } diff --git a/services/room-service/internal/room/command/command.go b/services/room-service/internal/room/command/command.go index c752e3d3..328c78b7 100644 --- a/services/room-service/internal/room/command/command.go +++ b/services/room-service/internal/room/command/command.go @@ -412,45 +412,47 @@ type SendGift struct { HeatValue int64 `json:"heat_value,omitempty"` // PriceVersion 是本次钱包结算使用的服务端礼物价格版本。 PriceVersion string `json:"price_version,omitempty"` - // GiftTypeCode 是 wallet-service 结算时锁定的礼物类型,用于宝箱礼物类型能量规则。 + // GiftTypeCode 是 wallet-service 结算时锁定的礼物类型,用于火箭礼物类型燃料规则。 GiftTypeCode string `json:"gift_type_code,omitempty"` // HostPeriodDiamondAdded 是 wallet-service 给主播周期钻石账户本次入账的钻石数。 HostPeriodDiamondAdded int64 `json:"host_period_diamond_added,omitempty"` // HostPeriodCycleKey 是本次周期钻石入账所属 UTC 月周期。 HostPeriodCycleKey string `json:"host_period_cycle_key,omitempty"` - // TreasureTouched 表示本次送礼已经计算过宝箱状态,恢复时直接使用下列确定性快照。 - TreasureTouched bool `json:"treasure_touched,omitempty"` - // TreasureAddedEnergy 是按后台规则算出的理论能量,倒计时和溢出规则会让它不完全生效。 - TreasureAddedEnergy int64 `json:"treasure_added_energy,omitempty"` - // TreasureEffectiveEnergy 是实际写入当前等级进度的能量,溢出不会进入下一级。 - TreasureEffectiveEnergy int64 `json:"treasure_effective_energy,omitempty"` - // TreasureOverflowEnergy 是本次礼物在当前等级阈值之外被丢弃的能量。 - TreasureOverflowEnergy int64 `json:"treasure_overflow_energy,omitempty"` - // TreasureLevel/TreasureProgress/TreasureStatus 是送礼后宝箱状态快照。 - TreasureLevel int32 `json:"treasure_level,omitempty"` - TreasureProgress int64 `json:"treasure_progress,omitempty"` - TreasureStatus string `json:"treasure_status,omitempty"` - // TreasureEnergyThreshold 是当前等级阈值快照。 - TreasureEnergyThreshold int64 `json:"treasure_energy_threshold,omitempty"` - // TreasureCountdownStartedAtMS/TreasureOpenAtMS 只在点火进入倒计时时写入。 - TreasureCountdownStartedAtMS int64 `json:"treasure_countdown_started_at_ms,omitempty"` - TreasureOpenAtMS int64 `json:"treasure_open_at_ms,omitempty"` - // TreasureResetAtMS 是该宝箱进度所属 UTC 日的下一次重置时间。 - TreasureResetAtMS int64 `json:"treasure_reset_at_ms,omitempty"` - // TreasureTop1UserID/TreasureIgniterUserID 在满能量瞬间锁定,离房后仍用它们发奖。 - TreasureTop1UserID int64 `json:"treasure_top1_user_id,omitempty"` - TreasureIgniterUserID int64 `json:"treasure_igniter_user_id,omitempty"` - // TreasureBoxID 是本轮宝箱幂等 ID,开箱、抽奖和 IM 都围绕它关联。 - TreasureBoxID string `json:"treasure_box_id,omitempty"` - // TreasureConfigVersion 是本轮宝箱采用的后台配置版本。 - TreasureConfigVersion int64 `json:"treasure_config_version,omitempty"` + // RocketTouched 表示本次送礼已经计算过火箭状态,恢复时直接使用下列确定性快照。 + RocketTouched bool `json:"rocket_touched,omitempty"` + // RocketAddedFuel 是按后台规则算出的理论燃料,倒计时和溢出规则会让它不完全生效。 + RocketAddedFuel int64 `json:"rocket_added_fuel,omitempty"` + // RocketEffectiveFuel 是实际写入当前等级进度的燃料,溢出不会进入下一级。 + RocketEffectiveFuel int64 `json:"rocket_effective_fuel,omitempty"` + // RocketOverflowFuel 是本次礼物在当前等级阈值之外被丢弃的燃料。 + RocketOverflowFuel int64 `json:"rocket_overflow_fuel,omitempty"` + // RocketLevel/RocketFuel/RocketStatus 是送礼后火箭状态快照。 + RocketLevel int32 `json:"rocket_level,omitempty"` + RocketFuel int64 `json:"rocket_fuel,omitempty"` + RocketStatus string `json:"rocket_status,omitempty"` + // RocketFuelThreshold 是当前等级阈值快照。 + RocketFuelThreshold int64 `json:"rocket_fuel_threshold,omitempty"` + // RocketIgnitedAtMS/RocketLaunchAtMS 只在点火进入倒计时时写入。 + RocketIgnitedAtMS int64 `json:"rocket_ignited_at_ms,omitempty"` + RocketLaunchAtMS int64 `json:"rocket_launch_at_ms,omitempty"` + // RocketResetAtMS 是该火箭进度所属 UTC 日的下一次重置时间。 + RocketResetAtMS int64 `json:"rocket_reset_at_ms,omitempty"` + // RocketTop1UserID/RocketIgniterUserID 在燃料满瞬间锁定,离房后仍用它们发奖。 + RocketTop1UserID int64 `json:"rocket_top1_user_id,omitempty"` + RocketIgniterUserID int64 `json:"rocket_igniter_user_id,omitempty"` + // RocketID 是本轮火箭幂等 ID,发射、抽奖和 IM 都围绕它关联。 + RocketID string `json:"rocket_id,omitempty"` + // RocketConfigVersion 是本轮火箭采用的后台配置版本。 + RocketConfigVersion int64 `json:"rocket_config_version,omitempty"` + // RocketPendingLaunches 是送礼提交后的待发射队列,恢复时不能只保存当前进度。 + RocketPendingLaunches []RocketPendingLaunch `json:"rocket_pending_launches,omitempty"` } // Type 返回命令类型。 func (SendGift) Type() string { return "send_gift" } -// TreasureRewardGrant 记录开箱命令中已经结算出的资源组发放结果。 -type TreasureRewardGrant struct { +// RocketRewardGrant 记录发射命令中已经结算出的资源组发放结果。 +type RocketRewardGrant struct { RewardRole string `json:"reward_role"` UserID int64 `json:"user_id"` RewardItemID string `json:"reward_item_id"` @@ -461,23 +463,45 @@ type TreasureRewardGrant struct { Status string `json:"status"` } -// OpenRoomTreasure 定义系统到点开箱命令。 -type OpenRoomTreasure struct { +// RocketPendingLaunch 记录一枚已点火火箭的延迟发射快照。 +type RocketPendingLaunch struct { + RocketID string `json:"rocket_id"` + Level int32 `json:"level"` + FuelThreshold int64 `json:"fuel_threshold"` + IgnitedAtMS int64 `json:"ignited_at_ms"` + LaunchAtMS int64 `json:"launch_at_ms"` + ResetAtMS int64 `json:"reset_at_ms"` + Top1UserID int64 `json:"top1_user_id,omitempty"` + IgniterUserID int64 `json:"igniter_user_id,omitempty"` + ConfigVersion int64 `json:"config_version"` + CoverURL string `json:"cover_url,omitempty"` +} + +// LaunchRoomRocket 定义系统到点发射命令。 +type LaunchRoomRocket struct { Base - BoxID string `json:"box_id"` - Level int32 `json:"level"` - NextLevel int32 `json:"next_level"` - NextEnergyThreshold int64 `json:"next_energy_threshold"` - ConfigVersion int64 `json:"config_version"` - ResetAtMS int64 `json:"reset_at_ms"` - Top1UserID int64 `json:"top1_user_id,omitempty"` - IgniterUserID int64 `json:"igniter_user_id,omitempty"` - InRoomUserIDs []int64 `json:"in_room_user_ids,omitempty"` - Rewards []TreasureRewardGrant `json:"rewards,omitempty"` + RocketID string `json:"rocket_id"` + Level int32 `json:"level"` + // Current* 是发射命令提交后的当前进度快照;发射不推进当前等级,只移除待发射队列。 + CurrentLevel int32 `json:"current_level"` + CurrentFuel int64 `json:"current_fuel"` + CurrentFuelThreshold int64 `json:"current_fuel_threshold"` + CurrentStatus string `json:"current_status"` + CurrentRocketID string `json:"current_rocket_id,omitempty"` + NextLevel int32 `json:"next_level"` + NextFuelThreshold int64 `json:"next_fuel_threshold"` + ConfigVersion int64 `json:"config_version"` + ResetAtMS int64 `json:"reset_at_ms"` + Top1UserID int64 `json:"top1_user_id,omitempty"` + IgniterUserID int64 `json:"igniter_user_id,omitempty"` + LaunchedAtMS int64 `json:"launched_at_ms"` + InRoomUserIDs []int64 `json:"in_room_user_ids,omitempty"` + Rewards []RocketRewardGrant `json:"rewards,omitempty"` + PendingLaunches []RocketPendingLaunch `json:"pending_launches,omitempty"` } // Type 返回命令类型。 -func (OpenRoomTreasure) Type() string { return "open_room_treasure" } +func (LaunchRoomRocket) Type() string { return "launch_room_rocket" } // Serialize 把命令编码成 command log 持久化所需的稳定载荷。 func Serialize(cmd Command) ([]byte, error) { @@ -513,30 +537,36 @@ func IdempotencyPayload(payload []byte) ([]byte, error) { delete(values, "gift_type_code") delete(values, "host_period_diamond_added") delete(values, "host_period_cycle_key") - delete(values, "treasure_touched") - delete(values, "treasure_added_energy") - delete(values, "treasure_effective_energy") - delete(values, "treasure_overflow_energy") - delete(values, "treasure_level") - delete(values, "treasure_progress") - delete(values, "treasure_status") - delete(values, "treasure_energy_threshold") - delete(values, "treasure_countdown_started_at_ms") - delete(values, "treasure_open_at_ms") - delete(values, "treasure_reset_at_ms") - delete(values, "treasure_top1_user_id") - delete(values, "treasure_igniter_user_id") - delete(values, "treasure_box_id") - delete(values, "treasure_config_version") - // OpenRoomTreasure 的以下字段是 worker 在开箱时结算出的结果,不属于触发开箱的幂等语义。 - delete(values, "next_level") - delete(values, "next_energy_threshold") + delete(values, "rocket_touched") + delete(values, "rocket_added_fuel") + delete(values, "rocket_effective_fuel") + delete(values, "rocket_overflow_fuel") + delete(values, "rocket_level") + delete(values, "rocket_fuel") + delete(values, "rocket_status") + delete(values, "rocket_fuel_threshold") + delete(values, "rocket_ignited_at_ms") + delete(values, "rocket_launch_at_ms") + delete(values, "rocket_reset_at_ms") + delete(values, "rocket_top1_user_id") + delete(values, "rocket_igniter_user_id") + delete(values, "rocket_id") + delete(values, "rocket_config_version") + delete(values, "rocket_pending_launches") + // LaunchRoomRocket 的以下字段是 worker 在发射时结算出的结果,不属于触发发射的幂等语义。 + delete(values, "current_level") + delete(values, "current_fuel") + delete(values, "current_fuel_threshold") + delete(values, "current_status") + delete(values, "current_rocket_id") delete(values, "config_version") delete(values, "reset_at_ms") delete(values, "top1_user_id") delete(values, "igniter_user_id") + delete(values, "launched_at_ms") delete(values, "in_room_user_ids") delete(values, "rewards") + delete(values, "pending_launches") // SetRoomPassword 的哈希带随机盐;通用 payload 比较先去掉哈希,service 层再用 transient 明文和已存 bcrypt 哈希确认是否同一密码。 delete(values, "password_hash") // MicUp 的发流确认 deadline 由 room-service 生成,客户端重试同一 command_id 时不能因此冲突。 @@ -601,8 +631,8 @@ func Deserialize(commandType string, payload []byte) (Command, error) { cmd = &UnbanUser{} case SendGift{}.Type(): cmd = &SendGift{} - case OpenRoomTreasure{}.Type(): - cmd = &OpenRoomTreasure{} + case LaunchRoomRocket{}.Type(): + cmd = &LaunchRoomRocket{} default: return nil, fmt.Errorf("unknown room command type: %s", commandType) } diff --git a/services/room-service/internal/room/service/admin_rocket.go b/services/room-service/internal/room/service/admin_rocket.go new file mode 100644 index 00000000..22256d8f --- /dev/null +++ b/services/room-service/internal/room/service/admin_rocket.go @@ -0,0 +1,154 @@ +package service + +import ( + "context" + + roomv1 "hyapp.local/api/proto/room/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" +) + +// AdminGetRoomRocketConfig 暴露 room-service owner 内部配置读模型,避免后台跨库读取 room_rocket_configs。 +func (s *Service) AdminGetRoomRocketConfig(ctx context.Context, _ *roomv1.AdminGetRoomRocketConfigRequest) (*roomv1.AdminGetRoomRocketConfigResponse, error) { + config, err := s.roomRocketConfig(ctx) + if err != nil { + return nil, err + } + return &roomv1.AdminGetRoomRocketConfigResponse{ + Config: roomRocketConfigToAdminProto(config), + ServerTimeMs: s.clock.Now().UnixMilli(), + }, nil +} + +// AdminUpdateRoomRocketConfig 保存后台火箭配置;版本号在 room-service 内递增,admin 不能直写 owner 表。 +func (s *Service) AdminUpdateRoomRocketConfig(ctx context.Context, req *roomv1.AdminUpdateRoomRocketConfigRequest) (*roomv1.AdminUpdateRoomRocketConfigResponse, error) { + if req == nil || req.GetConfig() == nil { + return nil, xerr.New(xerr.InvalidArgument, "room rocket config is required") + } + current, exists, err := s.repository.GetRoomRocketConfig(ctx) + if err != nil { + return nil, err + } + nowMS := s.clock.Now().UTC().UnixMilli() + createdAtMS := current.CreatedAtMS + if !exists || createdAtMS <= 0 { + createdAtMS = nowMS + } + input := req.GetConfig() + config, err := normalizeRoomRocketConfig(RoomRocketConfig{ + AppCode: appcode.FromContext(ctx), + Enabled: input.GetEnabled(), + ConfigVersion: current.ConfigVersion + 1, + FuelSource: input.GetFuelSource(), + LaunchDelayMS: input.GetLaunchDelayMs(), + BroadcastEnabled: input.GetBroadcastEnabled(), + BroadcastScope: input.GetBroadcastScope(), + BroadcastDelayMS: input.GetBroadcastDelayMs(), + RewardStackPolicy: input.GetRewardStackPolicy(), + Levels: roomRocketLevelsFromProto(input.GetLevels()), + GiftFuelRules: roomRocketFuelRulesFromProto(input.GetGiftFuelRules()), + UpdatedByAdminID: req.GetAdminId(), + CreatedAtMS: createdAtMS, + UpdatedAtMS: nowMS, + }) + if err != nil { + return nil, err + } + if err := s.repository.UpsertRoomRocketConfig(ctx, config); err != nil { + return nil, err + } + return &roomv1.AdminUpdateRoomRocketConfigResponse{ + Config: roomRocketConfigToAdminProto(config), + ServerTimeMs: nowMS, + }, nil +} + +func roomRocketConfigToAdminProto(config RoomRocketConfig) *roomv1.AdminRoomRocketConfig { + return &roomv1.AdminRoomRocketConfig{ + AppCode: config.AppCode, + Enabled: config.Enabled, + ConfigVersion: config.ConfigVersion, + FuelSource: config.FuelSource, + LaunchDelayMs: config.LaunchDelayMS, + BroadcastEnabled: config.BroadcastEnabled, + BroadcastScope: config.BroadcastScope, + BroadcastDelayMs: config.BroadcastDelayMS, + RewardStackPolicy: config.RewardStackPolicy, + Levels: roomRocketLevelsToProto(config.Levels), + GiftFuelRules: roomRocketFuelRulesToProto(config.GiftFuelRules), + UpdatedByAdminId: config.UpdatedByAdminID, + CreatedAtMs: config.CreatedAtMS, + UpdatedAtMs: config.UpdatedAtMS, + } +} + +func roomRocketLevelsFromProto(input []*roomv1.RoomRocketLevel) []RoomRocketLevelConfig { + out := make([]RoomRocketLevelConfig, 0, len(input)) + for _, level := range input { + if level == nil { + continue + } + out = append(out, RoomRocketLevelConfig{ + Level: level.GetLevel(), + FuelThreshold: level.GetFuelThreshold(), + CoverURL: level.GetCoverUrl(), + AnimationURL: level.GetAnimationUrl(), + LaunchAnimationURL: level.GetLaunchAnimationUrl(), + LaunchedImageURL: level.GetLaunchedImageUrl(), + InRoomRewards: roomRocketRewardsFromProto(level.GetInRoomRewards()), + Top1Rewards: roomRocketRewardsFromProto(level.GetTop1Rewards()), + IgniterRewards: roomRocketRewardsFromProto(level.GetIgniterRewards()), + }) + } + return out +} + +func roomRocketRewardsFromProto(input []*roomv1.RoomRocketRewardItem) []RoomRocketRewardItem { + out := make([]RoomRocketRewardItem, 0, len(input)) + for _, reward := range input { + if reward == nil { + continue + } + out = append(out, RoomRocketRewardItem{ + RewardItemID: reward.GetRewardItemId(), + ResourceGroupID: reward.GetResourceGroupId(), + Weight: reward.GetWeight(), + DisplayName: reward.GetDisplayName(), + IconURL: reward.GetIconUrl(), + }) + } + return out +} + +func roomRocketFuelRulesToProto(input []GiftFuelRuleConfig) []*roomv1.RoomRocketGiftFuelRule { + out := make([]*roomv1.RoomRocketGiftFuelRule, 0, len(input)) + for _, rule := range input { + out = append(out, &roomv1.RoomRocketGiftFuelRule{ + RuleId: rule.RuleID, + GiftId: rule.GiftID, + GiftTypeCode: rule.GiftTypeCode, + MultiplierPpm: rule.MultiplierPPM, + FixedFuel: rule.FixedFuel, + Excluded: rule.Excluded, + }) + } + return out +} + +func roomRocketFuelRulesFromProto(input []*roomv1.RoomRocketGiftFuelRule) []GiftFuelRuleConfig { + out := make([]GiftFuelRuleConfig, 0, len(input)) + for _, rule := range input { + if rule == nil { + continue + } + out = append(out, GiftFuelRuleConfig{ + RuleID: rule.GetRuleId(), + GiftID: rule.GetGiftId(), + GiftTypeCode: rule.GetGiftTypeCode(), + MultiplierPPM: rule.GetMultiplierPpm(), + FixedFuel: rule.GetFixedFuel(), + Excluded: rule.GetExcluded(), + }) + } + return out +} diff --git a/services/room-service/internal/room/service/admin_treasure.go b/services/room-service/internal/room/service/admin_treasure.go deleted file mode 100644 index 18bd3583..00000000 --- a/services/room-service/internal/room/service/admin_treasure.go +++ /dev/null @@ -1,154 +0,0 @@ -package service - -import ( - "context" - - roomv1 "hyapp.local/api/proto/room/v1" - "hyapp/pkg/appcode" - "hyapp/pkg/xerr" -) - -// AdminGetRoomTreasureConfig 暴露 room-service owner 内部配置读模型,避免后台跨库读取 room_treasure_configs。 -func (s *Service) AdminGetRoomTreasureConfig(ctx context.Context, _ *roomv1.AdminGetRoomTreasureConfigRequest) (*roomv1.AdminGetRoomTreasureConfigResponse, error) { - config, err := s.roomTreasureConfig(ctx) - if err != nil { - return nil, err - } - return &roomv1.AdminGetRoomTreasureConfigResponse{ - Config: roomTreasureConfigToAdminProto(config), - ServerTimeMs: s.clock.Now().UnixMilli(), - }, nil -} - -// AdminUpdateRoomTreasureConfig 保存后台宝箱配置;版本号在 room-service 内递增,admin 不能直写 owner 表。 -func (s *Service) AdminUpdateRoomTreasureConfig(ctx context.Context, req *roomv1.AdminUpdateRoomTreasureConfigRequest) (*roomv1.AdminUpdateRoomTreasureConfigResponse, error) { - if req == nil || req.GetConfig() == nil { - return nil, xerr.New(xerr.InvalidArgument, "room treasure config is required") - } - current, exists, err := s.repository.GetRoomTreasureConfig(ctx) - if err != nil { - return nil, err - } - nowMS := s.clock.Now().UTC().UnixMilli() - createdAtMS := current.CreatedAtMS - if !exists || createdAtMS <= 0 { - createdAtMS = nowMS - } - input := req.GetConfig() - config, err := normalizeRoomTreasureConfig(RoomTreasureConfig{ - AppCode: appcode.FromContext(ctx), - Enabled: input.GetEnabled(), - ConfigVersion: current.ConfigVersion + 1, - EnergySource: input.GetEnergySource(), - OpenDelayMS: input.GetOpenDelayMs(), - BroadcastEnabled: input.GetBroadcastEnabled(), - BroadcastScope: input.GetBroadcastScope(), - BroadcastDelayMS: input.GetBroadcastDelayMs(), - RewardStackPolicy: input.GetRewardStackPolicy(), - Levels: roomTreasureLevelsFromProto(input.GetLevels()), - GiftEnergyRules: roomTreasureEnergyRulesFromProto(input.GetGiftEnergyRules()), - UpdatedByAdminID: req.GetAdminId(), - CreatedAtMS: createdAtMS, - UpdatedAtMS: nowMS, - }) - if err != nil { - return nil, err - } - if err := s.repository.UpsertRoomTreasureConfig(ctx, config); err != nil { - return nil, err - } - return &roomv1.AdminUpdateRoomTreasureConfigResponse{ - Config: roomTreasureConfigToAdminProto(config), - ServerTimeMs: nowMS, - }, nil -} - -func roomTreasureConfigToAdminProto(config RoomTreasureConfig) *roomv1.AdminRoomTreasureConfig { - return &roomv1.AdminRoomTreasureConfig{ - AppCode: config.AppCode, - Enabled: config.Enabled, - ConfigVersion: config.ConfigVersion, - EnergySource: config.EnergySource, - OpenDelayMs: config.OpenDelayMS, - BroadcastEnabled: config.BroadcastEnabled, - BroadcastScope: config.BroadcastScope, - BroadcastDelayMs: config.BroadcastDelayMS, - RewardStackPolicy: config.RewardStackPolicy, - Levels: roomTreasureLevelsToProto(config.Levels), - GiftEnergyRules: roomTreasureEnergyRulesToProto(config.GiftEnergyRules), - UpdatedByAdminId: config.UpdatedByAdminID, - CreatedAtMs: config.CreatedAtMS, - UpdatedAtMs: config.UpdatedAtMS, - } -} - -func roomTreasureLevelsFromProto(input []*roomv1.RoomTreasureLevel) []RoomTreasureLevelConfig { - out := make([]RoomTreasureLevelConfig, 0, len(input)) - for _, level := range input { - if level == nil { - continue - } - out = append(out, RoomTreasureLevelConfig{ - Level: level.GetLevel(), - EnergyThreshold: level.GetEnergyThreshold(), - CoverURL: level.GetCoverUrl(), - AnimationURL: level.GetAnimationUrl(), - OpeningAnimationURL: level.GetOpeningAnimationUrl(), - OpenedImageURL: level.GetOpenedImageUrl(), - InRoomRewards: roomTreasureRewardsFromProto(level.GetInRoomRewards()), - Top1Rewards: roomTreasureRewardsFromProto(level.GetTop1Rewards()), - IgniterRewards: roomTreasureRewardsFromProto(level.GetIgniterRewards()), - }) - } - return out -} - -func roomTreasureRewardsFromProto(input []*roomv1.RoomTreasureRewardItem) []RoomTreasureRewardItem { - out := make([]RoomTreasureRewardItem, 0, len(input)) - for _, reward := range input { - if reward == nil { - continue - } - out = append(out, RoomTreasureRewardItem{ - RewardItemID: reward.GetRewardItemId(), - ResourceGroupID: reward.GetResourceGroupId(), - Weight: reward.GetWeight(), - DisplayName: reward.GetDisplayName(), - IconURL: reward.GetIconUrl(), - }) - } - return out -} - -func roomTreasureEnergyRulesToProto(input []GiftEnergyRuleConfig) []*roomv1.RoomTreasureGiftEnergyRule { - out := make([]*roomv1.RoomTreasureGiftEnergyRule, 0, len(input)) - for _, rule := range input { - out = append(out, &roomv1.RoomTreasureGiftEnergyRule{ - RuleId: rule.RuleID, - GiftId: rule.GiftID, - GiftTypeCode: rule.GiftTypeCode, - MultiplierPpm: rule.MultiplierPPM, - FixedEnergy: rule.FixedEnergy, - Excluded: rule.Excluded, - }) - } - return out -} - -func roomTreasureEnergyRulesFromProto(input []*roomv1.RoomTreasureGiftEnergyRule) []GiftEnergyRuleConfig { - out := make([]GiftEnergyRuleConfig, 0, len(input)) - for _, rule := range input { - if rule == nil { - continue - } - out = append(out, GiftEnergyRuleConfig{ - RuleID: rule.GetRuleId(), - GiftID: rule.GetGiftId(), - GiftTypeCode: rule.GetGiftTypeCode(), - MultiplierPPM: rule.GetMultiplierPpm(), - FixedEnergy: rule.GetFixedEnergy(), - Excluded: rule.GetExcluded(), - }) - } - return out -} diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index d1a71cd0..81048079 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -98,7 +98,7 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r // Check 只说明“允许按该 pool 抽奖”,真实价格、区域可用性和扣费仍以 wallet-service 为准。 luckyEnabled = true } - treasureConfig, err := s.roomTreasureConfig(ctx) + rocketConfig, err := s.roomRocketConfig(ctx) if err != nil { return mutationResult{}, nil, err } @@ -153,7 +153,7 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r current.Heat += heatValue current.GiftRank = localRank.ApplyGift(cmd.ActorUserID(), heatValue, now) current.Version++ - treasureApply, err := s.applyRoomTreasureGift(now, current, treasureConfig, cmd, &settledCommand, billing, roomMeta) + rocketApply, err := s.applyRoomRocketGift(now, current, rocketConfig, cmd, &settledCommand, billing, roomMeta) if err != nil { return mutationResult{}, nil, err } @@ -203,15 +203,15 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r records := make([]outbox.Record, 0, len(giftEvents)+4) records = append(records, giftEvents...) records = append(records, heatEvent, rankEvent) - if treasureApply.progressEvent != nil { - progressEvent, err := outbox.Build(current.RoomID, "RoomTreasureProgressChanged", current.Version, now, treasureApply.progressEvent) + if rocketApply.progressEvent != nil { + progressEvent, err := outbox.Build(current.RoomID, "RoomRocketFuelChanged", current.Version, now, rocketApply.progressEvent) if err != nil { return mutationResult{}, nil, err } records = append(records, progressEvent) } - if treasureApply.countdown != nil { - countdownEvent, err := outbox.Build(current.RoomID, "RoomTreasureCountdownStarted", current.Version, now, treasureApply.countdown) + if rocketApply.ignited != nil { + countdownEvent, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited) if err != nil { return mutationResult{}, nil, err } @@ -277,7 +277,7 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r RoomHeat: result.roomHeat, GiftRank: result.giftRank, Room: result.snapshot, - Treasure: result.snapshot.GetTreasure(), + Rocket: result.snapshot.GetRocket(), LuckyGift: result.luckyGift, LuckyGifts: result.luckyGifts, }, nil diff --git a/services/room-service/internal/room/service/gift_leaderboard_test.go b/services/room-service/internal/room/service/gift_leaderboard_test.go index c038b67a..03bee376 100644 --- a/services/room-service/internal/room/service/gift_leaderboard_test.go +++ b/services/room-service/internal/room/service/gift_leaderboard_test.go @@ -30,7 +30,7 @@ func (s *recordingRoomGiftLeaderboard) ListRoomGiftLeaderboard(context.Context, func TestSendGiftWritesRoomGiftLeaderboardWithHeatValue(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{ BillingReceiptId: "receipt-gift-leaderboard", CoinSpent: 100, ChargeAmount: 100, @@ -39,7 +39,7 @@ func TestSendGiftWritesRoomGiftLeaderboardWithHeatValue(t *testing.T) { GiftTypeCode: "lucky", }}} leaderboard := &recordingRoomGiftLeaderboard{} - now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 5, 12, 0, 0, 0, time.UTC)} + now := &fixedRoomRocketClock{now: time.Date(2026, 6, 5, 12, 0, 0, 0, time.UTC)} svc := roomservice.New(roomservice.Config{ NodeID: "node-gift-leaderboard-test", LeaseTTL: 10 * time.Second, @@ -52,8 +52,8 @@ func TestSendGiftWritesRoomGiftLeaderboardWithHeatValue(t *testing.T) { roomID := "room-gift-leaderboard" senderID := int64(18001) targetID := int64(18002) - createTreasureRoom(t, ctx, svc, roomID, senderID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, targetID) + createRocketRoom(t, ctx, svc, roomID, senderID, 9001) + joinRocketRoom(t, ctx, svc, roomID, targetID) if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ Meta: &roomv1.RequestMeta{ diff --git a/services/room-service/internal/room/service/kick_test.go b/services/room-service/internal/room/service/kick_test.go index 39f9aa2b..423139f1 100644 --- a/services/room-service/internal/room/service/kick_test.go +++ b/services/room-service/internal/room/service/kick_test.go @@ -105,7 +105,7 @@ func TestKickUserRemovesPresenceBanAndRTCConnection(t *testing.T) { func TestKickUserDurationExpiresAndAllowsJoin(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 28, 8, 0, 0, 0, time.UTC)} + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 28, 8, 0, 0, 0, time.UTC)} svc := roomservice.New(roomservice.Config{ NodeID: "node-kick-duration-test", LeaseTTL: 10 * time.Second, @@ -177,7 +177,7 @@ func TestKickUserDurationExpiresAndAllowsJoin(t *testing.T) { func TestListRoomBannedUsersReturnsActiveOnlyForManagers(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 29, 8, 0, 0, 0, time.UTC)} + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 29, 8, 0, 0, 0, time.UTC)} svc := roomservice.New(roomservice.Config{ NodeID: "node-banned-users-test", LeaseTTL: 10 * time.Second, diff --git a/services/room-service/internal/room/service/lucky_gift_test.go b/services/room-service/internal/room/service/lucky_gift_test.go index f4a94144..b2a6755d 100644 --- a/services/room-service/internal/room/service/lucky_gift_test.go +++ b/services/room-service/internal/room/service/lucky_gift_test.go @@ -75,7 +75,7 @@ func (c *luckyGiftTestClient) ExecuteLuckyGiftDraw(_ context.Context, req *activ func TestSendGiftReturnsLuckyGiftDrawResult(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{ BillingReceiptId: "receipt-lucky", CoinSpent: 100, GiftPointAdded: 100, @@ -118,8 +118,8 @@ func TestSendGiftReturnsLuckyGiftDrawResult(t *testing.T) { roomID := "room-lucky-gift" ownerID := int64(101) viewerID := int64(202) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, viewerID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9001) + joinRocketRoom(t, ctx, svc, roomID, viewerID) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ Meta: &roomv1.RequestMeta{ @@ -165,7 +165,7 @@ func TestSendGiftReturnsLuckyGiftDrawResult(t *testing.T) { func TestSendGiftReturnsLuckyGiftDrawResultsForMultipleTargets(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-lucky-202", CoinSpent: 100, ChargeAmount: 100, GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "super_lucky"}, {BillingReceiptId: "receipt-lucky-303", CoinSpent: 200, ChargeAmount: 200, GiftPointAdded: 200, HeatValue: 200, GiftTypeCode: "super_lucky"}, }} @@ -181,9 +181,9 @@ func TestSendGiftReturnsLuckyGiftDrawResultsForMultipleTargets(t *testing.T) { ownerID := int64(101) firstTargetID := int64(202) secondTargetID := int64(303) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, firstTargetID) - joinTreasureRoom(t, ctx, svc, roomID, secondTargetID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9001) + joinRocketRoom(t, ctx, svc, roomID, firstTargetID) + joinRocketRoom(t, ctx, svc, roomID, secondTargetID) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ Meta: &roomv1.RequestMeta{ diff --git a/services/room-service/internal/room/service/mic_test.go b/services/room-service/internal/room/service/mic_test.go index fc4c962e..238a022c 100644 --- a/services/room-service/internal/room/service/mic_test.go +++ b/services/room-service/internal/room/service/mic_test.go @@ -12,17 +12,17 @@ import ( func TestMicHeartbeatRefreshesPublishingSessionAndPresence(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} - svc := newTreasureTestService(t, repository, &treasureTestWallet{}, now) + now := &fixedRoomRocketClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} + svc := newRocketTestService(t, repository, &rocketTestWallet{}, now) roomID := "room-mic-heartbeat" ownerID := int64(8601) speakerID := int64(8602) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9101) - joinTreasureRoom(t, ctx, svc, roomID, speakerID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9101) + joinRocketRoom(t, ctx, svc, roomID, speakerID) upResp, err := svc.MicUp(ctx, &roomv1.MicUpRequest{ - Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-up"), + Meta: rocketMeta(roomID, speakerID, "mic-heartbeat-up"), SeatNo: 2, }) if err != nil { @@ -30,7 +30,7 @@ func TestMicHeartbeatRefreshesPublishingSessionAndPresence(t *testing.T) { } now.now = now.now.Add(500 * time.Millisecond) confirmResp, err := svc.ConfirmMicPublishing(ctx, &roomv1.ConfirmMicPublishingRequest{ - Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-confirm"), + Meta: rocketMeta(roomID, speakerID, "mic-heartbeat-confirm"), MicSessionId: upResp.GetMicSessionId(), RoomVersion: upResp.GetRoom().GetVersion(), EventTimeMs: now.Now().UnixMilli(), @@ -47,7 +47,7 @@ func TestMicHeartbeatRefreshesPublishingSessionAndPresence(t *testing.T) { now.now = now.now.Add(3 * time.Second) heartbeatAtMS := now.Now().UnixMilli() heartbeatResp, err := svc.MicHeartbeat(ctx, &roomv1.MicHeartbeatRequest{ - Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-refresh"), + Meta: rocketMeta(roomID, speakerID, "mic-heartbeat-refresh"), MicSessionId: upResp.GetMicSessionId(), }) if err != nil { @@ -69,24 +69,24 @@ func TestMicHeartbeatRefreshesPublishingSessionAndPresence(t *testing.T) { func TestMicHeartbeatRejectsPendingSession(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} - svc := newTreasureTestService(t, repository, &treasureTestWallet{}, now) + now := &fixedRoomRocketClock{now: time.Date(2026, 6, 4, 8, 0, 0, 0, time.UTC)} + svc := newRocketTestService(t, repository, &rocketTestWallet{}, now) roomID := "room-mic-heartbeat-pending" ownerID := int64(8701) speakerID := int64(8702) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9101) - joinTreasureRoom(t, ctx, svc, roomID, speakerID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9101) + joinRocketRoom(t, ctx, svc, roomID, speakerID) upResp, err := svc.MicUp(ctx, &roomv1.MicUpRequest{ - Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-pending-up"), + Meta: rocketMeta(roomID, speakerID, "mic-heartbeat-pending-up"), SeatNo: 1, }) if err != nil { t.Fatalf("mic up failed: %v", err) } if _, err := svc.MicHeartbeat(ctx, &roomv1.MicHeartbeatRequest{ - Meta: treasureMeta(roomID, speakerID, "mic-heartbeat-pending-refresh"), + Meta: rocketMeta(roomID, speakerID, "mic-heartbeat-pending-refresh"), MicSessionId: upResp.GetMicSessionId(), }); err == nil { t.Fatalf("pending_publish session must not accept mic heartbeat before publish confirmation") diff --git a/services/room-service/internal/room/service/online_users_test.go b/services/room-service/internal/room/service/online_users_test.go index 025e605a..dd219483 100644 --- a/services/room-service/internal/room/service/online_users_test.go +++ b/services/room-service/internal/room/service/online_users_test.go @@ -16,23 +16,23 @@ import ( func TestListRoomOnlineUsersReturnsOwnerAdminRoleAndGiftValue(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{ BillingReceiptId: "receipt-online-users", CoinSpent: 321, GiftPointAdded: 321, HeatValue: 321, GiftTypeCode: "normal", }}} - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 27, 12, 0, 0, 0, time.UTC)} - svc := newTreasureTestService(t, repository, wallet, now) + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 27, 12, 0, 0, 0, time.UTC)} + svc := newRocketTestService(t, repository, wallet, now) roomID := "room-online-users" ownerID := int64(1001) adminID := int64(1002) normalID := int64(1003) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, adminID) - joinTreasureRoom(t, ctx, svc, roomID, normalID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9001) + joinRocketRoom(t, ctx, svc, roomID, adminID) + joinRocketRoom(t, ctx, svc, roomID, normalID) if _, err := svc.SetRoomAdmin(ctx, &roomv1.SetRoomAdminRequest{ Meta: roomservice.NewRequestMeta(roomID, ownerID), @@ -50,7 +50,7 @@ func TestListRoomOnlineUsersReturnsOwnerAdminRoleAndGiftValue(t *testing.T) { } if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, adminID, "online-users-gift"), + Meta: rocketMeta(roomID, adminID, "online-users-gift"), TargetType: "user", TargetUserId: ownerID, GiftId: "gift-online-users", @@ -97,7 +97,7 @@ func TestListRoomOnlineUsersReturnsOwnerAdminRoleAndGiftValue(t *testing.T) { func TestSendGiftPassesHostPeriodScopeToWallet(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{{ + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{{ BillingReceiptId: "receipt-host-period", CoinSpent: 14, GiftPointAdded: 6, @@ -106,17 +106,17 @@ func TestSendGiftPassesHostPeriodScopeToWallet(t *testing.T) { HostPeriodDiamondAdded: 14, HostPeriodCycleKey: "2026-05", }}} - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 27, 12, 0, 0, 0, time.UTC)} - svc := newTreasureTestService(t, repository, wallet, now) + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 27, 12, 0, 0, 0, time.UTC)} + svc := newRocketTestService(t, repository, wallet, now) roomID := "room-host-period-scope" senderID := int64(2001) hostID := int64(2002) - createTreasureRoom(t, ctx, svc, roomID, senderID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, hostID) + createRocketRoom(t, ctx, svc, roomID, senderID, 9001) + joinRocketRoom(t, ctx, svc, roomID, hostID) if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, senderID, "host-period-scope"), + Meta: rocketMeta(roomID, senderID, "host-period-scope"), TargetType: "user", TargetUserId: hostID, GiftId: "gift-host-period", diff --git a/services/room-service/internal/room/service/outbox_worker.go b/services/room-service/internal/room/service/outbox_worker.go index 54b8fd7c..10315f25 100644 --- a/services/room-service/internal/room/service/outbox_worker.go +++ b/services/room-service/internal/room/service/outbox_worker.go @@ -204,8 +204,8 @@ func (s *Service) ProcessPendingOutbox(ctx context.Context, options OutboxWorker } func (s *Service) publishOutboxRecord(ctx context.Context, record outbox.Record) error { - // Countdown 先安排延迟开箱,再对外广播事件;如果 MQ 延迟调度不可用,本条 outbox 保持 retryable。 - if err := s.scheduleRoomTreasureOpenFromEnvelope(ctx, record.Envelope); err != nil { + // Ignited 先安排延迟发射,再对外广播事件;如果 MQ 延迟调度不可用,本条 outbox 保持 retryable。 + if err := s.scheduleRoomRocketLaunchFromEnvelope(ctx, record.Envelope); err != nil { return err } if s.outboxPublisher == nil { diff --git a/services/room-service/internal/room/service/recovery.go b/services/room-service/internal/room/service/recovery.go index accf688d..e2b06552 100644 --- a/services/room-service/internal/room/service/recovery.go +++ b/services/room-service/internal/room/service/recovery.go @@ -400,55 +400,87 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64) }) } - if typed.TreasureTouched { - current.Treasure = treasureStateFromSettledGift(typed) + if typed.RocketTouched { + current.Rocket = rocketStateFromSettledGift(typed) } current.Version++ - case *command.OpenRoomTreasure: - if current.Treasure == nil || current.Treasure.BoxID != typed.BoxID { - // 开箱命令必须对应当前倒计时宝箱;如果快照已包含更新后的下一轮状态,回放保持幂等。 + case *command.LaunchRoomRocket: + if current.Rocket == nil || !rocketPendingLaunchExists(current.Rocket.PendingLaunches, typed.RocketID, typed.Level) { + // 发射命令必须对应待发射队列中的火箭;如果快照已包含移除后的状态,回放保持幂等。 return nil } - current.Treasure = treasureStateFromOpenCommand(typed) + current.Rocket = rocketStateFromLaunchCommand(typed) current.Version++ } return nil } -func treasureStateFromSettledGift(cmd *command.SendGift) *state.TreasureState { - return &state.TreasureState{ - CurrentLevel: cmd.TreasureLevel, - CurrentProgress: cmd.TreasureProgress, - EnergyThreshold: cmd.TreasureEnergyThreshold, - Status: cmd.TreasureStatus, - CountdownStartedAtMS: cmd.TreasureCountdownStartedAtMS, - OpenAtMS: cmd.TreasureOpenAtMS, - ResetAtMS: cmd.TreasureResetAtMS, - Top1UserID: cmd.TreasureTop1UserID, - IgniterUserID: cmd.TreasureIgniterUserID, - BoxID: cmd.TreasureBoxID, - ConfigVersion: cmd.TreasureConfigVersion, +func rocketStateFromSettledGift(cmd *command.SendGift) *state.RocketState { + return &state.RocketState{ + CurrentLevel: cmd.RocketLevel, + CurrentFuel: cmd.RocketFuel, + FuelThreshold: cmd.RocketFuelThreshold, + Status: cmd.RocketStatus, + IgnitedAtMS: cmd.RocketIgnitedAtMS, + LaunchAtMS: cmd.RocketLaunchAtMS, + ResetAtMS: cmd.RocketResetAtMS, + Top1UserID: cmd.RocketTop1UserID, + IgniterUserID: cmd.RocketIgniterUserID, + RocketID: cmd.RocketID, + ConfigVersion: cmd.RocketConfigVersion, + PendingLaunches: rocketPendingLaunchesFromCommand(cmd.RocketPendingLaunches), } } -func treasureStateFromOpenCommand(cmd *command.OpenRoomTreasure) *state.TreasureState { - return &state.TreasureState{ - CurrentLevel: cmd.NextLevel, - EnergyThreshold: cmd.NextEnergyThreshold, - Status: state.TreasureStatusIdle, - OpenedAtMS: cmd.SentAtMS, +func rocketStateFromLaunchCommand(cmd *command.LaunchRoomRocket) *state.RocketState { + return &state.RocketState{ + CurrentLevel: cmd.CurrentLevel, + CurrentFuel: cmd.CurrentFuel, + FuelThreshold: cmd.CurrentFuelThreshold, + Status: cmd.CurrentStatus, + LaunchedAtMS: cmd.LaunchedAtMS, ResetAtMS: cmd.ResetAtMS, + RocketID: cmd.CurrentRocketID, ConfigVersion: cmd.ConfigVersion, - LastRewards: treasureRewardsFromCommand(cmd.Rewards), + PendingLaunches: rocketPendingLaunchesFromCommand(cmd.PendingLaunches), + LastRewards: rocketRewardsFromCommand(cmd.Rewards), } } -func treasureRewardsFromCommand(input []command.TreasureRewardGrant) []state.TreasureRewardGrant { - rewards := make([]state.TreasureRewardGrant, 0, len(input)) +func rocketPendingLaunchExists(input []state.RocketPendingLaunch, rocketID string, level int32) bool { + for _, launch := range input { + if launch.RocketID == rocketID && launch.Level == level { + return true + } + } + return false +} + +func rocketPendingLaunchesFromCommand(input []command.RocketPendingLaunch) []state.RocketPendingLaunch { + launches := make([]state.RocketPendingLaunch, 0, len(input)) + for _, launch := range input { + launches = append(launches, state.RocketPendingLaunch{ + RocketID: launch.RocketID, + Level: launch.Level, + FuelThreshold: launch.FuelThreshold, + IgnitedAtMS: launch.IgnitedAtMS, + LaunchAtMS: launch.LaunchAtMS, + ResetAtMS: launch.ResetAtMS, + Top1UserID: launch.Top1UserID, + IgniterUserID: launch.IgniterUserID, + ConfigVersion: launch.ConfigVersion, + CoverURL: launch.CoverURL, + }) + } + return launches +} + +func rocketRewardsFromCommand(input []command.RocketRewardGrant) []state.RocketRewardGrant { + rewards := make([]state.RocketRewardGrant, 0, len(input)) for _, reward := range input { - rewards = append(rewards, state.TreasureRewardGrant{ + rewards = append(rewards, state.RocketRewardGrant{ RewardRole: reward.RewardRole, UserID: reward.UserID, RewardItemID: reward.RewardItemID, diff --git a/services/room-service/internal/room/service/repository.go b/services/room-service/internal/room/service/repository.go index 8df2eb55..37b28a5b 100644 --- a/services/room-service/internal/room/service/repository.go +++ b/services/room-service/internal/room/service/repository.go @@ -247,39 +247,39 @@ type RoomSeatConfig struct { UpdatedAtMS int64 } -// RoomTreasureConfig 是后台语音房宝箱配置的运行时快照。 -type RoomTreasureConfig struct { +// RoomRocketConfig 是后台语音房火箭配置的运行时快照。 +type RoomRocketConfig struct { AppCode string Enabled bool ConfigVersion int64 - EnergySource string - OpenDelayMS int64 + FuelSource string + LaunchDelayMS int64 BroadcastEnabled bool BroadcastScope string BroadcastDelayMS int64 RewardStackPolicy string - Levels []RoomTreasureLevelConfig - GiftEnergyRules []GiftEnergyRuleConfig + Levels []RoomRocketLevelConfig + GiftFuelRules []GiftFuelRuleConfig UpdatedByAdminID int64 CreatedAtMS int64 UpdatedAtMS int64 } -// RoomTreasureLevelConfig 描述单个等级的物料、阈值和三类奖励池。 -type RoomTreasureLevelConfig struct { - Level int32 `json:"level"` - EnergyThreshold int64 `json:"energyThreshold"` - CoverURL string `json:"coverUrl"` - AnimationURL string `json:"animationUrl"` - OpeningAnimationURL string `json:"openingAnimationUrl"` - OpenedImageURL string `json:"openedImageUrl"` - InRoomRewards []RoomTreasureRewardItem `json:"inRoomRewards"` - Top1Rewards []RoomTreasureRewardItem `json:"top1Rewards"` - IgniterRewards []RoomTreasureRewardItem `json:"igniterRewards"` +// RoomRocketLevelConfig 描述单个等级的物料、阈值和三类奖励池。 +type RoomRocketLevelConfig struct { + Level int32 `json:"level"` + FuelThreshold int64 `json:"fuelThreshold"` + CoverURL string `json:"coverUrl"` + AnimationURL string `json:"animationUrl"` + LaunchAnimationURL string `json:"launchAnimationUrl"` + LaunchedImageURL string `json:"launchedImageUrl"` + InRoomRewards []RoomRocketRewardItem `json:"inRoomRewards"` + Top1Rewards []RoomRocketRewardItem `json:"top1Rewards"` + IgniterRewards []RoomRocketRewardItem `json:"igniterRewards"` } -// RoomTreasureRewardItem 是后台配置中的奖励候选项。 -type RoomTreasureRewardItem struct { +// RoomRocketRewardItem 是后台配置中的奖励候选项。 +type RoomRocketRewardItem struct { RewardItemID string `json:"rewardItemId"` ResourceGroupID int64 `json:"resourceGroupId"` Weight int64 `json:"weight"` @@ -287,13 +287,13 @@ type RoomTreasureRewardItem struct { IconURL string `json:"iconUrl"` } -// GiftEnergyRuleConfig 控制特定礼物或礼物类型如何覆盖默认能量计算。 -type GiftEnergyRuleConfig struct { +// GiftFuelRuleConfig 控制特定礼物或礼物类型如何覆盖默认燃料计算。 +type GiftFuelRuleConfig struct { RuleID string `json:"ruleId"` GiftID string `json:"giftId"` GiftTypeCode string `json:"giftTypeCode"` MultiplierPPM int64 `json:"multiplierPpm"` - FixedEnergy int64 `json:"fixedEnergy"` + FixedFuel int64 `json:"fixedFuel"` Excluded bool `json:"excluded"` } @@ -508,10 +508,10 @@ type Repository interface { GetRoomSeatConfig(ctx context.Context) (RoomSeatConfig, bool, error) // UpsertRoomSeatConfig 写入房间座位数配置,供本地验证和后台配置共享同一张表。 UpsertRoomSeatConfig(ctx context.Context, config RoomSeatConfig) error - // GetRoomTreasureConfig 读取语音房宝箱低频配置;不存在时 service 层使用关闭态默认配置。 - GetRoomTreasureConfig(ctx context.Context) (RoomTreasureConfig, bool, error) - // UpsertRoomTreasureConfig 写入语音房宝箱配置,主要供集成测试和本地验证复用生产表结构。 - UpsertRoomTreasureConfig(ctx context.Context, config RoomTreasureConfig) error + // GetRoomRocketConfig 读取语音房火箭低频配置;不存在时 service 层使用关闭态默认配置。 + GetRoomRocketConfig(ctx context.Context) (RoomRocketConfig, bool, error) + // UpsertRoomRocketConfig 写入语音房火箭配置,主要供集成测试和本地验证复用生产表结构。 + UpsertRoomRocketConfig(ctx context.Context, config RoomRocketConfig) error // ListCommandsAfter 读取快照版本之后的命令,恢复时按版本顺序回放。 ListCommandsAfter(ctx context.Context, roomID string, roomVersion int64) ([]CommandRecord, error) // SaveSnapshot 保存最新房间快照,允许覆盖较低版本号快照但不能倒退。 diff --git a/services/room-service/internal/room/service/room_rocket.go b/services/room-service/internal/room/service/room_rocket.go new file mode 100644 index 00000000..470552d7 --- /dev/null +++ b/services/room-service/internal/room/service/room_rocket.go @@ -0,0 +1,1075 @@ +package service + +import ( + "context" + "crypto/sha256" + "encoding/binary" + "fmt" + "slices" + "strings" + "time" + + roomeventsv1 "hyapp.local/api/proto/events/room/v1" + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/roomid" + "hyapp/pkg/xerr" + "hyapp/services/room-service/internal/room/command" + "hyapp/services/room-service/internal/room/outbox" + "hyapp/services/room-service/internal/room/rank" + "hyapp/services/room-service/internal/room/state" +) + +const ( + roomRocketLevelCount = 5 + + roomRocketDefaultFuelSource = "heat_value" + roomRocketDefaultLaunchDelayMS = int64(30_000) + roomRocketDefaultBroadcastScope = "region" + roomRocketDefaultRewardStackPolicy = "allow_stack" + + roomRocketFuelHeatValue = "heat_value" + + roomRocketBroadcastNone = "none" + roomRocketBroadcastRegion = "region" + roomRocketBroadcastGlobal = "global" + + roomRocketRewardStackAllow = "allow_stack" + roomRocketRewardStackPriority = "priority_only" + + roomRocketRewardInRoom = "in_room" + roomRocketRewardTop1 = "top1" + roomRocketRewardIgniter = "igniter" + roomRocketGrantSource = "room_rocket" + roomRocketGrantStatus = "succeeded" +) + +var roomRocketDefaultThresholds = []int64{1_000, 3_000, 6_000, 10_000, 15_000} + +// GetRoomRocket 返回房间火箭 UI 初始化数据;它只读 Room Cell,不刷新 presence。 +func (s *Service) GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + roomID := strings.TrimSpace(req.GetRoomId()) + viewerUserID := req.GetViewerUserId() + if !roomid.ValidStringID(roomID) { + return nil, xerr.New(xerr.InvalidArgument, "room_id is invalid") + } + if viewerUserID <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "viewer_user_id is required") + } + + snapshot, err := s.currentSnapshot(ctx, roomID) + if err != nil { + return nil, err + } + if snapshot == nil || snapshot.GetRoomId() == "" { + return nil, xerr.New(xerr.NotFound, "room not found") + } + if snapshot.GetStatus() != state.RoomStatusActive { + return nil, xerr.New(xerr.RoomClosed, "room closed") + } + if snapshotUserBanned(snapshot, viewerUserID, s.clock.Now().UnixMilli()) || findProtoUser(snapshot, viewerUserID) == nil { + // 火箭状态属于房间内活动信息,只允许仍在业务 presence 内的用户读取。 + return nil, xerr.New(xerr.PermissionDenied, "viewer is not in room") + } + + config, err := s.roomRocketConfig(ctx) + if err != nil { + return nil, err + } + now := s.clock.Now().UTC() + info := roomRocketInfoFromConfig(config, snapshot.GetRocket(), now) + return &roomv1.GetRoomRocketResponse{ + Rocket: info, + ServerTimeMs: now.UnixMilli(), + }, nil +} + +func (s *Service) roomRocketConfig(ctx context.Context) (RoomRocketConfig, error) { + config, exists, err := s.repository.GetRoomRocketConfig(ctx) + if err != nil { + return RoomRocketConfig{}, err + } + if !exists { + config = defaultRoomRocketConfig(appcode.FromContext(ctx)) + } + return normalizeRoomRocketConfig(config) +} + +func defaultRoomRocketConfig(appCode string) RoomRocketConfig { + levels := make([]RoomRocketLevelConfig, 0, roomRocketLevelCount) + for index, threshold := range roomRocketDefaultThresholds { + levels = append(levels, RoomRocketLevelConfig{ + Level: int32(index + 1), + FuelThreshold: threshold, + }) + } + return RoomRocketConfig{ + AppCode: appcode.Normalize(appCode), + FuelSource: roomRocketDefaultFuelSource, + LaunchDelayMS: roomRocketDefaultLaunchDelayMS, + BroadcastEnabled: true, + BroadcastScope: roomRocketDefaultBroadcastScope, + RewardStackPolicy: roomRocketDefaultRewardStackPolicy, + Levels: levels, + } +} + +func normalizeRoomRocketConfig(config RoomRocketConfig) (RoomRocketConfig, error) { + config.AppCode = appcode.Normalize(config.AppCode) + if config.AppCode == "" { + config.AppCode = appcode.Default + } + if config.ConfigVersion < 0 { + return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket config_version is invalid") + } + config.FuelSource = defaultRoomRocketString(config.FuelSource, roomRocketDefaultFuelSource) + if config.FuelSource == "gift_point_added" { + // 旧配置可能还存着 gift_point_added;GIFT_POINT 已下线,运行时统一按真实送礼贡献 heat_value 计算火箭燃料。 + config.FuelSource = roomRocketFuelHeatValue + } + if config.FuelSource != roomRocketFuelHeatValue { + return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket fuel_source is invalid") + } + if config.LaunchDelayMS < 0 || config.BroadcastDelayMS < 0 { + return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket delay is invalid") + } + config.BroadcastScope = defaultRoomRocketString(config.BroadcastScope, roomRocketDefaultBroadcastScope) + if config.BroadcastScope != roomRocketBroadcastNone && config.BroadcastScope != roomRocketBroadcastRegion && config.BroadcastScope != roomRocketBroadcastGlobal { + return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket broadcast_scope is invalid") + } + if !config.BroadcastEnabled { + config.BroadcastScope = roomRocketBroadcastNone + } + config.RewardStackPolicy = defaultRoomRocketString(config.RewardStackPolicy, roomRocketDefaultRewardStackPolicy) + if config.RewardStackPolicy != roomRocketRewardStackAllow && config.RewardStackPolicy != roomRocketRewardStackPriority { + return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket reward_stack_policy is invalid") + } + + levels, err := normalizeRoomRocketLevels(config.Levels) + if err != nil { + return RoomRocketConfig{}, err + } + config.Levels = levels + config.GiftFuelRules = normalizeRoomRocketFuelRules(config.GiftFuelRules) + return config, nil +} + +func normalizeRoomRocketLevels(levels []RoomRocketLevelConfig) ([]RoomRocketLevelConfig, error) { + if len(levels) == 0 { + return defaultRoomRocketConfig(appcode.Default).Levels, nil + } + if len(levels) != roomRocketLevelCount { + return nil, xerr.New(xerr.InvalidArgument, "room rocket levels must be 5") + } + seen := make(map[int32]bool, roomRocketLevelCount) + normalized := make([]RoomRocketLevelConfig, 0, roomRocketLevelCount) + for _, level := range levels { + if level.Level < 1 || level.Level > roomRocketLevelCount || seen[level.Level] { + return nil, xerr.New(xerr.InvalidArgument, "room rocket level is invalid") + } + if level.FuelThreshold <= 0 { + return nil, xerr.New(xerr.InvalidArgument, "room rocket fuel_threshold is invalid") + } + seen[level.Level] = true + level.CoverURL = strings.TrimSpace(level.CoverURL) + level.AnimationURL = strings.TrimSpace(level.AnimationURL) + level.LaunchAnimationURL = strings.TrimSpace(level.LaunchAnimationURL) + level.LaunchedImageURL = strings.TrimSpace(level.LaunchedImageURL) + level.InRoomRewards = normalizeRoomRocketRewardPool(level.InRoomRewards) + level.Top1Rewards = normalizeRoomRocketRewardPool(level.Top1Rewards) + level.IgniterRewards = normalizeRoomRocketRewardPool(level.IgniterRewards) + normalized = append(normalized, level) + } + slices.SortFunc(normalized, func(left, right RoomRocketLevelConfig) int { + return int(left.Level - right.Level) + }) + return normalized, nil +} + +func normalizeRoomRocketRewardPool(input []RoomRocketRewardItem) []RoomRocketRewardItem { + out := make([]RoomRocketRewardItem, 0, len(input)) + for _, reward := range input { + reward.RewardItemID = strings.TrimSpace(reward.RewardItemID) + reward.DisplayName = strings.TrimSpace(reward.DisplayName) + reward.IconURL = strings.TrimSpace(reward.IconURL) + if reward.ResourceGroupID <= 0 || reward.Weight <= 0 { + // 后台保存层会拒绝非法奖励;运行时跳过历史脏项,避免一个奖励池配置污染送礼主链路。 + continue + } + out = append(out, reward) + } + return out +} + +func normalizeRoomRocketFuelRules(input []GiftFuelRuleConfig) []GiftFuelRuleConfig { + out := make([]GiftFuelRuleConfig, 0, len(input)) + for _, rule := range input { + rule.RuleID = strings.TrimSpace(rule.RuleID) + rule.GiftID = strings.TrimSpace(rule.GiftID) + rule.GiftTypeCode = strings.TrimSpace(rule.GiftTypeCode) + if rule.GiftID == "" && rule.GiftTypeCode == "" { + continue + } + if rule.MultiplierPPM < 0 || rule.FixedFuel < 0 { + continue + } + out = append(out, rule) + } + return out +} + +func defaultRoomRocketString(value string, fallback string) string { + value = strings.TrimSpace(value) + if value == "" { + return fallback + } + return value +} + +func roomRocketInfoFromConfig(config RoomRocketConfig, current *roomv1.RoomRocketState, now time.Time) *roomv1.RoomRocketInfo { + stateView := roomRocketProtoStateForView(current, config, now) + return &roomv1.RoomRocketInfo{ + Enabled: config.Enabled, + Levels: roomRocketLevelsToProto(config.Levels), + State: stateView, + ServerTimeMs: now.UnixMilli(), + BroadcastScope: config.BroadcastScope, + LaunchDelayMs: config.LaunchDelayMS, + BroadcastDelayMs: config.BroadcastDelayMS, + RewardStackPolicy: config.RewardStackPolicy, + } +} + +func roomRocketProtoStateForView(current *roomv1.RoomRocketState, config RoomRocketConfig, now time.Time) *roomv1.RoomRocketState { + internal := state.RocketState{} + if current != nil { + internal = state.RocketState{ + CurrentLevel: current.GetCurrentLevel(), + CurrentFuel: current.GetCurrentFuel(), + FuelThreshold: current.GetFuelThreshold(), + Status: current.GetStatus(), + IgnitedAtMS: current.GetIgnitedAtMs(), + LaunchAtMS: current.GetLaunchAtMs(), + LaunchedAtMS: current.GetLaunchedAtMs(), + ResetAtMS: current.GetResetAtMs(), + Top1UserID: current.GetTop1UserId(), + IgniterUserID: current.GetIgniterUserId(), + RocketID: current.GetRocketId(), + ConfigVersion: current.GetConfigVersion(), + PendingLaunches: statePendingLaunchesFromProto(current.GetPendingLaunches()), + LastRewards: stateRewardsFromProto(current.GetLastRewards()), + } + } + normalized := rocketStateForNow(&internal, config, now, false) + return rocketStateToRoomProto(normalized) +} + +func stateRewardsFromProto(input []*roomv1.RoomRocketRewardGrant) []state.RocketRewardGrant { + out := make([]state.RocketRewardGrant, 0, len(input)) + for _, reward := range input { + out = append(out, state.RocketRewardGrant{ + RewardRole: reward.GetRewardRole(), + UserID: reward.GetUserId(), + RewardItemID: reward.GetRewardItemId(), + ResourceGroupID: reward.GetResourceGroupId(), + DisplayName: reward.GetDisplayName(), + IconURL: reward.GetIconUrl(), + GrantID: reward.GetGrantId(), + Status: reward.GetStatus(), + }) + } + return out +} + +func statePendingLaunchesFromProto(input []*roomv1.RoomRocketPendingLaunch) []state.RocketPendingLaunch { + out := make([]state.RocketPendingLaunch, 0, len(input)) + for _, launch := range input { + out = append(out, state.RocketPendingLaunch{ + RocketID: launch.GetRocketId(), + Level: launch.GetLevel(), + FuelThreshold: launch.GetFuelThreshold(), + IgnitedAtMS: launch.GetIgnitedAtMs(), + LaunchAtMS: launch.GetLaunchAtMs(), + ResetAtMS: launch.GetResetAtMs(), + Top1UserID: launch.GetTop1UserId(), + IgniterUserID: launch.GetIgniterUserId(), + ConfigVersion: launch.GetConfigVersion(), + CoverURL: launch.GetCoverUrl(), + }) + } + return out +} + +func roomRocketLevelsToProto(levels []RoomRocketLevelConfig) []*roomv1.RoomRocketLevel { + out := make([]*roomv1.RoomRocketLevel, 0, len(levels)) + for _, level := range levels { + out = append(out, &roomv1.RoomRocketLevel{ + Level: level.Level, + FuelThreshold: level.FuelThreshold, + CoverUrl: level.CoverURL, + AnimationUrl: level.AnimationURL, + LaunchAnimationUrl: level.LaunchAnimationURL, + LaunchedImageUrl: level.LaunchedImageURL, + InRoomRewards: roomRocketRewardsToProto(level.InRoomRewards), + Top1Rewards: roomRocketRewardsToProto(level.Top1Rewards), + IgniterRewards: roomRocketRewardsToProto(level.IgniterRewards), + }) + } + return out +} + +func roomRocketRewardsToProto(input []RoomRocketRewardItem) []*roomv1.RoomRocketRewardItem { + out := make([]*roomv1.RoomRocketRewardItem, 0, len(input)) + for _, reward := range input { + out = append(out, &roomv1.RoomRocketRewardItem{ + RewardItemId: reward.RewardItemID, + ResourceGroupId: reward.ResourceGroupID, + Weight: reward.Weight, + DisplayName: reward.DisplayName, + IconUrl: reward.IconURL, + }) + } + return out +} + +type rocketGiftApplyResult struct { + touched bool + progressEvent *roomeventsv1.RoomRocketFuelChanged + ignited *roomeventsv1.RoomRocketIgnited +} + +func (s *Service) applyRoomRocketGift(now time.Time, current *state.RoomState, cfg RoomRocketConfig, cmd command.SendGift, settled *command.SendGift, billing *walletv1.DebitGiftResponse, roomMeta RoomMeta) (rocketGiftApplyResult, error) { + if !cfg.Enabled { + return rocketGiftApplyResult{}, nil + } + now = now.UTC() + nowMS := now.UnixMilli() + rocket := rocketStateForNow(current.Rocket, cfg, now, true) + result := rocketGiftApplyResult{touched: current.Rocket == nil || rocket.ResetAtMS != current.Rocket.ResetAtMS} + + addedFuel := roomRocketFuel(cfg, cmd.GiftID, billing.GetGiftTypeCode(), billing.GetHeatValue()) + effectiveFuel := int64(0) + overflowFuel := int64(0) + progressRocketID := rocket.RocketID + progressLevel := rocket.CurrentLevel + progressFuel := rocket.CurrentFuel + progressThreshold := rocket.FuelThreshold + progressStatus := rocket.Status + + if rocket.Status == state.RocketStatusCompleted { + // 当天最高 5 级已满后,继续送礼不再产生新火箭;整笔燃料按产品规则直接作废。 + overflowFuel = addedFuel + } else if addedFuel > 0 { + remaining := rocket.FuelThreshold - rocket.CurrentFuel + if remaining < 0 { + remaining = 0 + } + effectiveFuel = minInt64(addedFuel, remaining) + overflowFuel = addedFuel - effectiveFuel + if effectiveFuel > 0 { + rocket.CurrentFuel += effectiveFuel + progressFuel = rocket.CurrentFuel + result.touched = true + } + if rocket.CurrentFuel >= rocket.FuelThreshold { + levelCfg := roomRocketLevelByNumber(cfg, rocket.CurrentLevel) + pending := state.RocketPendingLaunch{ + RocketID: rocket.RocketID, + Level: rocket.CurrentLevel, + FuelThreshold: rocket.FuelThreshold, + IgnitedAtMS: nowMS, + LaunchAtMS: nowMS + cfg.LaunchDelayMS, + ResetAtMS: rocket.ResetAtMS, + Top1UserID: firstRankUserID(current.GiftRank), + IgniterUserID: cmd.ActorUserID(), + ConfigVersion: cfg.ConfigVersion, + CoverURL: levelCfg.CoverURL, + } + rocket.CurrentFuel = rocket.FuelThreshold + rocket.IgnitedAtMS = pending.IgnitedAtMS + rocket.LaunchAtMS = pending.LaunchAtMS + rocket.Top1UserID = pending.Top1UserID + rocket.IgniterUserID = pending.IgniterUserID + rocket.ConfigVersion = cfg.ConfigVersion + rocket.PendingLaunches = append(rocket.PendingLaunches, pending) + progressRocketID = pending.RocketID + progressLevel = pending.Level + progressFuel = pending.FuelThreshold + progressThreshold = pending.FuelThreshold + progressStatus = state.RocketStatusIgnited + result.ignited = &roomeventsv1.RoomRocketIgnited{ + RocketId: pending.RocketID, + Level: pending.Level, + CurrentFuel: pending.FuelThreshold, + FuelThreshold: pending.FuelThreshold, + IgnitedAtMs: pending.IgnitedAtMS, + LaunchAtMs: pending.LaunchAtMS, + BroadcastScope: cfg.BroadcastScope, + VisibleRegionId: roomMeta.VisibleRegionID, + Top1UserId: pending.Top1UserID, + IgniterUserId: pending.IgniterUserID, + CommandId: cmd.ID(), + RoomShortId: roomMeta.RoomShortID, + RocketCoverUrl: pending.CoverURL, + ResetAtMs: pending.ResetAtMS, + } + if rocket.CurrentLevel < roomRocketLevelCount { + nextLevel := rocket.CurrentLevel + 1 + nextLevelCfg := roomRocketLevelByNumber(cfg, nextLevel) + rocket.CurrentLevel = nextLevel + rocket.CurrentFuel = 0 + rocket.FuelThreshold = nextLevelCfg.FuelThreshold + rocket.Status = state.RocketStatusCharging + rocket.RocketID = idgen.New("room_rocket") + } else { + // 5 级是当天最高等级;点火后不再生成第 6 级,UTC 日界统一重置回 1 级。 + rocket.Status = state.RocketStatusCompleted + rocket.RocketID = "" + } + } + } + + if result.touched { + current.Rocket = rocket + } + if effectiveFuel > 0 { + result.progressEvent = &roomeventsv1.RoomRocketFuelChanged{ + RocketId: progressRocketID, + Level: progressLevel, + AddedFuel: addedFuel, + EffectiveAddedFuel: effectiveFuel, + OverflowFuel: overflowFuel, + CurrentFuel: progressFuel, + FuelThreshold: progressThreshold, + Status: progressStatus, + ResetAtMs: rocket.ResetAtMS, + SenderUserId: cmd.ActorUserID(), + GiftId: cmd.GiftID, + GiftCount: cmd.GiftCount, + CommandId: cmd.ID(), + VisibleRegionId: roomMeta.VisibleRegionID, + } + } + + if result.touched { + settled.GiftTypeCode = billing.GetGiftTypeCode() + settled.RocketTouched = true + settled.RocketAddedFuel = addedFuel + settled.RocketEffectiveFuel = effectiveFuel + settled.RocketOverflowFuel = overflowFuel + settled.RocketLevel = rocket.CurrentLevel + settled.RocketFuel = rocket.CurrentFuel + settled.RocketStatus = rocket.Status + settled.RocketFuelThreshold = rocket.FuelThreshold + settled.RocketIgnitedAtMS = rocket.IgnitedAtMS + settled.RocketLaunchAtMS = rocket.LaunchAtMS + settled.RocketResetAtMS = rocket.ResetAtMS + settled.RocketTop1UserID = rocket.Top1UserID + settled.RocketIgniterUserID = rocket.IgniterUserID + settled.RocketID = rocket.RocketID + settled.RocketConfigVersion = rocket.ConfigVersion + settled.RocketPendingLaunches = rocketPendingLaunchesToCommand(rocket.PendingLaunches) + } + return result, nil +} + +func rocketStateForNow(input *state.RocketState, cfg RoomRocketConfig, now time.Time, allocateRocketID bool) *state.RocketState { + now = now.UTC() + nowMS := now.UnixMilli() + resetAtMS := nextUTCResetMS(now) + level := int32(1) + if input != nil && input.CurrentLevel >= 1 && input.CurrentLevel <= roomRocketLevelCount { + level = input.CurrentLevel + } + if input == nil || input.ResetAtMS <= 0 || nowMS >= input.ResetAtMS { + return newRocketState(levelForUTCReset(), roomRocketLevelByNumber(cfg, levelForUTCReset()), resetAtMS, cfg.ConfigVersion, allocateRocketID) + } + + rocket := input.Clone() + levelConfig := roomRocketLevelByNumber(cfg, level) + rocket.CurrentLevel = level + rocket.FuelThreshold = levelConfig.FuelThreshold + rocket.ResetAtMS = input.ResetAtMS + if rocket.CurrentFuel < 0 { + rocket.CurrentFuel = 0 + } + if rocket.CurrentFuel > rocket.FuelThreshold { + rocket.CurrentFuel = rocket.FuelThreshold + } + rocket.PendingLaunches = validRocketPendingLaunches(rocket.PendingLaunches, rocket.ResetAtMS) + if rocket.Status == state.RocketStatusCompleted { + rocket.CurrentLevel = roomRocketLevelCount + rocket.FuelThreshold = roomRocketLevelByNumber(cfg, roomRocketLevelCount).FuelThreshold + rocket.CurrentFuel = rocket.FuelThreshold + rocket.RocketID = "" + } else { + rocket.Status = state.RocketStatusCharging + } + if rocket.RocketID == "" && allocateRocketID && rocket.Status != state.RocketStatusCompleted { + rocket.RocketID = idgen.New("room_rocket") + } + return rocket +} + +func validRocketPendingLaunches(input []state.RocketPendingLaunch, resetAtMS int64) []state.RocketPendingLaunch { + out := make([]state.RocketPendingLaunch, 0, len(input)) + seen := make(map[string]bool, len(input)) + for _, launch := range input { + if launch.RocketID == "" || launch.Level <= 0 || launch.LaunchAtMS <= 0 { + continue + } + if resetAtMS > 0 && launch.ResetAtMS > 0 && launch.ResetAtMS != resetAtMS { + continue + } + key := fmt.Sprintf("%s:%d", launch.RocketID, launch.Level) + if seen[key] { + continue + } + seen[key] = true + out = append(out, launch) + } + slices.SortFunc(out, func(left, right state.RocketPendingLaunch) int { + if left.LaunchAtMS == right.LaunchAtMS { + return int(left.Level - right.Level) + } + if left.LaunchAtMS < right.LaunchAtMS { + return -1 + } + return 1 + }) + return out +} + +func newRocketState(level int32, levelConfig RoomRocketLevelConfig, resetAtMS int64, configVersion int64, allocateRocketID bool) *state.RocketState { + rocketID := "" + if allocateRocketID { + rocketID = idgen.New("room_rocket") + } + return &state.RocketState{ + CurrentLevel: level, + FuelThreshold: levelConfig.FuelThreshold, + Status: state.RocketStatusCharging, + ResetAtMS: resetAtMS, + RocketID: rocketID, + ConfigVersion: configVersion, + } +} + +func levelForUTCReset() int32 { + return 1 +} + +func nextUTCResetMS(now time.Time) int64 { + utc := now.UTC() + next := time.Date(utc.Year(), utc.Month(), utc.Day()+1, 0, 0, 0, 0, time.UTC) + return next.UnixMilli() +} + +func roomRocketLevelByNumber(cfg RoomRocketConfig, level int32) RoomRocketLevelConfig { + for _, item := range cfg.Levels { + if item.Level == level { + return item + } + } + return defaultRoomRocketConfig(cfg.AppCode).Levels[0] +} + +func roomRocketFuel(cfg RoomRocketConfig, giftID string, giftTypeCode string, heatValue int64) int64 { + // 火箭燃料只读取 wallet-service 按真实扣费和贡献比例计算出的 heat_value,避免历史 GIFT_POINT 字段污染活动进度。 + base := heatValue + if base < 0 { + base = 0 + } + + for _, rule := range cfg.GiftFuelRules { + if rule.GiftID != "" && rule.GiftID == giftID { + return roomRocketFuelByRule(base, rule) + } + } + for _, rule := range cfg.GiftFuelRules { + if rule.GiftID == "" && rule.GiftTypeCode != "" && rule.GiftTypeCode == giftTypeCode { + return roomRocketFuelByRule(base, rule) + } + } + return base +} + +func roomRocketFuelByRule(base int64, rule GiftFuelRuleConfig) int64 { + if rule.Excluded { + return 0 + } + fuel := int64(0) + if rule.MultiplierPPM > 0 { + fuel += base * rule.MultiplierPPM / 1_000_000 + } + fuel += rule.FixedFuel + if fuel < 0 { + return 0 + } + return fuel +} + +func firstRankUserID(items []state.RankItem) int64 { + if len(items) == 0 { + return 0 + } + return items[0].UserID +} + +func minInt64(left int64, right int64) int64 { + if left < right { + return left + } + return right +} + +func rocketStateToRoomProto(input *state.RocketState) *roomv1.RoomRocketState { + if input == nil { + return nil + } + rewards := make([]*roomv1.RoomRocketRewardGrant, 0, len(input.LastRewards)) + for _, reward := range input.LastRewards { + rewards = append(rewards, &roomv1.RoomRocketRewardGrant{ + RewardRole: reward.RewardRole, + UserId: reward.UserID, + RewardItemId: reward.RewardItemID, + ResourceGroupId: reward.ResourceGroupID, + DisplayName: reward.DisplayName, + IconUrl: reward.IconURL, + GrantId: reward.GrantID, + Status: reward.Status, + }) + } + pending := make([]*roomv1.RoomRocketPendingLaunch, 0, len(input.PendingLaunches)) + for _, launch := range input.PendingLaunches { + pending = append(pending, &roomv1.RoomRocketPendingLaunch{ + RocketId: launch.RocketID, + Level: launch.Level, + FuelThreshold: launch.FuelThreshold, + IgnitedAtMs: launch.IgnitedAtMS, + LaunchAtMs: launch.LaunchAtMS, + ResetAtMs: launch.ResetAtMS, + Top1UserId: launch.Top1UserID, + IgniterUserId: launch.IgniterUserID, + ConfigVersion: launch.ConfigVersion, + CoverUrl: launch.CoverURL, + }) + } + return &roomv1.RoomRocketState{ + CurrentLevel: input.CurrentLevel, + CurrentFuel: input.CurrentFuel, + FuelThreshold: input.FuelThreshold, + Status: input.Status, + IgnitedAtMs: input.IgnitedAtMS, + LaunchAtMs: input.LaunchAtMS, + LaunchedAtMs: input.LaunchedAtMS, + ResetAtMs: input.ResetAtMS, + Top1UserId: input.Top1UserID, + IgniterUserId: input.IgniterUserID, + RocketId: input.RocketID, + ConfigVersion: input.ConfigVersion, + LastRewards: rewards, + PendingLaunches: pending, + } +} + +func rocketStateToEventRewards(input []state.RocketRewardGrant) []*roomeventsv1.RoomRocketRewardGrant { + out := make([]*roomeventsv1.RoomRocketRewardGrant, 0, len(input)) + for _, reward := range input { + out = append(out, &roomeventsv1.RoomRocketRewardGrant{ + RewardRole: reward.RewardRole, + UserId: reward.UserID, + RewardItemId: reward.RewardItemID, + ResourceGroupId: reward.ResourceGroupID, + DisplayName: reward.DisplayName, + IconUrl: reward.IconURL, + GrantId: reward.GrantID, + Status: reward.Status, + }) + } + return out +} + +// RunRoomRocketLaunchWorker 周期性扫描已装载房间,把到点的倒计时火箭走命令链路打开。 +func (s *Service) RunRoomRocketLaunchWorker(ctx context.Context, interval time.Duration) { + if interval <= 0 { + return + } + ticker := time.NewTicker(interval) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + _ = s.SweepRoomRocketLaunchings(ctx) + } + } +} + +// SweepRoomRocketLaunchings 只处理本节点仍持有 lease 的已装载 Room Cell。 +func (s *Service) SweepRoomRocketLaunchings(ctx context.Context) error { + now := s.clock.Now().UTC() + nowMS := now.UnixMilli() + for _, roomRef := range s.loadedRoomRefs() { + roomCtx := appcode.WithContext(ctx, roomRef.AppCode) + lease, owned, err := s.loadedRoomLease(roomCtx, roomRef, now) + if err != nil { + return err + } + if !owned { + continue + } + roomCell := s.loadCell(roomCtx, roomRef.RoomID) + if roomCell == nil { + continue + } + currentState, _, err := roomCell.Snapshot(roomCtx) + if err != nil { + return err + } + owned, err = s.verifyLoadedRoomLease(roomCtx, roomRef, lease, s.clock.Now()) + if err != nil { + return err + } + if !owned || currentState == nil || currentState.Rocket == nil { + continue + } + rocket := currentState.Rocket + if rocket.ResetAtMS > 0 && nowMS >= rocket.ResetAtMS { + // UTC 切日优先级高于延迟发射;跨日倒计时火箭不再结算,下一次查询或送礼会按新 UTC 日投影/持久化一级新进度。 + continue + } + for _, pending := range append([]state.RocketPendingLaunch(nil), rocket.PendingLaunches...) { + if pending.LaunchAtMS <= 0 || pending.LaunchAtMS > nowMS { + continue + } + actorID := pending.IgniterUserID + if actorID <= 0 { + actorID = roomRocketSystemActor(currentState) + } + cmd := command.LaunchRoomRocket{ + Base: command.Base{ + AppCode: roomRef.AppCode, + RequestID: idgen.New("req_room_rocket_launch"), + CommandID: roomRocketLaunchCommandID(pending.RocketID), + ActorID: actorID, + Room: roomRef.RoomID, + GatewayNodeID: s.nodeID, + SessionID: "room-rocket-launch", + SentAtMS: nowMS, + }, + RocketID: pending.RocketID, + Level: pending.Level, + } + if _, err := s.launchRoomRocket(roomCtx, cmd); err != nil { + return err + } + } + } + return nil +} + +func roomRocketLaunchCommandID(rocketID string) string { + if strings.TrimSpace(rocketID) == "" { + return idgen.New("cmd_room_rocket_launch") + } + return "cmd_room_rocket_launch_" + rocketID +} + +func roomRocketSystemActor(current *state.RoomState) int64 { + if current == nil { + return 0 + } + if current.OwnerUserID > 0 { + return current.OwnerUserID + } + if current.Rocket != nil && current.Rocket.IgniterUserID > 0 { + return current.Rocket.IgniterUserID + } + return 0 +} + +func (s *Service) launchRoomRocket(ctx context.Context, cmd command.LaunchRoomRocket) (*roomv1.RoomRocketState, error) { + result, err := s.mutateRoom(ctx, cmd, true, func(now time.Time, current *state.RoomState, _ *rank.LocalRank) (mutationResult, []outbox.Record, error) { + now = now.UTC() + nowMS := now.UnixMilli() + if current.Rocket == nil { + return mutationResult{snapshot: current.ToProto()}, nil, nil + } + pending, pendingIndex, ok := findRocketPendingLaunch(current.Rocket.PendingLaunches, cmd.RocketID, cmd.Level) + if !ok { + return mutationResult{snapshot: current.ToProto()}, nil, nil + } + if pending.ResetAtMS > 0 && nowMS >= pending.ResetAtMS { + // 手动或延迟到达的发射命令也不能越过 UTC 日界结算昨天的火箭。 + return mutationResult{snapshot: current.ToProto()}, nil, nil + } + if pending.LaunchAtMS <= 0 || pending.LaunchAtMS > nowMS { + return mutationResult{snapshot: current.ToProto()}, nil, nil + } + + cfg, err := s.roomRocketConfig(ctx) + if err != nil { + return mutationResult{}, nil, err + } + levelCfg := roomRocketLevelByNumber(cfg, pending.Level) + inRoomUserIDs := sortedRocketOnlineUserIDs(current.OnlineUsers) + rewards, err := s.settleRoomRocketRewards(ctx, now, current, pending, cfg, levelCfg, inRoomUserIDs) + if err != nil { + return mutationResult{}, nil, err + } + + pendingAfter := removeRocketPendingLaunch(current.Rocket.PendingLaunches, pendingIndex) + current.Rocket.PendingLaunches = pendingAfter + current.Rocket.LaunchedAtMS = nowMS + current.Rocket.LastRewards = rewards + + settledCommand := cmd + settledCommand.CurrentLevel = current.Rocket.CurrentLevel + settledCommand.CurrentFuel = current.Rocket.CurrentFuel + settledCommand.CurrentFuelThreshold = current.Rocket.FuelThreshold + settledCommand.CurrentStatus = current.Rocket.Status + settledCommand.CurrentRocketID = current.Rocket.RocketID + settledCommand.ConfigVersion = current.Rocket.ConfigVersion + settledCommand.ResetAtMS = current.Rocket.ResetAtMS + settledCommand.Top1UserID = pending.Top1UserID + settledCommand.IgniterUserID = pending.IgniterUserID + settledCommand.LaunchedAtMS = nowMS + settledCommand.InRoomUserIDs = inRoomUserIDs + settledCommand.Rewards = rocketRewardsToCommand(rewards) + settledCommand.PendingLaunches = rocketPendingLaunchesToCommand(pendingAfter) + commandPayload, err := command.Serialize(settledCommand) + if err != nil { + return mutationResult{}, nil, err + } + + current.Version++ + + openedEvent, err := outbox.Build(current.RoomID, "RoomRocketLaunched", current.Version, now, &roomeventsv1.RoomRocketLaunched{ + RocketId: pending.RocketID, + Level: pending.Level, + NextLevel: current.Rocket.CurrentLevel, + LaunchedAtMs: nowMS, + ResetAtMs: pending.ResetAtMS, + Top1UserId: pending.Top1UserID, + IgniterUserId: pending.IgniterUserID, + InRoomUserIds: inRoomUserIDs, + Rewards: rocketStateToEventRewards(rewards), + }) + if err != nil { + return mutationResult{}, nil, err + } + records := []outbox.Record{openedEvent} + if len(rewards) > 0 { + rewardEvent, err := outbox.Build(current.RoomID, "RoomRocketRewardGranted", current.Version, now, &roomeventsv1.RoomRocketRewardGranted{ + RocketId: pending.RocketID, + Level: pending.Level, + Rewards: rocketStateToEventRewards(rewards), + }) + if err != nil { + return mutationResult{}, nil, err + } + records = append(records, rewardEvent) + } + + return mutationResult{ + snapshot: current.ToProto(), + commandPayload: commandPayload, + }, records, nil + }) + if err != nil { + return nil, err + } + return result.snapshot.GetRocket(), nil +} + +func findRocketPendingLaunch(input []state.RocketPendingLaunch, rocketID string, level int32) (state.RocketPendingLaunch, int, bool) { + for index, launch := range input { + if launch.RocketID == rocketID && launch.Level == level { + return launch, index, true + } + } + return state.RocketPendingLaunch{}, -1, false +} + +func removeRocketPendingLaunch(input []state.RocketPendingLaunch, index int) []state.RocketPendingLaunch { + if index < 0 || index >= len(input) { + return append([]state.RocketPendingLaunch(nil), input...) + } + out := make([]state.RocketPendingLaunch, 0, len(input)-1) + out = append(out, input[:index]...) + out = append(out, input[index+1:]...) + return out +} + +func sortedRocketOnlineUserIDs(users map[int64]*state.RoomUserState) []int64 { + userIDs := make([]int64, 0, len(users)) + for userID := range users { + if userID > 0 { + userIDs = append(userIDs, userID) + } + } + slices.Sort(userIDs) + return userIDs +} + +func (s *Service) settleRoomRocketRewards(ctx context.Context, now time.Time, current *state.RoomState, launch state.RocketPendingLaunch, cfg RoomRocketConfig, levelCfg RoomRocketLevelConfig, inRoomUserIDs []int64) ([]state.RocketRewardGrant, error) { + if current == nil { + return nil, nil + } + rewards := make([]state.RocketRewardGrant, 0, len(inRoomUserIDs)+2) + claimed := make(map[int64]bool, len(inRoomUserIDs)+2) + addReward := func(role string, userID int64, pool []RoomRocketRewardItem) error { + if userID <= 0 { + return nil + } + if cfg.RewardStackPolicy == roomRocketRewardStackPriority && claimed[userID] { + return nil + } + item, ok := selectRoomRocketReward(launch.RocketID, role, userID, pool) + if !ok { + return nil + } + grantID, err := s.grantRoomRocketReward(ctx, now, current, launch.RocketID, role, userID, item) + if err != nil { + return err + } + rewards = append(rewards, state.RocketRewardGrant{ + RewardRole: role, + UserID: userID, + RewardItemID: item.RewardItemID, + ResourceGroupID: item.ResourceGroupID, + DisplayName: item.DisplayName, + IconURL: item.IconURL, + GrantID: grantID, + Status: roomRocketGrantStatus, + }) + claimed[userID] = true + return nil + } + + if cfg.RewardStackPolicy == roomRocketRewardStackPriority { + // 去重策略下先发特殊身份奖励,再发普通在房奖励,避免 top1/点火人被普通池占位。 + if err := addReward(roomRocketRewardIgniter, launch.IgniterUserID, levelCfg.IgniterRewards); err != nil { + return nil, err + } + if err := addReward(roomRocketRewardTop1, launch.Top1UserID, levelCfg.Top1Rewards); err != nil { + return nil, err + } + for _, userID := range inRoomUserIDs { + if err := addReward(roomRocketRewardInRoom, userID, levelCfg.InRoomRewards); err != nil { + return nil, err + } + } + return rewards, nil + } + + for _, userID := range inRoomUserIDs { + if err := addReward(roomRocketRewardInRoom, userID, levelCfg.InRoomRewards); err != nil { + return nil, err + } + } + if err := addReward(roomRocketRewardTop1, launch.Top1UserID, levelCfg.Top1Rewards); err != nil { + return nil, err + } + if err := addReward(roomRocketRewardIgniter, launch.IgniterUserID, levelCfg.IgniterRewards); err != nil { + return nil, err + } + return rewards, nil +} + +func (s *Service) grantRoomRocketReward(ctx context.Context, _ time.Time, current *state.RoomState, rocketID string, role string, userID int64, item RoomRocketRewardItem) (string, error) { + if s.wallet == nil { + return "", xerr.New(xerr.Unavailable, "wallet client is not configured") + } + operatorUserID := current.OwnerUserID + if operatorUserID <= 0 { + operatorUserID = userID + } + resp, err := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ + CommandId: roomRocketGrantCommandID(rocketID, role, userID, item.RewardItemID), + AppCode: appcode.FromContext(ctx), + TargetUserId: userID, + GroupId: item.ResourceGroupID, + Reason: fmt.Sprintf("room rocket %s reward", role), + OperatorUserId: operatorUserID, + GrantSource: roomRocketGrantSource, + }) + if err != nil { + return "", err + } + if resp == nil || resp.GetGrant() == nil { + return "", xerr.New(xerr.Unavailable, "wallet grant response is empty") + } + return resp.GetGrant().GetGrantId(), nil +} + +func selectRoomRocketReward(rocketID string, role string, userID int64, pool []RoomRocketRewardItem) (RoomRocketRewardItem, bool) { + total := int64(0) + for _, item := range pool { + if item.Weight > 0 && item.ResourceGroupID > 0 { + total += item.Weight + } + } + if total <= 0 { + return RoomRocketRewardItem{}, false + } + hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d", rocketID, role, userID))) + pick := int64(binary.BigEndian.Uint64(hash[:8]) % uint64(total)) + cursor := int64(0) + for _, item := range pool { + if item.Weight <= 0 || item.ResourceGroupID <= 0 { + continue + } + cursor += item.Weight + if pick < cursor { + return item, true + } + } + return pool[len(pool)-1], true +} + +func roomRocketGrantCommandID(rocketID string, role string, userID int64, rewardItemID string) string { + hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d|%s", rocketID, role, userID, rewardItemID))) + return fmt.Sprintf("cmd_room_rocket_grant_%x", hash[:8]) +} + +func rocketRewardsToCommand(input []state.RocketRewardGrant) []command.RocketRewardGrant { + out := make([]command.RocketRewardGrant, 0, len(input)) + for _, reward := range input { + out = append(out, command.RocketRewardGrant{ + RewardRole: reward.RewardRole, + UserID: reward.UserID, + RewardItemID: reward.RewardItemID, + ResourceGroupID: reward.ResourceGroupID, + DisplayName: reward.DisplayName, + IconURL: reward.IconURL, + GrantID: reward.GrantID, + Status: reward.Status, + }) + } + return out +} + +func rocketPendingLaunchesToCommand(input []state.RocketPendingLaunch) []command.RocketPendingLaunch { + out := make([]command.RocketPendingLaunch, 0, len(input)) + for _, launch := range input { + out = append(out, command.RocketPendingLaunch{ + RocketID: launch.RocketID, + Level: launch.Level, + FuelThreshold: launch.FuelThreshold, + IgnitedAtMS: launch.IgnitedAtMS, + LaunchAtMS: launch.LaunchAtMS, + ResetAtMS: launch.ResetAtMS, + Top1UserID: launch.Top1UserID, + IgniterUserID: launch.IgniterUserID, + ConfigVersion: launch.ConfigVersion, + CoverURL: launch.CoverURL, + }) + } + return out +} diff --git a/services/room-service/internal/room/service/room_rocket_mq.go b/services/room-service/internal/room/service/room_rocket_mq.go new file mode 100644 index 00000000..34ed8bb7 --- /dev/null +++ b/services/room-service/internal/room/service/room_rocket_mq.go @@ -0,0 +1,112 @@ +package service + +import ( + "context" + "fmt" + + "google.golang.org/protobuf/proto" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/roommq" + "hyapp/pkg/xerr" + "hyapp/services/room-service/internal/integration" + "hyapp/services/room-service/internal/room/command" +) + +// scheduleRoomRocketLaunchFromEnvelope derives the delayed wakeup from the +// already committed ignited outbox. Scheduling after outbox claim keeps +// SendGift free of external MQ side effects before MySQL commit. +func (s *Service) scheduleRoomRocketLaunchFromEnvelope(ctx context.Context, envelope *roomeventsv1.EventEnvelope) error { + if s.roomRocketLaunchScheduler == nil || envelope == nil || envelope.GetEventType() != "RoomRocketIgnited" { + return nil + } + var event roomeventsv1.RoomRocketIgnited + if err := proto.Unmarshal(envelope.GetBody(), &event); err != nil { + return err + } + if event.GetRocketId() == "" || event.GetLevel() <= 0 || event.GetLaunchAtMs() <= 0 { + return fmt.Errorf("room rocket ignited event is incomplete: event_id=%s", envelope.GetEventId()) + } + return s.roomRocketLaunchScheduler.ScheduleRoomRocketLaunch(ctx, integration.RoomRocketLaunchSchedule{ + AppCode: appcode.Normalize(envelope.GetAppCode()), + RoomID: envelope.GetRoomId(), + RocketID: event.GetRocketId(), + Level: event.GetLevel(), + LaunchAtMS: event.GetLaunchAtMs(), + ResetAtMS: event.GetResetAtMs(), + CommandID: roomRocketLaunchCommandID(event.GetRocketId()), + }) +} + +// HandleRoomRocketLaunchDue handles a RocketMQ delayed wakeup. It pre-checks +// due-ness before writing a command log, because an early-delivered delay +// message must not poison the deterministic open command_id as a no-op. +func (s *Service) HandleRoomRocketLaunchDue(ctx context.Context, due roommq.RoomRocketLaunchDueMessage) error { + ctx = appcode.WithContext(ctx, due.AppCode) + if due.RoomID == "" || due.RocketID == "" || due.Level <= 0 || due.LaunchAtMS <= 0 { + return xerr.New(xerr.InvalidArgument, "room rocket launch due message is incomplete") + } + + roomCell, lease, err := s.ensureCell(ctx, due.RoomID) + if err != nil { + return err + } + currentState, _, err := roomCell.Snapshot(ctx) + if err != nil { + return err + } + owned, err := s.directory.VerifyOwner(ctx, runtimeRoomKeyFromContext(ctx, due.RoomID), s.nodeID, lease.LeaseToken, s.clock.Now()) + if err != nil { + return err + } + if !owned { + return xerr.New(xerr.Conflict, "room rocket launch lease moved") + } + + now := s.clock.Now().UTC() + nowMS := now.UnixMilli() + if currentState == nil || currentState.Rocket == nil { + return nil + } + rocket := currentState.Rocket + pending, _, ok := findRocketPendingLaunch(rocket.PendingLaunches, due.RocketID, due.Level) + if !ok || pending.LaunchAtMS != due.LaunchAtMS { + // Stale delayed messages are expected after retries or if the room reset/launched by another path. + return nil + } + if pending.ResetAtMS > 0 && nowMS >= pending.ResetAtMS { + // UTC day reset wins over yesterday's delayed wakeup. + return nil + } + if pending.LaunchAtMS > nowMS { + return xerr.New(xerr.Unavailable, "room rocket launch wakeup arrived before launch_at_ms") + } + + actorUserID := currentState.OwnerUserID + if actorUserID <= 0 { + actorUserID = pending.IgniterUserID + } + if actorUserID <= 0 { + return xerr.New(xerr.InvalidArgument, "room rocket launch actor is missing") + } + commandID := due.CommandID + if commandID == "" { + commandID = roomRocketLaunchCommandID(due.RocketID) + } + _, err = s.launchRoomRocket(ctx, command.LaunchRoomRocket{ + Base: command.Base{ + AppCode: appcode.FromContext(ctx), + RequestID: idgen.New("req_room_rocket_launch_mq"), + CommandID: commandID, + ActorID: actorUserID, + Room: due.RoomID, + GatewayNodeID: s.nodeID, + SessionID: "room-rocket-launch-mq", + SentAtMS: nowMS, + }, + RocketID: due.RocketID, + Level: due.Level, + }) + return err +} diff --git a/services/room-service/internal/room/service/room_treasure_test.go b/services/room-service/internal/room/service/room_rocket_test.go similarity index 53% rename from services/room-service/internal/room/service/room_treasure_test.go rename to services/room-service/internal/room/service/room_rocket_test.go index a11c3043..6ed40ebc 100644 --- a/services/room-service/internal/room/service/room_treasure_test.go +++ b/services/room-service/internal/room/service/room_rocket_test.go @@ -20,15 +20,15 @@ import ( "hyapp/services/room-service/internal/testutil/mysqltest" ) -type fixedRoomTreasureClock struct { +type fixedRoomRocketClock struct { now time.Time } -func (c *fixedRoomTreasureClock) Now() time.Time { +func (c *fixedRoomRocketClock) Now() time.Time { return c.now.UTC() } -type treasureTestWallet struct { +type rocketTestWallet struct { debits []*walletv1.DebitGiftResponse grants []*walletv1.GrantResourceGroupRequest lastDebit *walletv1.DebitGiftRequest @@ -36,7 +36,7 @@ type treasureTestWallet struct { lastBatch *walletv1.BatchDebitGiftRequest } -func (w *treasureTestWallet) DebitGift(_ context.Context, req *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) { +func (w *rocketTestWallet) DebitGift(_ context.Context, req *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) { w.lastDebit = req w.debitRequests = append(w.debitRequests, req) if len(w.debits) == 0 { @@ -47,7 +47,7 @@ func (w *treasureTestWallet) DebitGift(_ context.Context, req *walletv1.DebitGif return next, nil } -func (w *treasureTestWallet) BatchDebitGift(_ context.Context, req *walletv1.BatchDebitGiftRequest) (*walletv1.BatchDebitGiftResponse, error) { +func (w *rocketTestWallet) BatchDebitGift(_ context.Context, req *walletv1.BatchDebitGiftRequest) (*walletv1.BatchDebitGiftResponse, error) { w.lastBatch = req receipts := make([]*walletv1.BatchDebitGiftReceipt, 0, len(req.GetTargets())) aggregate := &walletv1.DebitGiftResponse{} @@ -94,20 +94,20 @@ func joinReceiptIDs(left string, right string) string { func TestSendGiftBatchDebitsMultipleTargets(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-202", CoinSpent: 10, ChargeAmount: 10, GiftPointAdded: 5, HeatValue: 11, GiftTypeCode: "normal", PriceVersion: "v1", BalanceAfter: 90}, {BillingReceiptId: "receipt-303", CoinSpent: 20, ChargeAmount: 20, GiftPointAdded: 7, HeatValue: 19, GiftTypeCode: "normal", PriceVersion: "v1", BalanceAfter: 70}, }} - svc := newTreasureTestService(t, repository, wallet, now) + svc := newRocketTestService(t, repository, wallet, now) roomID := "room-gift-multi-target" ownerID := int64(101) firstTargetID := int64(202) secondTargetID := int64(303) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, firstTargetID) - joinTreasureRoom(t, ctx, svc, roomID, secondTargetID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9001) + joinRocketRoom(t, ctx, svc, roomID, firstTargetID) + joinRocketRoom(t, ctx, svc, roomID, secondTargetID) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ Meta: &roomv1.RequestMeta{ @@ -155,7 +155,7 @@ func TestSendGiftBatchDebitsMultipleTargets(t *testing.T) { } } -func (w *treasureTestWallet) GrantResourceGroup(_ context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) { +func (w *rocketTestWallet) GrantResourceGroup(_ context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) { w.grants = append(w.grants, req) return &walletv1.ResourceGrantResponse{ Grant: &walletv1.ResourceGrant{ @@ -166,34 +166,34 @@ func (w *treasureTestWallet) GrantResourceGroup(_ context.Context, req *walletv1 }, nil } -type treasureOpenScheduleRecorder struct { - schedules []integration.RoomTreasureOpenSchedule +type rocketLaunchScheduleRecorder struct { + schedules []integration.RoomRocketLaunchSchedule } -func (r *treasureOpenScheduleRecorder) ScheduleRoomTreasureOpen(_ context.Context, schedule integration.RoomTreasureOpenSchedule) error { +func (r *rocketLaunchScheduleRecorder) ScheduleRoomRocketLaunch(_ context.Context, schedule integration.RoomRocketLaunchSchedule) error { r.schedules = append(r.schedules, schedule) return nil } -func TestRoomTreasureGiftOverflowAndCountdownInvalidEnergy(t *testing.T) { +func TestRoomRocketGiftOverflowAndIgnitedInvalidEnergy(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-fill", GiftPointAdded: 150, HeatValue: 150, GiftTypeCode: "normal"}, - {BillingReceiptId: "receipt-countdown", GiftPointAdded: 200, HeatValue: 200, GiftTypeCode: "normal"}, + {BillingReceiptId: "receipt-ignited", GiftPointAdded: 200, HeatValue: 200, GiftTypeCode: "normal"}, }} - svc := newTreasureTestService(t, repository, wallet, now) - writeTreasureConfig(t, ctx, repository, treasureConfigForTest(100, 1_000)) + svc := newRocketTestService(t, repository, wallet, now) + writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-treasure-flow" + roomID := "room-rocket-flow" ownerID := int64(101) viewerID := int64(202) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9001) - joinTreasureRoom(t, ctx, svc, roomID, viewerID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9001) + joinRocketRoom(t, ctx, svc, roomID, viewerID) fillResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, ownerID, "fill"), + Meta: rocketMeta(roomID, ownerID, "fill"), TargetType: "user", TargetUserId: viewerID, GiftId: "gift-overflow", @@ -202,68 +202,68 @@ func TestRoomTreasureGiftOverflowAndCountdownInvalidEnergy(t *testing.T) { if err != nil { t.Fatalf("send fill gift failed: %v", err) } - treasure := fillResp.GetTreasure() - if treasure.GetCurrentLevel() != 1 || treasure.GetCurrentProgress() != 100 || treasure.GetStatus() != state.TreasureStatusCountdown { - t.Fatalf("fill gift must cap level 1 progress and enter countdown: %+v", treasure) + rocket := fillResp.GetRocket() + if rocket.GetCurrentLevel() != 1 || rocket.GetCurrentFuel() != 100 || rocket.GetStatus() != state.RocketStatusIgnited { + t.Fatalf("fill gift must cap level 1 progress and enter ignited: %+v", rocket) } - if treasure.GetOpenAtMs() != now.Now().Add(time.Second).UnixMilli() || treasure.GetResetAtMs() != time.Date(2026, 5, 21, 0, 0, 0, 0, time.UTC).UnixMilli() { - t.Fatalf("treasure timers must use UTC business time: %+v", treasure) + if rocket.GetLaunchAtMs() != now.Now().Add(time.Second).UnixMilli() || rocket.GetResetAtMs() != time.Date(2026, 5, 21, 0, 0, 0, 0, time.UTC).UnixMilli() { + t.Fatalf("rocket timers must use UTC business time: %+v", rocket) } - if treasure.GetTop1UserId() != ownerID || treasure.GetIgniterUserId() != ownerID { - t.Fatalf("top1 and igniter must lock at countdown start: %+v", treasure) + if rocket.GetTop1UserId() != ownerID || rocket.GetIgniterUserId() != ownerID { + t.Fatalf("top1 and igniter must lock at ignited start: %+v", rocket) } - progressEvents := treasureProgressEvents(t, ctx, repository) - if len(progressEvents) != 1 || progressEvents[0].GetAddedEnergy() != 150 || progressEvents[0].GetEffectiveAddedEnergy() != 100 || progressEvents[0].GetOverflowEnergy() != 50 { + progressEvents := rocketProgressEvents(t, ctx, repository) + if len(progressEvents) != 1 || progressEvents[0].GetAddedFuel() != 150 || progressEvents[0].GetEffectiveAddedFuel() != 100 || progressEvents[0].GetOverflowFuel() != 50 { t.Fatalf("progress event must expose effective energy and discarded overflow: %+v", progressEvents) } - if got := countTreasureCountdownEvents(t, ctx, repository); got != 1 { - t.Fatalf("fill gift must emit one countdown event, got %d", got) + if got := countRocketIgnitedEvents(t, ctx, repository); got != 1 { + t.Fatalf("fill gift must emit one ignited event, got %d", got) } countdownResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, viewerID, "countdown"), + Meta: rocketMeta(roomID, viewerID, "ignited"), TargetType: "user", TargetUserId: ownerID, - GiftId: "gift-during-countdown", + GiftId: "gift-during-ignited", GiftCount: 1, }) if err != nil { - t.Fatalf("send countdown gift failed: %v", err) + t.Fatalf("send ignited gift failed: %v", err) } - if countdownResp.GetTreasure().GetCurrentProgress() != 100 || countdownResp.GetTreasure().GetStatus() != state.TreasureStatusCountdown { - t.Fatalf("countdown gift must not change treasure progress: %+v", countdownResp.GetTreasure()) + if countdownResp.GetRocket().GetCurrentFuel() != 100 || countdownResp.GetRocket().GetStatus() != state.RocketStatusIgnited { + t.Fatalf("ignited gift must not change rocket progress: %+v", countdownResp.GetRocket()) } - if got := len(treasureProgressEvents(t, ctx, repository)); got != 1 { - t.Fatalf("countdown invalid energy must not emit a second progress event, got %d", got) + if got := len(rocketProgressEvents(t, ctx, repository)); got != 1 { + t.Fatalf("ignited invalid energy must not emit a second progress event, got %d", got) } - if got := countTreasureCountdownEvents(t, ctx, repository); got != 1 { - t.Fatalf("countdown invalid energy must not emit another countdown event, got %d", got) + if got := countRocketIgnitedEvents(t, ctx, repository); got != 1 { + t.Fatalf("ignited invalid energy must not emit another ignited event, got %d", got) } } -func TestRoomTreasureCountdownOutboxSchedulesDelayedOpen(t *testing.T) { +func TestRoomRocketIgnitedOutboxSchedulesDelayedOpen(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-fill", GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "normal"}, }} - scheduler := &treasureOpenScheduleRecorder{} - svc := newTreasureTestServiceWithScheduler(t, repository, wallet, now, scheduler) - writeTreasureConfig(t, ctx, repository, treasureConfigForTest(100, 1_000)) + scheduler := &rocketLaunchScheduleRecorder{} + svc := newRocketTestServiceWithScheduler(t, repository, wallet, now, scheduler) + writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-treasure-schedule" + roomID := "room-rocket-schedule" ownerID := int64(801) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9008) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9008) if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, ownerID, "fill"), + Meta: rocketMeta(roomID, ownerID, "fill"), TargetType: "user", TargetUserId: ownerID, GiftId: "gift-fill", GiftCount: 1, }); err != nil { - t.Fatalf("fill treasure failed: %v", err) + t.Fatalf("fill rocket failed: %v", err) } if err := svc.ProcessPendingOutbox(ctx, roomservice.OutboxWorkerOptions{PublishTimeout: time.Second, BatchSize: 100}); err != nil { @@ -273,53 +273,53 @@ func TestRoomTreasureCountdownOutboxSchedulesDelayedOpen(t *testing.T) { t.Fatalf("scheduled opens=%d, want 1: %+v", len(scheduler.schedules), scheduler.schedules) } scheduled := scheduler.schedules[0] - if scheduled.RoomID != roomID || scheduled.Level != 1 || scheduled.OpenAtMS != now.Now().Add(time.Second).UnixMilli() || scheduled.CommandID == "" { + if scheduled.RoomID != roomID || scheduled.Level != 1 || scheduled.LaunchAtMS != now.Now().Add(time.Second).UnixMilli() || scheduled.CommandID == "" { t.Fatalf("unexpected delayed open schedule: %+v", scheduled) } } -func TestRoomTreasureOpenDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { +func TestRoomRocketLaunchDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-ignite", GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "normal"}, }} - svc := newTreasureTestService(t, repository, wallet, now) - writeTreasureConfig(t, ctx, repository, treasureConfigForTest(100, 1_000)) + svc := newRocketTestService(t, repository, wallet, now) + writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-treasure-mq-open" + roomID := "room-rocket-mq-open" ownerID := int64(901) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9009) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9009) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, ownerID, "ignite"), + Meta: rocketMeta(roomID, ownerID, "ignite"), TargetType: "user", TargetUserId: ownerID, GiftId: "gift-ignite", GiftCount: 1, }) if err != nil { - t.Fatalf("ignite treasure failed: %v", err) + t.Fatalf("ignite rocket failed: %v", err) } - treasure := resp.GetTreasure() - due := roommq.RoomTreasureOpenDueMessage{ - MessageType: roommq.MessageTypeRoomTreasureOpenDue, + rocket := resp.GetRocket() + due := roommq.RoomRocketLaunchDueMessage{ + MessageType: roommq.MessageTypeRoomRocketLaunchDue, AppCode: appcode.Default, RoomID: roomID, - BoxID: treasure.GetBoxId(), - Level: treasure.GetCurrentLevel(), - OpenAtMS: treasure.GetOpenAtMs(), - CommandID: "cmd_room_treasure_open_" + treasure.GetBoxId(), + RocketID: rocket.GetRocketId(), + Level: rocket.GetCurrentLevel(), + LaunchAtMS: rocket.GetLaunchAtMs(), + CommandID: "cmd_room_rocket_launch_" + rocket.GetRocketId(), } - if err := svc.HandleRoomTreasureOpenDue(ctx, due); err == nil { + if err := svc.HandleRoomRocketLaunchDue(ctx, due); err == nil { t.Fatal("early delayed message should ask MQ to retry") } now.now = now.now.Add(time.Second) - if err := svc.HandleRoomTreasureOpenDue(ctx, due); err != nil { - t.Fatalf("due delayed message should open treasure after retry: %v", err) + if err := svc.HandleRoomRocketLaunchDue(ctx, due); err != nil { + t.Fatalf("due delayed message should open rocket after retry: %v", err) } - info, err := svc.GetRoomTreasure(ctx, &roomv1.GetRoomTreasureRequest{ + info, err := svc.GetRoomRocket(ctx, &roomv1.GetRoomRocketRequest{ RoomId: roomID, ViewerUserId: ownerID, Meta: &roomv1.RequestMeta{ @@ -328,99 +328,99 @@ func TestRoomTreasureOpenDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { }, }) if err != nil { - t.Fatalf("get treasure failed: %v", err) + t.Fatalf("get rocket failed: %v", err) } - if info.GetTreasure().GetState().GetStatus() != state.TreasureStatusIdle || info.GetTreasure().GetState().GetCurrentLevel() != 2 { - t.Fatalf("treasure should open once after early retry: %+v", info.GetTreasure().GetState()) + if info.GetRocket().GetState().GetStatus() != state.RocketStatusCharging || info.GetRocket().GetState().GetCurrentLevel() != 2 { + t.Fatalf("rocket should open once after early retry: %+v", info.GetRocket().GetState()) } if len(wallet.grants) == 0 { t.Fatal("open should grant configured rewards after retry") } } -func TestRoomTreasureOpenGrantsLockedTop1AndIgniterAfterLeave(t *testing.T) { +func TestRoomRocketLaunchGrantsLockedTop1AndIgniterAfterLeave(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-ignite", GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "normal"}, }} - svc := newTreasureTestService(t, repository, wallet, now) - writeTreasureConfig(t, ctx, repository, treasureConfigForTest(100, 1_000)) + svc := newRocketTestService(t, repository, wallet, now) + writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-treasure-open" + roomID := "room-rocket-open" ownerID := int64(301) igniterID := int64(302) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9002) - joinTreasureRoom(t, ctx, svc, roomID, igniterID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9002) + joinRocketRoom(t, ctx, svc, roomID, igniterID) if _, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, igniterID, "ignite"), + Meta: rocketMeta(roomID, igniterID, "ignite"), TargetType: "user", TargetUserId: ownerID, GiftId: "gift-ignite", GiftCount: 1, }); err != nil { - t.Fatalf("ignite treasure failed: %v", err) + t.Fatalf("ignite rocket failed: %v", err) } - if _, err := svc.LeaveRoom(ctx, &roomv1.LeaveRoomRequest{Meta: treasureMeta(roomID, igniterID, "leave")}); err != nil { + if _, err := svc.LeaveRoom(ctx, &roomv1.LeaveRoomRequest{Meta: rocketMeta(roomID, igniterID, "leave")}); err != nil { t.Fatalf("igniter leave room failed: %v", err) } now.now = now.now.Add(1100 * time.Millisecond) - if err := svc.SweepRoomTreasureOpenings(ctx); err != nil { - t.Fatalf("sweep room treasure openings failed: %v", err) + if err := svc.SweepRoomRocketLaunchings(ctx); err != nil { + t.Fatalf("sweep room rocket openings failed: %v", err) } - if !hasTreasureGrant(wallet.grants, igniterID, 2001) || !hasTreasureGrant(wallet.grants, igniterID, 3001) { + if !hasRocketGrant(wallet.grants, igniterID, 2001) || !hasRocketGrant(wallet.grants, igniterID, 3001) { t.Fatalf("left top1/igniter must still receive locked rewards: %+v", wallet.grants) } - if hasTreasureGrant(wallet.grants, igniterID, 1001) { + if hasRocketGrant(wallet.grants, igniterID, 1001) { t.Fatalf("left igniter must not receive in-room reward: %+v", wallet.grants) } - if !hasTreasureGrant(wallet.grants, ownerID, 1001) { + if !hasRocketGrant(wallet.grants, ownerID, 1001) { t.Fatalf("remaining in-room owner must receive in-room reward: %+v", wallet.grants) } - info, err := svc.GetRoomTreasure(ctx, &roomv1.GetRoomTreasureRequest{ + info, err := svc.GetRoomRocket(ctx, &roomv1.GetRoomRocketRequest{ Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID}, RoomId: roomID, ViewerUserId: ownerID, }) if err != nil { - t.Fatalf("get treasure after open failed: %v", err) + t.Fatalf("get rocket after open failed: %v", err) } - stateView := info.GetTreasure().GetState() - if stateView.GetCurrentLevel() != 2 || stateView.GetStatus() != state.TreasureStatusIdle { - t.Fatalf("opened treasure must advance to next idle level: %+v", stateView) + stateView := info.GetRocket().GetState() + if stateView.GetCurrentLevel() != 2 || stateView.GetStatus() != state.RocketStatusCharging { + t.Fatalf("opened rocket must advance to next idle level: %+v", stateView) } if len(stateView.GetLastRewards()) != 3 { - t.Fatalf("opened treasure must retain in-room, top1 and igniter grants for client display: %+v", stateView.GetLastRewards()) + t.Fatalf("opened rocket must retain in-room, top1 and igniter grants for client display: %+v", stateView.GetLastRewards()) } - if got := treasureRewardUserIDs(stateView.GetLastRewards()); !slices.Equal(got, []int64{301, 302, 302}) { + if got := rocketRewardUserIDs(stateView.GetLastRewards()); !slices.Equal(got, []int64{301, 302, 302}) { t.Fatalf("reward users mismatch: got %+v rewards=%+v", got, stateView.GetLastRewards()) } } -func TestRoomTreasureUTCResetCancelsCrossDayCountdown(t *testing.T) { +func TestRoomRocketUTCResetCancelsCrossDayIgnited(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) - now := &fixedRoomTreasureClock{now: time.Date(2026, 5, 20, 23, 59, 59, 0, time.UTC)} - wallet := &treasureTestWallet{debits: []*walletv1.DebitGiftResponse{ + now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 23, 59, 59, 0, time.UTC)} + wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ {BillingReceiptId: "receipt-cross-day", GiftPointAdded: 100, HeatValue: 100, GiftTypeCode: "normal"}, {BillingReceiptId: "receipt-new-day", GiftPointAdded: 10, HeatValue: 10, GiftTypeCode: "normal"}, }} - svc := newTreasureTestService(t, repository, wallet, now) - writeTreasureConfig(t, ctx, repository, treasureConfigForTest(100, 2_000)) + svc := newRocketTestService(t, repository, wallet, now) + writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 2_000)) - roomID := "room-treasure-reset" + roomID := "room-rocket-reset" ownerID := int64(401) viewerID := int64(402) - createTreasureRoom(t, ctx, svc, roomID, ownerID, 9003) - joinTreasureRoom(t, ctx, svc, roomID, viewerID) + createRocketRoom(t, ctx, svc, roomID, ownerID, 9003) + joinRocketRoom(t, ctx, svc, roomID, viewerID) fillResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, viewerID, "cross-day-fill"), + Meta: rocketMeta(roomID, viewerID, "cross-day-fill"), TargetType: "user", TargetUserId: ownerID, GiftId: "gift-cross-day", @@ -429,32 +429,32 @@ func TestRoomTreasureUTCResetCancelsCrossDayCountdown(t *testing.T) { if err != nil { t.Fatalf("send cross-day gift failed: %v", err) } - if fillResp.GetTreasure().GetStatus() != state.TreasureStatusCountdown || fillResp.GetTreasure().GetOpenAtMs() <= fillResp.GetTreasure().GetResetAtMs() { - t.Fatalf("fixture must create a countdown whose open time crosses UTC reset: %+v", fillResp.GetTreasure()) + if fillResp.GetRocket().GetStatus() != state.RocketStatusIgnited || fillResp.GetRocket().GetLaunchAtMs() <= fillResp.GetRocket().GetResetAtMs() { + t.Fatalf("fixture must create a ignited whose open time crosses UTC reset: %+v", fillResp.GetRocket()) } now.now = time.Date(2026, 5, 21, 0, 0, 2, 0, time.UTC) - if err := svc.SweepRoomTreasureOpenings(ctx); err != nil { - t.Fatalf("sweep cross-day treasure failed: %v", err) + if err := svc.SweepRoomRocketLaunchings(ctx); err != nil { + t.Fatalf("sweep cross-day rocket failed: %v", err) } if len(wallet.grants) != 0 { - t.Fatalf("cross-day countdown must be canceled by UTC reset, grants=%+v", wallet.grants) + t.Fatalf("cross-day ignited must be canceled by UTC reset, grants=%+v", wallet.grants) } - info, err := svc.GetRoomTreasure(ctx, &roomv1.GetRoomTreasureRequest{ + info, err := svc.GetRoomRocket(ctx, &roomv1.GetRoomRocketRequest{ Meta: &roomv1.RequestMeta{AppCode: appcode.Default, RoomId: roomID}, RoomId: roomID, ViewerUserId: ownerID, }) if err != nil { - t.Fatalf("get treasure after UTC reset failed: %v", err) + t.Fatalf("get rocket after UTC reset failed: %v", err) } - if stateView := info.GetTreasure().GetState(); stateView.GetCurrentLevel() != 1 || stateView.GetCurrentProgress() != 0 || stateView.GetStatus() != state.TreasureStatusIdle { - t.Fatalf("query view must reset stale countdown at UTC boundary: %+v", stateView) + if stateView := info.GetRocket().GetState(); stateView.GetCurrentLevel() != 1 || stateView.GetCurrentFuel() != 0 || stateView.GetStatus() != state.RocketStatusCharging { + t.Fatalf("query view must reset stale ignited at UTC boundary: %+v", stateView) } nextResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: treasureMeta(roomID, ownerID, "new-day-gift"), + Meta: rocketMeta(roomID, ownerID, "new-day-gift"), TargetType: "user", TargetUserId: viewerID, GiftId: "gift-new-day", @@ -463,54 +463,54 @@ func TestRoomTreasureUTCResetCancelsCrossDayCountdown(t *testing.T) { if err != nil { t.Fatalf("send new-day gift failed: %v", err) } - if nextResp.GetTreasure().GetCurrentLevel() != 1 || nextResp.GetTreasure().GetCurrentProgress() != 10 || nextResp.GetTreasure().GetStatus() != state.TreasureStatusIdle { - t.Fatalf("first new-day gift must start a fresh level 1 treasure: %+v", nextResp.GetTreasure()) + if nextResp.GetRocket().GetCurrentLevel() != 1 || nextResp.GetRocket().GetCurrentFuel() != 10 || nextResp.GetRocket().GetStatus() != state.RocketStatusCharging { + t.Fatalf("first new-day gift must start a fresh level 1 rocket: %+v", nextResp.GetRocket()) } } -func newTreasureTestService(t *testing.T, repository *mysqltest.Repository, wallet *treasureTestWallet, clock *fixedRoomTreasureClock) *roomservice.Service { +func newRocketTestService(t *testing.T, repository *mysqltest.Repository, wallet *rocketTestWallet, clock *fixedRoomRocketClock) *roomservice.Service { t.Helper() - return newTreasureTestServiceWithScheduler(t, repository, wallet, clock, nil) + return newRocketTestServiceWithScheduler(t, repository, wallet, clock, nil) } -func newTreasureTestServiceWithScheduler(t *testing.T, repository *mysqltest.Repository, wallet *treasureTestWallet, clock *fixedRoomTreasureClock, scheduler integration.RoomTreasureOpenScheduler) *roomservice.Service { +func newRocketTestServiceWithScheduler(t *testing.T, repository *mysqltest.Repository, wallet *rocketTestWallet, clock *fixedRoomRocketClock, scheduler integration.RoomRocketLaunchScheduler) *roomservice.Service { t.Helper() return roomservice.New(roomservice.Config{ - NodeID: "node-treasure-test", + NodeID: "node-rocket-test", LeaseTTL: 10 * time.Second, RankLimit: 20, SnapshotEveryN: 1, Clock: clock, - RoomTreasureOpenScheduler: scheduler, + RoomRocketLaunchScheduler: scheduler, }, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) } -func treasureConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomTreasureConfig { - levels := make([]roomservice.RoomTreasureLevelConfig, 0, 7) +func rocketConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomRocketConfig { + levels := make([]roomservice.RoomRocketLevelConfig, 0, 7) for level := int32(1); level <= 7; level++ { - levels = append(levels, roomservice.RoomTreasureLevelConfig{ - Level: level, - EnergyThreshold: threshold + int64(level-1)*100, - CoverURL: fmt.Sprintf("https://example.test/treasure/%d-cover.png", level), - AnimationURL: fmt.Sprintf("https://example.test/treasure/%d-idle.webp", level), - OpeningAnimationURL: fmt.Sprintf("https://example.test/treasure/%d-opening.webp", level), - OpenedImageURL: fmt.Sprintf("https://example.test/treasure/%d-open.png", level), - InRoomRewards: []roomservice.RoomTreasureRewardItem{{ + levels = append(levels, roomservice.RoomRocketLevelConfig{ + Level: level, + FuelThreshold: threshold + int64(level-1)*100, + CoverURL: fmt.Sprintf("https://example.test/rocket/%d-cover.png", level), + AnimationURL: fmt.Sprintf("https://example.test/rocket/%d-idle.webp", level), + LaunchAnimationURL: fmt.Sprintf("https://example.test/rocket/%d-opening.webp", level), + LaunchedImageURL: fmt.Sprintf("https://example.test/rocket/%d-open.png", level), + InRoomRewards: []roomservice.RoomRocketRewardItem{{ RewardItemID: fmt.Sprintf("level-%d-in-room", level), ResourceGroupID: 1000 + int64(level), Weight: 1, DisplayName: "In Room", IconURL: "https://example.test/reward/in-room.png", }}, - Top1Rewards: []roomservice.RoomTreasureRewardItem{{ + Top1Rewards: []roomservice.RoomRocketRewardItem{{ RewardItemID: fmt.Sprintf("level-%d-top1", level), ResourceGroupID: 2000 + int64(level), Weight: 1, DisplayName: "Top 1", IconURL: "https://example.test/reward/top1.png", }}, - IgniterRewards: []roomservice.RoomTreasureRewardItem{{ + IgniterRewards: []roomservice.RoomRocketRewardItem{{ RewardItemID: fmt.Sprintf("level-%d-igniter", level), ResourceGroupID: 3000 + int64(level), Weight: 1, @@ -519,12 +519,12 @@ func treasureConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomT }}, }) } - return roomservice.RoomTreasureConfig{ + return roomservice.RoomRocketConfig{ AppCode: appcode.Default, Enabled: true, ConfigVersion: 1, - EnergySource: "gift_point_added", - OpenDelayMS: openDelayMS, + FuelSource: "gift_point_added", + LaunchDelayMS: openDelayMS, BroadcastEnabled: true, BroadcastScope: "region", RewardStackPolicy: "allow_stack", @@ -532,15 +532,15 @@ func treasureConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomT } } -func writeTreasureConfig(t *testing.T, ctx context.Context, repository *mysqltest.Repository, config roomservice.RoomTreasureConfig) { +func writeRocketConfig(t *testing.T, ctx context.Context, repository *mysqltest.Repository, config roomservice.RoomRocketConfig) { t.Helper() - if err := repository.UpsertRoomTreasureConfig(ctx, config); err != nil { - t.Fatalf("upsert treasure config failed: %v", err) + if err := repository.UpsertRoomRocketConfig(ctx, config); err != nil { + t.Fatalf("upsert rocket config failed: %v", err) } } -func createTreasureRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, ownerID int64, regionID int64) { +func createRocketRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, ownerID int64, regionID int64) { t.Helper() if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{ @@ -552,25 +552,25 @@ func createTreasureRoom(t *testing.T, ctx context.Context, svc *roomservice.Serv RoomAvatar: testRoomCoverURL, RoomShortId: roomID, }); err != nil { - t.Fatalf("create treasure room failed: %v", err) + t.Fatalf("create rocket room failed: %v", err) } } -func joinTreasureRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, userID int64) { +func joinRocketRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, userID int64) { t.Helper() if _, err := svc.JoinRoom(ctx, &roomv1.JoinRoomRequest{ Meta: roomservice.NewRequestMeta(roomID, userID), Role: "audience", }); err != nil { - t.Fatalf("join treasure room failed: %v", err) + t.Fatalf("join rocket room failed: %v", err) } } -func treasureMeta(roomID string, actorUserID int64, suffix string) *roomv1.RequestMeta { +func rocketMeta(roomID string, actorUserID int64, suffix string) *roomv1.RequestMeta { return &roomv1.RequestMeta{ - RequestId: "req-room-treasure-" + suffix, - CommandId: "cmd-room-treasure-" + suffix, + RequestId: "req-room-rocket-" + suffix, + CommandId: "cmd-room-rocket-" + suffix, ActorUserId: actorUserID, RoomId: roomID, AppCode: appcode.Default, @@ -578,21 +578,21 @@ func treasureMeta(roomID string, actorUserID int64, suffix string) *roomv1.Reque } } -func treasureProgressEvents(t *testing.T, ctx context.Context, repository *mysqltest.Repository) []*roomeventsv1.RoomTreasureProgressChanged { +func rocketProgressEvents(t *testing.T, ctx context.Context, repository *mysqltest.Repository) []*roomeventsv1.RoomRocketFuelChanged { t.Helper() records, err := repository.ListPendingOutbox(ctx, 50) if err != nil { t.Fatalf("list pending outbox failed: %v", err) } - events := make([]*roomeventsv1.RoomTreasureProgressChanged, 0) + events := make([]*roomeventsv1.RoomRocketFuelChanged, 0) for _, record := range records { - if record.EventType != "RoomTreasureProgressChanged" { + if record.EventType != "RoomRocketFuelChanged" { continue } - var event roomeventsv1.RoomTreasureProgressChanged + var event roomeventsv1.RoomRocketFuelChanged if err := proto.Unmarshal(record.Envelope.GetBody(), &event); err != nil { - t.Fatalf("decode treasure progress event failed: %v", err) + t.Fatalf("decode rocket progress event failed: %v", err) } events = append(events, &event) } @@ -620,7 +620,7 @@ func roomGiftSentEvents(t *testing.T, ctx context.Context, repository *mysqltest return events } -func countTreasureCountdownEvents(t *testing.T, ctx context.Context, repository *mysqltest.Repository) int { +func countRocketIgnitedEvents(t *testing.T, ctx context.Context, repository *mysqltest.Repository) int { t.Helper() records, err := repository.ListPendingOutbox(ctx, 50) @@ -629,14 +629,14 @@ func countTreasureCountdownEvents(t *testing.T, ctx context.Context, repository } count := 0 for _, record := range records { - if record.EventType == "RoomTreasureCountdownStarted" { + if record.EventType == "RoomRocketIgnited" { count++ } } return count } -func hasTreasureGrant(grants []*walletv1.GrantResourceGroupRequest, userID int64, groupID int64) bool { +func hasRocketGrant(grants []*walletv1.GrantResourceGroupRequest, userID int64, groupID int64) bool { for _, grant := range grants { if grant.GetTargetUserId() == userID && grant.GetGroupId() == groupID { return true @@ -645,7 +645,7 @@ func hasTreasureGrant(grants []*walletv1.GrantResourceGroupRequest, userID int64 return false } -func treasureRewardUserIDs(rewards []*roomv1.RoomTreasureRewardGrant) []int64 { +func rocketRewardUserIDs(rewards []*roomv1.RoomRocketRewardGrant) []int64 { userIDs := make([]int64, 0, len(rewards)) for _, reward := range rewards { userIDs = append(userIDs, reward.GetUserId()) diff --git a/services/room-service/internal/room/service/room_treasure.go b/services/room-service/internal/room/service/room_treasure.go deleted file mode 100644 index 359c0de1..00000000 --- a/services/room-service/internal/room/service/room_treasure.go +++ /dev/null @@ -1,933 +0,0 @@ -package service - -import ( - "context" - "crypto/sha256" - "encoding/binary" - "fmt" - "slices" - "strings" - "time" - - roomeventsv1 "hyapp.local/api/proto/events/room/v1" - roomv1 "hyapp.local/api/proto/room/v1" - walletv1 "hyapp.local/api/proto/wallet/v1" - "hyapp/pkg/appcode" - "hyapp/pkg/idgen" - "hyapp/pkg/roomid" - "hyapp/pkg/xerr" - "hyapp/services/room-service/internal/room/command" - "hyapp/services/room-service/internal/room/outbox" - "hyapp/services/room-service/internal/room/rank" - "hyapp/services/room-service/internal/room/state" -) - -const ( - roomTreasureLevelCount = 7 - - roomTreasureDefaultEnergySource = "heat_value" - roomTreasureDefaultOpenDelayMS = int64(30_000) - roomTreasureDefaultBroadcastScope = "region" - roomTreasureDefaultRewardStackPolicy = "allow_stack" - - roomTreasureEnergyHeatValue = "heat_value" - - roomTreasureBroadcastNone = "none" - roomTreasureBroadcastRegion = "region" - roomTreasureBroadcastGlobal = "global" - - roomTreasureRewardStackAllow = "allow_stack" - roomTreasureRewardStackPriority = "priority_only" - - roomTreasureRewardInRoom = "in_room" - roomTreasureRewardTop1 = "top1" - roomTreasureRewardIgniter = "igniter" - roomTreasureGrantSource = "room_treasure" - roomTreasureGrantStatus = "succeeded" -) - -var roomTreasureDefaultThresholds = []int64{1_000, 3_000, 6_000, 10_000, 15_000, 21_000, 28_000} - -// GetRoomTreasure 返回房间宝箱 UI 初始化数据;它只读 Room Cell,不刷新 presence。 -func (s *Service) GetRoomTreasure(ctx context.Context, req *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) { - ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) - roomID := strings.TrimSpace(req.GetRoomId()) - viewerUserID := req.GetViewerUserId() - if !roomid.ValidStringID(roomID) { - return nil, xerr.New(xerr.InvalidArgument, "room_id is invalid") - } - if viewerUserID <= 0 { - return nil, xerr.New(xerr.InvalidArgument, "viewer_user_id is required") - } - - snapshot, err := s.currentSnapshot(ctx, roomID) - if err != nil { - return nil, err - } - if snapshot == nil || snapshot.GetRoomId() == "" { - return nil, xerr.New(xerr.NotFound, "room not found") - } - if snapshot.GetStatus() != state.RoomStatusActive { - return nil, xerr.New(xerr.RoomClosed, "room closed") - } - if snapshotUserBanned(snapshot, viewerUserID, s.clock.Now().UnixMilli()) || findProtoUser(snapshot, viewerUserID) == nil { - // 宝箱状态属于房间内活动信息,只允许仍在业务 presence 内的用户读取。 - return nil, xerr.New(xerr.PermissionDenied, "viewer is not in room") - } - - config, err := s.roomTreasureConfig(ctx) - if err != nil { - return nil, err - } - now := s.clock.Now().UTC() - info := roomTreasureInfoFromConfig(config, snapshot.GetTreasure(), now) - return &roomv1.GetRoomTreasureResponse{ - Treasure: info, - ServerTimeMs: now.UnixMilli(), - }, nil -} - -func (s *Service) roomTreasureConfig(ctx context.Context) (RoomTreasureConfig, error) { - config, exists, err := s.repository.GetRoomTreasureConfig(ctx) - if err != nil { - return RoomTreasureConfig{}, err - } - if !exists { - config = defaultRoomTreasureConfig(appcode.FromContext(ctx)) - } - return normalizeRoomTreasureConfig(config) -} - -func defaultRoomTreasureConfig(appCode string) RoomTreasureConfig { - levels := make([]RoomTreasureLevelConfig, 0, roomTreasureLevelCount) - for index, threshold := range roomTreasureDefaultThresholds { - levels = append(levels, RoomTreasureLevelConfig{ - Level: int32(index + 1), - EnergyThreshold: threshold, - }) - } - return RoomTreasureConfig{ - AppCode: appcode.Normalize(appCode), - EnergySource: roomTreasureDefaultEnergySource, - OpenDelayMS: roomTreasureDefaultOpenDelayMS, - BroadcastEnabled: true, - BroadcastScope: roomTreasureDefaultBroadcastScope, - RewardStackPolicy: roomTreasureDefaultRewardStackPolicy, - Levels: levels, - } -} - -func normalizeRoomTreasureConfig(config RoomTreasureConfig) (RoomTreasureConfig, error) { - config.AppCode = appcode.Normalize(config.AppCode) - if config.AppCode == "" { - config.AppCode = appcode.Default - } - if config.ConfigVersion < 0 { - return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure config_version is invalid") - } - config.EnergySource = defaultRoomTreasureString(config.EnergySource, roomTreasureDefaultEnergySource) - if config.EnergySource == "gift_point_added" { - // 旧配置可能还存着 gift_point_added;GIFT_POINT 已下线,运行时统一按真实送礼贡献 heat_value 计算宝箱能量。 - config.EnergySource = roomTreasureEnergyHeatValue - } - if config.EnergySource != roomTreasureEnergyHeatValue { - return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure energy_source is invalid") - } - if config.OpenDelayMS < 0 || config.BroadcastDelayMS < 0 { - return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure delay is invalid") - } - config.BroadcastScope = defaultRoomTreasureString(config.BroadcastScope, roomTreasureDefaultBroadcastScope) - if config.BroadcastScope != roomTreasureBroadcastNone && config.BroadcastScope != roomTreasureBroadcastRegion && config.BroadcastScope != roomTreasureBroadcastGlobal { - return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure broadcast_scope is invalid") - } - if !config.BroadcastEnabled { - config.BroadcastScope = roomTreasureBroadcastNone - } - config.RewardStackPolicy = defaultRoomTreasureString(config.RewardStackPolicy, roomTreasureDefaultRewardStackPolicy) - if config.RewardStackPolicy != roomTreasureRewardStackAllow && config.RewardStackPolicy != roomTreasureRewardStackPriority { - return RoomTreasureConfig{}, xerr.New(xerr.InvalidArgument, "room treasure reward_stack_policy is invalid") - } - - levels, err := normalizeRoomTreasureLevels(config.Levels) - if err != nil { - return RoomTreasureConfig{}, err - } - config.Levels = levels - config.GiftEnergyRules = normalizeRoomTreasureEnergyRules(config.GiftEnergyRules) - return config, nil -} - -func normalizeRoomTreasureLevels(levels []RoomTreasureLevelConfig) ([]RoomTreasureLevelConfig, error) { - if len(levels) == 0 { - return defaultRoomTreasureConfig(appcode.Default).Levels, nil - } - if len(levels) != roomTreasureLevelCount { - return nil, xerr.New(xerr.InvalidArgument, "room treasure levels must be 7") - } - seen := make(map[int32]bool, roomTreasureLevelCount) - normalized := make([]RoomTreasureLevelConfig, 0, roomTreasureLevelCount) - for _, level := range levels { - if level.Level < 1 || level.Level > roomTreasureLevelCount || seen[level.Level] { - return nil, xerr.New(xerr.InvalidArgument, "room treasure level is invalid") - } - if level.EnergyThreshold <= 0 { - return nil, xerr.New(xerr.InvalidArgument, "room treasure energy_threshold is invalid") - } - seen[level.Level] = true - level.CoverURL = strings.TrimSpace(level.CoverURL) - level.AnimationURL = strings.TrimSpace(level.AnimationURL) - level.OpeningAnimationURL = strings.TrimSpace(level.OpeningAnimationURL) - level.OpenedImageURL = strings.TrimSpace(level.OpenedImageURL) - level.InRoomRewards = normalizeRoomTreasureRewardPool(level.InRoomRewards) - level.Top1Rewards = normalizeRoomTreasureRewardPool(level.Top1Rewards) - level.IgniterRewards = normalizeRoomTreasureRewardPool(level.IgniterRewards) - normalized = append(normalized, level) - } - slices.SortFunc(normalized, func(left, right RoomTreasureLevelConfig) int { - return int(left.Level - right.Level) - }) - return normalized, nil -} - -func normalizeRoomTreasureRewardPool(input []RoomTreasureRewardItem) []RoomTreasureRewardItem { - out := make([]RoomTreasureRewardItem, 0, len(input)) - for _, reward := range input { - reward.RewardItemID = strings.TrimSpace(reward.RewardItemID) - reward.DisplayName = strings.TrimSpace(reward.DisplayName) - reward.IconURL = strings.TrimSpace(reward.IconURL) - if reward.ResourceGroupID <= 0 || reward.Weight <= 0 { - // 后台保存层会拒绝非法奖励;运行时跳过历史脏项,避免一个奖励池配置污染送礼主链路。 - continue - } - out = append(out, reward) - } - return out -} - -func normalizeRoomTreasureEnergyRules(input []GiftEnergyRuleConfig) []GiftEnergyRuleConfig { - out := make([]GiftEnergyRuleConfig, 0, len(input)) - for _, rule := range input { - rule.RuleID = strings.TrimSpace(rule.RuleID) - rule.GiftID = strings.TrimSpace(rule.GiftID) - rule.GiftTypeCode = strings.TrimSpace(rule.GiftTypeCode) - if rule.GiftID == "" && rule.GiftTypeCode == "" { - continue - } - if rule.MultiplierPPM < 0 || rule.FixedEnergy < 0 { - continue - } - out = append(out, rule) - } - return out -} - -func defaultRoomTreasureString(value string, fallback string) string { - value = strings.TrimSpace(value) - if value == "" { - return fallback - } - return value -} - -func roomTreasureInfoFromConfig(config RoomTreasureConfig, current *roomv1.RoomTreasureState, now time.Time) *roomv1.RoomTreasureInfo { - stateView := roomTreasureProtoStateForView(current, config, now) - return &roomv1.RoomTreasureInfo{ - Enabled: config.Enabled, - Levels: roomTreasureLevelsToProto(config.Levels), - State: stateView, - ServerTimeMs: now.UnixMilli(), - BroadcastScope: config.BroadcastScope, - OpenDelayMs: config.OpenDelayMS, - BroadcastDelayMs: config.BroadcastDelayMS, - RewardStackPolicy: config.RewardStackPolicy, - } -} - -func roomTreasureProtoStateForView(current *roomv1.RoomTreasureState, config RoomTreasureConfig, now time.Time) *roomv1.RoomTreasureState { - internal := state.TreasureState{} - if current != nil { - internal = state.TreasureState{ - CurrentLevel: current.GetCurrentLevel(), - CurrentProgress: current.GetCurrentProgress(), - EnergyThreshold: current.GetEnergyThreshold(), - Status: current.GetStatus(), - CountdownStartedAtMS: current.GetCountdownStartedAtMs(), - OpenAtMS: current.GetOpenAtMs(), - OpenedAtMS: current.GetOpenedAtMs(), - ResetAtMS: current.GetResetAtMs(), - Top1UserID: current.GetTop1UserId(), - IgniterUserID: current.GetIgniterUserId(), - BoxID: current.GetBoxId(), - ConfigVersion: current.GetConfigVersion(), - LastRewards: stateRewardsFromProto(current.GetLastRewards()), - } - } - normalized := treasureStateForNow(&internal, config, now, false) - return treasureStateToRoomProto(normalized) -} - -func stateRewardsFromProto(input []*roomv1.RoomTreasureRewardGrant) []state.TreasureRewardGrant { - out := make([]state.TreasureRewardGrant, 0, len(input)) - for _, reward := range input { - out = append(out, state.TreasureRewardGrant{ - RewardRole: reward.GetRewardRole(), - UserID: reward.GetUserId(), - RewardItemID: reward.GetRewardItemId(), - ResourceGroupID: reward.GetResourceGroupId(), - DisplayName: reward.GetDisplayName(), - IconURL: reward.GetIconUrl(), - GrantID: reward.GetGrantId(), - Status: reward.GetStatus(), - }) - } - return out -} - -func roomTreasureLevelsToProto(levels []RoomTreasureLevelConfig) []*roomv1.RoomTreasureLevel { - out := make([]*roomv1.RoomTreasureLevel, 0, len(levels)) - for _, level := range levels { - out = append(out, &roomv1.RoomTreasureLevel{ - Level: level.Level, - EnergyThreshold: level.EnergyThreshold, - CoverUrl: level.CoverURL, - AnimationUrl: level.AnimationURL, - OpeningAnimationUrl: level.OpeningAnimationURL, - OpenedImageUrl: level.OpenedImageURL, - InRoomRewards: roomTreasureRewardsToProto(level.InRoomRewards), - Top1Rewards: roomTreasureRewardsToProto(level.Top1Rewards), - IgniterRewards: roomTreasureRewardsToProto(level.IgniterRewards), - }) - } - return out -} - -func roomTreasureRewardsToProto(input []RoomTreasureRewardItem) []*roomv1.RoomTreasureRewardItem { - out := make([]*roomv1.RoomTreasureRewardItem, 0, len(input)) - for _, reward := range input { - out = append(out, &roomv1.RoomTreasureRewardItem{ - RewardItemId: reward.RewardItemID, - ResourceGroupId: reward.ResourceGroupID, - Weight: reward.Weight, - DisplayName: reward.DisplayName, - IconUrl: reward.IconURL, - }) - } - return out -} - -type treasureGiftApplyResult struct { - touched bool - progressEvent *roomeventsv1.RoomTreasureProgressChanged - countdown *roomeventsv1.RoomTreasureCountdownStarted -} - -func (s *Service) applyRoomTreasureGift(now time.Time, current *state.RoomState, cfg RoomTreasureConfig, cmd command.SendGift, settled *command.SendGift, billing *walletv1.DebitGiftResponse, roomMeta RoomMeta) (treasureGiftApplyResult, error) { - if !cfg.Enabled { - return treasureGiftApplyResult{}, nil - } - now = now.UTC() - nowMS := now.UnixMilli() - treasure := treasureStateForNow(current.Treasure, cfg, now, true) - result := treasureGiftApplyResult{touched: current.Treasure == nil || treasure.ResetAtMS != current.Treasure.ResetAtMS} - - addedEnergy := roomTreasureEnergy(cfg, cmd.GiftID, billing.GetGiftTypeCode(), billing.GetHeatValue()) - effectiveEnergy := int64(0) - overflowEnergy := int64(0) - - if treasure.Status == state.TreasureStatusCountdown { - // 倒计时期间送礼只走普通礼物表现,宝箱能量按产品规则整笔无效。 - overflowEnergy = addedEnergy - } else if addedEnergy > 0 { - remaining := treasure.EnergyThreshold - treasure.CurrentProgress - if remaining < 0 { - remaining = 0 - } - effectiveEnergy = minInt64(addedEnergy, remaining) - overflowEnergy = addedEnergy - effectiveEnergy - if effectiveEnergy > 0 { - treasure.CurrentProgress += effectiveEnergy - result.touched = true - } - if treasure.CurrentProgress >= treasure.EnergyThreshold { - treasure.CurrentProgress = treasure.EnergyThreshold - treasure.Status = state.TreasureStatusCountdown - treasure.CountdownStartedAtMS = nowMS - treasure.OpenAtMS = nowMS + cfg.OpenDelayMS - treasure.Top1UserID = firstRankUserID(current.GiftRank) - treasure.IgniterUserID = cmd.ActorUserID() - treasure.ConfigVersion = cfg.ConfigVersion - result.countdown = &roomeventsv1.RoomTreasureCountdownStarted{ - BoxId: treasure.BoxID, - Level: treasure.CurrentLevel, - CurrentProgress: treasure.CurrentProgress, - EnergyThreshold: treasure.EnergyThreshold, - CountdownStartedAtMs: treasure.CountdownStartedAtMS, - OpenAtMs: treasure.OpenAtMS, - BroadcastScope: cfg.BroadcastScope, - VisibleRegionId: roomMeta.VisibleRegionID, - Top1UserId: treasure.Top1UserID, - IgniterUserId: treasure.IgniterUserID, - CommandId: cmd.ID(), - } - } - } - - if result.touched { - current.Treasure = treasure - } - if effectiveEnergy > 0 { - result.progressEvent = &roomeventsv1.RoomTreasureProgressChanged{ - BoxId: treasure.BoxID, - Level: treasure.CurrentLevel, - AddedEnergy: addedEnergy, - EffectiveAddedEnergy: effectiveEnergy, - OverflowEnergy: overflowEnergy, - CurrentProgress: treasure.CurrentProgress, - EnergyThreshold: treasure.EnergyThreshold, - Status: treasure.Status, - ResetAtMs: treasure.ResetAtMS, - SenderUserId: cmd.ActorUserID(), - GiftId: cmd.GiftID, - GiftCount: cmd.GiftCount, - CommandId: cmd.ID(), - VisibleRegionId: roomMeta.VisibleRegionID, - } - } - - if result.touched { - settled.GiftTypeCode = billing.GetGiftTypeCode() - settled.TreasureTouched = true - settled.TreasureAddedEnergy = addedEnergy - settled.TreasureEffectiveEnergy = effectiveEnergy - settled.TreasureOverflowEnergy = overflowEnergy - settled.TreasureLevel = treasure.CurrentLevel - settled.TreasureProgress = treasure.CurrentProgress - settled.TreasureStatus = treasure.Status - settled.TreasureEnergyThreshold = treasure.EnergyThreshold - settled.TreasureCountdownStartedAtMS = treasure.CountdownStartedAtMS - settled.TreasureOpenAtMS = treasure.OpenAtMS - settled.TreasureResetAtMS = treasure.ResetAtMS - settled.TreasureTop1UserID = treasure.Top1UserID - settled.TreasureIgniterUserID = treasure.IgniterUserID - settled.TreasureBoxID = treasure.BoxID - settled.TreasureConfigVersion = treasure.ConfigVersion - } - return result, nil -} - -func treasureStateForNow(input *state.TreasureState, cfg RoomTreasureConfig, now time.Time, allocateBoxID bool) *state.TreasureState { - now = now.UTC() - nowMS := now.UnixMilli() - resetAtMS := nextUTCResetMS(now) - level := int32(1) - if input != nil && input.CurrentLevel >= 1 && input.CurrentLevel <= roomTreasureLevelCount { - level = input.CurrentLevel - } - if input == nil || input.ResetAtMS <= 0 || nowMS >= input.ResetAtMS { - return newTreasureState(levelForUTCReset(), roomTreasureLevelByNumber(cfg, levelForUTCReset()), resetAtMS, cfg.ConfigVersion, allocateBoxID) - } - - treasure := input.Clone() - levelConfig := roomTreasureLevelByNumber(cfg, level) - treasure.CurrentLevel = level - treasure.EnergyThreshold = levelConfig.EnergyThreshold - treasure.ResetAtMS = input.ResetAtMS - if treasure.Status == "" { - treasure.Status = state.TreasureStatusIdle - } - if treasure.Status != state.TreasureStatusCountdown { - treasure.Status = state.TreasureStatusIdle - treasure.OpenAtMS = 0 - treasure.CountdownStartedAtMS = 0 - } - if treasure.CurrentProgress < 0 { - treasure.CurrentProgress = 0 - } - if treasure.CurrentProgress > treasure.EnergyThreshold { - treasure.CurrentProgress = treasure.EnergyThreshold - } - if treasure.BoxID == "" && allocateBoxID { - treasure.BoxID = idgen.New("room_treasure_box") - } - return treasure -} - -func newTreasureState(level int32, levelConfig RoomTreasureLevelConfig, resetAtMS int64, configVersion int64, allocateBoxID bool) *state.TreasureState { - boxID := "" - if allocateBoxID { - boxID = idgen.New("room_treasure_box") - } - return &state.TreasureState{ - CurrentLevel: level, - EnergyThreshold: levelConfig.EnergyThreshold, - Status: state.TreasureStatusIdle, - ResetAtMS: resetAtMS, - BoxID: boxID, - ConfigVersion: configVersion, - } -} - -func levelForUTCReset() int32 { - return 1 -} - -func nextUTCResetMS(now time.Time) int64 { - utc := now.UTC() - next := time.Date(utc.Year(), utc.Month(), utc.Day()+1, 0, 0, 0, 0, time.UTC) - return next.UnixMilli() -} - -func roomTreasureLevelByNumber(cfg RoomTreasureConfig, level int32) RoomTreasureLevelConfig { - for _, item := range cfg.Levels { - if item.Level == level { - return item - } - } - return defaultRoomTreasureConfig(cfg.AppCode).Levels[0] -} - -func roomTreasureEnergy(cfg RoomTreasureConfig, giftID string, giftTypeCode string, heatValue int64) int64 { - // 宝箱能量只读取 wallet-service 按真实扣费和贡献比例计算出的 heat_value,避免历史 GIFT_POINT 字段污染活动进度。 - base := heatValue - if base < 0 { - base = 0 - } - - for _, rule := range cfg.GiftEnergyRules { - if rule.GiftID != "" && rule.GiftID == giftID { - return roomTreasureEnergyByRule(base, rule) - } - } - for _, rule := range cfg.GiftEnergyRules { - if rule.GiftID == "" && rule.GiftTypeCode != "" && rule.GiftTypeCode == giftTypeCode { - return roomTreasureEnergyByRule(base, rule) - } - } - return base -} - -func roomTreasureEnergyByRule(base int64, rule GiftEnergyRuleConfig) int64 { - if rule.Excluded { - return 0 - } - energy := int64(0) - if rule.MultiplierPPM > 0 { - energy += base * rule.MultiplierPPM / 1_000_000 - } - energy += rule.FixedEnergy - if energy < 0 { - return 0 - } - return energy -} - -func firstRankUserID(items []state.RankItem) int64 { - if len(items) == 0 { - return 0 - } - return items[0].UserID -} - -func minInt64(left int64, right int64) int64 { - if left < right { - return left - } - return right -} - -func treasureStateToRoomProto(input *state.TreasureState) *roomv1.RoomTreasureState { - if input == nil { - return nil - } - rewards := make([]*roomv1.RoomTreasureRewardGrant, 0, len(input.LastRewards)) - for _, reward := range input.LastRewards { - rewards = append(rewards, &roomv1.RoomTreasureRewardGrant{ - RewardRole: reward.RewardRole, - UserId: reward.UserID, - RewardItemId: reward.RewardItemID, - ResourceGroupId: reward.ResourceGroupID, - DisplayName: reward.DisplayName, - IconUrl: reward.IconURL, - GrantId: reward.GrantID, - Status: reward.Status, - }) - } - return &roomv1.RoomTreasureState{ - CurrentLevel: input.CurrentLevel, - CurrentProgress: input.CurrentProgress, - EnergyThreshold: input.EnergyThreshold, - Status: input.Status, - CountdownStartedAtMs: input.CountdownStartedAtMS, - OpenAtMs: input.OpenAtMS, - OpenedAtMs: input.OpenedAtMS, - ResetAtMs: input.ResetAtMS, - Top1UserId: input.Top1UserID, - IgniterUserId: input.IgniterUserID, - BoxId: input.BoxID, - ConfigVersion: input.ConfigVersion, - LastRewards: rewards, - } -} - -func treasureStateToEventRewards(input []state.TreasureRewardGrant) []*roomeventsv1.RoomTreasureRewardGrant { - out := make([]*roomeventsv1.RoomTreasureRewardGrant, 0, len(input)) - for _, reward := range input { - out = append(out, &roomeventsv1.RoomTreasureRewardGrant{ - RewardRole: reward.RewardRole, - UserId: reward.UserID, - RewardItemId: reward.RewardItemID, - ResourceGroupId: reward.ResourceGroupID, - DisplayName: reward.DisplayName, - IconUrl: reward.IconURL, - GrantId: reward.GrantID, - Status: reward.Status, - }) - } - return out -} - -// RunRoomTreasureOpenWorker 周期性扫描已装载房间,把到点的倒计时宝箱走命令链路打开。 -func (s *Service) RunRoomTreasureOpenWorker(ctx context.Context, interval time.Duration) { - if interval <= 0 { - return - } - ticker := time.NewTicker(interval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - _ = s.SweepRoomTreasureOpenings(ctx) - } - } -} - -// SweepRoomTreasureOpenings 只处理本节点仍持有 lease 的已装载 Room Cell。 -func (s *Service) SweepRoomTreasureOpenings(ctx context.Context) error { - now := s.clock.Now().UTC() - nowMS := now.UnixMilli() - for _, roomRef := range s.loadedRoomRefs() { - roomCtx := appcode.WithContext(ctx, roomRef.AppCode) - lease, owned, err := s.loadedRoomLease(roomCtx, roomRef, now) - if err != nil { - return err - } - if !owned { - continue - } - roomCell := s.loadCell(roomCtx, roomRef.RoomID) - if roomCell == nil { - continue - } - currentState, _, err := roomCell.Snapshot(roomCtx) - if err != nil { - return err - } - owned, err = s.verifyLoadedRoomLease(roomCtx, roomRef, lease, s.clock.Now()) - if err != nil { - return err - } - if !owned || currentState == nil || currentState.Treasure == nil { - continue - } - treasure := currentState.Treasure - if treasure.ResetAtMS > 0 && nowMS >= treasure.ResetAtMS { - // UTC 切日优先级高于延迟开箱;跨日倒计时宝箱不再结算,下一次查询或送礼会按新 UTC 日投影/持久化一级新进度。 - continue - } - if treasure.Status != state.TreasureStatusCountdown || treasure.OpenAtMS <= 0 || treasure.OpenAtMS > nowMS { - continue - } - cmd := command.OpenRoomTreasure{ - Base: command.Base{ - AppCode: roomRef.AppCode, - RequestID: idgen.New("req_room_treasure_open"), - CommandID: roomTreasureOpenCommandID(treasure.BoxID), - ActorID: roomTreasureSystemActor(currentState), - Room: roomRef.RoomID, - GatewayNodeID: s.nodeID, - SessionID: "room-treasure-open", - SentAtMS: nowMS, - }, - BoxID: treasure.BoxID, - Level: treasure.CurrentLevel, - } - if _, err := s.openRoomTreasure(roomCtx, cmd); err != nil { - return err - } - } - return nil -} - -func roomTreasureOpenCommandID(boxID string) string { - if strings.TrimSpace(boxID) == "" { - return idgen.New("cmd_room_treasure_open") - } - return "cmd_room_treasure_open_" + boxID -} - -func roomTreasureSystemActor(current *state.RoomState) int64 { - if current == nil { - return 0 - } - if current.OwnerUserID > 0 { - return current.OwnerUserID - } - if current.Treasure != nil && current.Treasure.IgniterUserID > 0 { - return current.Treasure.IgniterUserID - } - return 0 -} - -func (s *Service) openRoomTreasure(ctx context.Context, cmd command.OpenRoomTreasure) (*roomv1.RoomTreasureState, error) { - result, err := s.mutateRoom(ctx, cmd, true, func(now time.Time, current *state.RoomState, _ *rank.LocalRank) (mutationResult, []outbox.Record, error) { - now = now.UTC() - nowMS := now.UnixMilli() - if current.Treasure == nil || current.Treasure.Status != state.TreasureStatusCountdown { - return mutationResult{snapshot: current.ToProto()}, nil, nil - } - if current.Treasure.BoxID != cmd.BoxID || current.Treasure.CurrentLevel != cmd.Level { - return mutationResult{snapshot: current.ToProto()}, nil, nil - } - if current.Treasure.ResetAtMS > 0 && nowMS >= current.Treasure.ResetAtMS { - // 手动或延迟到达的开箱命令也不能越过 UTC 日界结算昨天的宝箱。 - return mutationResult{snapshot: current.ToProto()}, nil, nil - } - if current.Treasure.OpenAtMS <= 0 || current.Treasure.OpenAtMS > nowMS { - return mutationResult{snapshot: current.ToProto()}, nil, nil - } - - cfg, err := s.roomTreasureConfig(ctx) - if err != nil { - return mutationResult{}, nil, err - } - levelCfg := roomTreasureLevelByNumber(cfg, current.Treasure.CurrentLevel) - inRoomUserIDs := sortedTreasureOnlineUserIDs(current.OnlineUsers) - rewards, err := s.settleRoomTreasureRewards(ctx, now, current, cfg, levelCfg, inRoomUserIDs) - if err != nil { - return mutationResult{}, nil, err - } - - nextLevel := current.Treasure.CurrentLevel + 1 - if nextLevel > roomTreasureLevelCount { - // 七级是当天最高等级;打开七级后继续留在七级,UTC 切日再回到一级。 - nextLevel = roomTreasureLevelCount - } - nextLevelCfg := roomTreasureLevelByNumber(cfg, nextLevel) - settledCommand := cmd - settledCommand.NextLevel = nextLevel - settledCommand.NextEnergyThreshold = nextLevelCfg.EnergyThreshold - settledCommand.ConfigVersion = cfg.ConfigVersion - settledCommand.ResetAtMS = current.Treasure.ResetAtMS - settledCommand.Top1UserID = current.Treasure.Top1UserID - settledCommand.IgniterUserID = current.Treasure.IgniterUserID - settledCommand.InRoomUserIDs = inRoomUserIDs - settledCommand.Rewards = treasureRewardsToCommand(rewards) - commandPayload, err := command.Serialize(settledCommand) - if err != nil { - return mutationResult{}, nil, err - } - - openedBoxID := current.Treasure.BoxID - openedLevel := current.Treasure.CurrentLevel - top1UserID := current.Treasure.Top1UserID - igniterUserID := current.Treasure.IgniterUserID - resetAtMS := current.Treasure.ResetAtMS - current.Treasure = &state.TreasureState{ - CurrentLevel: nextLevel, - EnergyThreshold: nextLevelCfg.EnergyThreshold, - Status: state.TreasureStatusIdle, - OpenedAtMS: nowMS, - ResetAtMS: resetAtMS, - ConfigVersion: cfg.ConfigVersion, - LastRewards: rewards, - } - current.Version++ - - openedEvent, err := outbox.Build(current.RoomID, "RoomTreasureOpened", current.Version, now, &roomeventsv1.RoomTreasureOpened{ - BoxId: openedBoxID, - Level: openedLevel, - NextLevel: nextLevel, - OpenedAtMs: nowMS, - ResetAtMs: resetAtMS, - Top1UserId: top1UserID, - IgniterUserId: igniterUserID, - InRoomUserIds: inRoomUserIDs, - Rewards: treasureStateToEventRewards(rewards), - }) - if err != nil { - return mutationResult{}, nil, err - } - records := []outbox.Record{openedEvent} - if len(rewards) > 0 { - rewardEvent, err := outbox.Build(current.RoomID, "RoomTreasureRewardGranted", current.Version, now, &roomeventsv1.RoomTreasureRewardGranted{ - BoxId: openedBoxID, - Level: openedLevel, - Rewards: treasureStateToEventRewards(rewards), - }) - if err != nil { - return mutationResult{}, nil, err - } - records = append(records, rewardEvent) - } - - return mutationResult{ - snapshot: current.ToProto(), - commandPayload: commandPayload, - }, records, nil - }) - if err != nil { - return nil, err - } - return result.snapshot.GetTreasure(), nil -} - -func sortedTreasureOnlineUserIDs(users map[int64]*state.RoomUserState) []int64 { - userIDs := make([]int64, 0, len(users)) - for userID := range users { - if userID > 0 { - userIDs = append(userIDs, userID) - } - } - slices.Sort(userIDs) - return userIDs -} - -func (s *Service) settleRoomTreasureRewards(ctx context.Context, now time.Time, current *state.RoomState, cfg RoomTreasureConfig, levelCfg RoomTreasureLevelConfig, inRoomUserIDs []int64) ([]state.TreasureRewardGrant, error) { - if current == nil || current.Treasure == nil { - return nil, nil - } - rewards := make([]state.TreasureRewardGrant, 0, len(inRoomUserIDs)+2) - claimed := make(map[int64]bool, len(inRoomUserIDs)+2) - addReward := func(role string, userID int64, pool []RoomTreasureRewardItem) error { - if userID <= 0 { - return nil - } - if cfg.RewardStackPolicy == roomTreasureRewardStackPriority && claimed[userID] { - return nil - } - item, ok := selectRoomTreasureReward(current.Treasure.BoxID, role, userID, pool) - if !ok { - return nil - } - grantID, err := s.grantRoomTreasureReward(ctx, now, current, current.Treasure.BoxID, role, userID, item) - if err != nil { - return err - } - rewards = append(rewards, state.TreasureRewardGrant{ - RewardRole: role, - UserID: userID, - RewardItemID: item.RewardItemID, - ResourceGroupID: item.ResourceGroupID, - DisplayName: item.DisplayName, - IconURL: item.IconURL, - GrantID: grantID, - Status: roomTreasureGrantStatus, - }) - claimed[userID] = true - return nil - } - - if cfg.RewardStackPolicy == roomTreasureRewardStackPriority { - // 去重策略下先发特殊身份奖励,再发普通在房奖励,避免 top1/点火人被普通池占位。 - if err := addReward(roomTreasureRewardIgniter, current.Treasure.IgniterUserID, levelCfg.IgniterRewards); err != nil { - return nil, err - } - if err := addReward(roomTreasureRewardTop1, current.Treasure.Top1UserID, levelCfg.Top1Rewards); err != nil { - return nil, err - } - for _, userID := range inRoomUserIDs { - if err := addReward(roomTreasureRewardInRoom, userID, levelCfg.InRoomRewards); err != nil { - return nil, err - } - } - return rewards, nil - } - - for _, userID := range inRoomUserIDs { - if err := addReward(roomTreasureRewardInRoom, userID, levelCfg.InRoomRewards); err != nil { - return nil, err - } - } - if err := addReward(roomTreasureRewardTop1, current.Treasure.Top1UserID, levelCfg.Top1Rewards); err != nil { - return nil, err - } - if err := addReward(roomTreasureRewardIgniter, current.Treasure.IgniterUserID, levelCfg.IgniterRewards); err != nil { - return nil, err - } - return rewards, nil -} - -func (s *Service) grantRoomTreasureReward(ctx context.Context, _ time.Time, current *state.RoomState, boxID string, role string, userID int64, item RoomTreasureRewardItem) (string, error) { - if s.wallet == nil { - return "", xerr.New(xerr.Unavailable, "wallet client is not configured") - } - operatorUserID := current.OwnerUserID - if operatorUserID <= 0 { - operatorUserID = userID - } - resp, err := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ - CommandId: roomTreasureGrantCommandID(boxID, role, userID, item.RewardItemID), - AppCode: appcode.FromContext(ctx), - TargetUserId: userID, - GroupId: item.ResourceGroupID, - Reason: fmt.Sprintf("room treasure %s reward", role), - OperatorUserId: operatorUserID, - GrantSource: roomTreasureGrantSource, - }) - if err != nil { - return "", err - } - if resp == nil || resp.GetGrant() == nil { - return "", xerr.New(xerr.Unavailable, "wallet grant response is empty") - } - return resp.GetGrant().GetGrantId(), nil -} - -func selectRoomTreasureReward(boxID string, role string, userID int64, pool []RoomTreasureRewardItem) (RoomTreasureRewardItem, bool) { - total := int64(0) - for _, item := range pool { - if item.Weight > 0 && item.ResourceGroupID > 0 { - total += item.Weight - } - } - if total <= 0 { - return RoomTreasureRewardItem{}, false - } - hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d", boxID, role, userID))) - pick := int64(binary.BigEndian.Uint64(hash[:8]) % uint64(total)) - cursor := int64(0) - for _, item := range pool { - if item.Weight <= 0 || item.ResourceGroupID <= 0 { - continue - } - cursor += item.Weight - if pick < cursor { - return item, true - } - } - return pool[len(pool)-1], true -} - -func roomTreasureGrantCommandID(boxID string, role string, userID int64, rewardItemID string) string { - hash := sha256.Sum256([]byte(fmt.Sprintf("%s|%s|%d|%s", boxID, role, userID, rewardItemID))) - return fmt.Sprintf("cmd_room_treasure_grant_%x", hash[:8]) -} - -func treasureRewardsToCommand(input []state.TreasureRewardGrant) []command.TreasureRewardGrant { - out := make([]command.TreasureRewardGrant, 0, len(input)) - for _, reward := range input { - out = append(out, command.TreasureRewardGrant{ - RewardRole: reward.RewardRole, - UserID: reward.UserID, - RewardItemID: reward.RewardItemID, - ResourceGroupID: reward.ResourceGroupID, - DisplayName: reward.DisplayName, - IconURL: reward.IconURL, - GrantID: reward.GrantID, - Status: reward.Status, - }) - } - return out -} diff --git a/services/room-service/internal/room/service/room_treasure_mq.go b/services/room-service/internal/room/service/room_treasure_mq.go deleted file mode 100644 index 765af793..00000000 --- a/services/room-service/internal/room/service/room_treasure_mq.go +++ /dev/null @@ -1,111 +0,0 @@ -package service - -import ( - "context" - "fmt" - - "google.golang.org/protobuf/proto" - roomeventsv1 "hyapp.local/api/proto/events/room/v1" - "hyapp/pkg/appcode" - "hyapp/pkg/idgen" - "hyapp/pkg/roommq" - "hyapp/pkg/xerr" - "hyapp/services/room-service/internal/integration" - "hyapp/services/room-service/internal/room/command" - "hyapp/services/room-service/internal/room/state" -) - -// scheduleRoomTreasureOpenFromEnvelope derives the delayed wakeup from the -// already committed countdown outbox. Scheduling after outbox claim keeps -// SendGift free of external MQ side effects before MySQL commit. -func (s *Service) scheduleRoomTreasureOpenFromEnvelope(ctx context.Context, envelope *roomeventsv1.EventEnvelope) error { - if s.roomTreasureOpenScheduler == nil || envelope == nil || envelope.GetEventType() != "RoomTreasureCountdownStarted" { - return nil - } - var event roomeventsv1.RoomTreasureCountdownStarted - if err := proto.Unmarshal(envelope.GetBody(), &event); err != nil { - return err - } - if event.GetBoxId() == "" || event.GetLevel() <= 0 || event.GetOpenAtMs() <= 0 { - return fmt.Errorf("room treasure countdown event is incomplete: event_id=%s", envelope.GetEventId()) - } - return s.roomTreasureOpenScheduler.ScheduleRoomTreasureOpen(ctx, integration.RoomTreasureOpenSchedule{ - AppCode: appcode.Normalize(envelope.GetAppCode()), - RoomID: envelope.GetRoomId(), - BoxID: event.GetBoxId(), - Level: event.GetLevel(), - OpenAtMS: event.GetOpenAtMs(), - CommandID: roomTreasureOpenCommandID(event.GetBoxId()), - }) -} - -// HandleRoomTreasureOpenDue handles a RocketMQ delayed wakeup. It pre-checks -// due-ness before writing a command log, because an early-delivered delay -// message must not poison the deterministic open command_id as a no-op. -func (s *Service) HandleRoomTreasureOpenDue(ctx context.Context, due roommq.RoomTreasureOpenDueMessage) error { - ctx = appcode.WithContext(ctx, due.AppCode) - if due.RoomID == "" || due.BoxID == "" || due.Level <= 0 || due.OpenAtMS <= 0 { - return xerr.New(xerr.InvalidArgument, "room treasure open due message is incomplete") - } - - roomCell, lease, err := s.ensureCell(ctx, due.RoomID) - if err != nil { - return err - } - currentState, _, err := roomCell.Snapshot(ctx) - if err != nil { - return err - } - owned, err := s.directory.VerifyOwner(ctx, runtimeRoomKeyFromContext(ctx, due.RoomID), s.nodeID, lease.LeaseToken, s.clock.Now()) - if err != nil { - return err - } - if !owned { - return xerr.New(xerr.Conflict, "room treasure open lease moved") - } - - now := s.clock.Now().UTC() - nowMS := now.UnixMilli() - if currentState == nil || currentState.Treasure == nil || currentState.Treasure.Status != state.TreasureStatusCountdown { - return nil - } - treasure := currentState.Treasure - if treasure.BoxID != due.BoxID || treasure.CurrentLevel != due.Level || treasure.OpenAtMS != due.OpenAtMS { - // Stale delayed messages are expected after retries or if the room reset/opened by another path. - return nil - } - if treasure.ResetAtMS > 0 && nowMS >= treasure.ResetAtMS { - // UTC day reset wins over yesterday's delayed wakeup. - return nil - } - if treasure.OpenAtMS > nowMS { - return xerr.New(xerr.Unavailable, "room treasure open wakeup arrived before open_at_ms") - } - - actorUserID := currentState.OwnerUserID - if actorUserID <= 0 { - actorUserID = treasure.IgniterUserID - } - if actorUserID <= 0 { - return xerr.New(xerr.InvalidArgument, "room treasure open actor is missing") - } - commandID := due.CommandID - if commandID == "" { - commandID = roomTreasureOpenCommandID(due.BoxID) - } - _, err = s.openRoomTreasure(ctx, command.OpenRoomTreasure{ - Base: command.Base{ - AppCode: appcode.FromContext(ctx), - RequestID: idgen.New("req_room_treasure_open_mq"), - CommandID: commandID, - ActorID: actorUserID, - Room: due.RoomID, - GatewayNodeID: s.nodeID, - SessionID: "room-treasure-open-mq", - SentAtMS: nowMS, - }, - BoxID: due.BoxID, - Level: due.Level, - }) - return err -} diff --git a/services/room-service/internal/room/service/service.go b/services/room-service/internal/room/service/service.go index 19436743..9d438299 100644 --- a/services/room-service/internal/room/service/service.go +++ b/services/room-service/internal/room/service/service.go @@ -32,8 +32,8 @@ type Config struct { MicPublishTimeout time.Duration // RTCUserRemover 是平台级封禁后把用户从腾讯 RTC 房间移出的外部边界。 RTCUserRemover integration.RTCUserRemover - // RoomTreasureOpenScheduler 把倒计时开箱唤醒交给外部延迟消息,避免只靠已加载 Cell 扫描。 - RoomTreasureOpenScheduler integration.RoomTreasureOpenScheduler + // RoomRocketLaunchScheduler 把倒计时发射唤醒交给外部延迟消息,避免只靠已加载 Cell 扫描。 + RoomRocketLaunchScheduler integration.RoomRocketLaunchScheduler // RoomGiftLeaderboard 是跨房间贡献榜读模型,SendGift 提交后 best-effort 写入。 RoomGiftLeaderboard RoomGiftLeaderboardStore // LuckyGiftSendLocker 串行化同一用户的幸运礼物扣费、抽奖和同步返奖链路。 @@ -72,8 +72,8 @@ type Service struct { syncPublisher integration.RoomEventPublisher // outboxPublisher 是补偿 worker 对外部消费者的异步投递抽象。 outboxPublisher integration.OutboxPublisher - // roomTreasureOpenScheduler 在 countdown outbox 投递成功后安排 open_at_ms 唤醒。 - roomTreasureOpenScheduler integration.RoomTreasureOpenScheduler + // roomRocketLaunchScheduler 在 ignited outbox 投递成功后安排 launch_at_ms 唤醒。 + roomRocketLaunchScheduler integration.RoomRocketLaunchScheduler // roomGiftLeaderboard 只保存房间维度贡献值 zset,不承载 Room Cell 核心状态。 roomGiftLeaderboard RoomGiftLeaderboardStore // luckyGiftSendLocker 只保护同一用户幸运礼物扣费到同步返奖的小事务链路。 @@ -195,7 +195,7 @@ func New(cfg Config, directory router.Directory, repository Repository, wallet i luckyGift: luckyGiftClient, syncPublisher: syncPublisher, outboxPublisher: outboxPublisher, - roomTreasureOpenScheduler: cfg.RoomTreasureOpenScheduler, + roomRocketLaunchScheduler: cfg.RoomRocketLaunchScheduler, roomGiftLeaderboard: cfg.RoomGiftLeaderboard, luckyGiftSendLocker: cfg.LuckyGiftSendLocker, luckyGiftSendLockTTL: luckyGiftSendLockTTL, diff --git a/services/room-service/internal/room/state/state.go b/services/room-service/internal/room/state/state.go index 2ef606f9..bfe84bfb 100644 --- a/services/room-service/internal/room/state/state.go +++ b/services/room-service/internal/room/state/state.go @@ -20,10 +20,12 @@ const ( // RoomStatusDeleted 表示后台删除后的运营终态;保留 command log/snapshot 作为恢复和审计来源。 RoomStatusDeleted = "deleted" - // TreasureStatusIdle 表示当前等级宝箱还在积攒能量。 - TreasureStatusIdle = "idle" - // TreasureStatusCountdown 表示当前等级已经满能量,等待后台 worker 到点开箱。 - TreasureStatusCountdown = "countdown" + // RocketStatusCharging 表示当前等级火箭还在积攒燃料。 + RocketStatusCharging = "charging" + // RocketStatusIgnited 表示当前等级已经燃料满,等待后台 worker 到点发射。 + RocketStatusIgnited = "ignited" + // RocketStatusCompleted 表示当天最高等级已经点火完成,UTC 重置前不再积攒新火箭。 + RocketStatusCompleted = "completed" // MicPublishIdle 表示麦位没有正在确认或已确认的 RTC 发流会话。 MicPublishIdle = "idle" @@ -129,17 +131,17 @@ type RankItem struct { UpdatedAtMS int64 } -// TreasureRewardGrant 记录一次宝箱开箱时给单个用户结算出的奖励。 -type TreasureRewardGrant struct { +// RocketRewardGrant 记录一次火箭发射时给单个用户结算出的奖励。 +type RocketRewardGrant struct { // RewardRole 区分 in_room、top1、igniter 三种奖励归因,客户端据此分组展示。 RewardRole string - // UserID 是奖励归属用户;top1 和 igniter 即使离房也必须用满能量时锁定的用户。 + // UserID 是奖励归属用户;top1 和 igniter 即使离房也必须用燃料满时锁定的用户。 UserID int64 // RewardItemID 是后台奖励池内的稳定项 ID,用于排障和客户端去重。 RewardItemID string // ResourceGroupID 是 wallet-service 发放资源组 ID。 ResourceGroupID int64 - // DisplayName/IconURL 是开箱 IM 展示快照,避免客户端为历史消息回查后台配置。 + // DisplayName/IconURL 是发射 IM 展示快照,避免客户端为历史消息回查后台配置。 DisplayName string IconURL string // GrantID 是 wallet-service 资源发放回执;空值表示该奖励未实际发放。 @@ -148,40 +150,62 @@ type TreasureRewardGrant struct { Status string } -// TreasureState 保存 Room Cell 内当前宝箱进度和最近一次开箱结果。 -type TreasureState struct { - // CurrentLevel 是当前正在积攒的宝箱等级,UTC 日重置后回到 1。 - CurrentLevel int32 - // CurrentProgress 是当前等级已累计能量,满级后的溢出不跨等级继承。 - CurrentProgress int64 - // EnergyThreshold 是当前等级阈值快照,便于客户端不依赖配置二次计算。 - EnergyThreshold int64 - // Status 区分 idle/countdown,倒计时期间送礼能量无效。 - Status string - // CountdownStartedAtMS/OpenAtMS/OpenedAtMS 描述最近一次满能量到开箱的时间线。 - CountdownStartedAtMS int64 - OpenAtMS int64 - OpenedAtMS int64 - // ResetAtMS 是下一次 UTC 自然日重置毫秒时间。 - ResetAtMS int64 - // Top1UserID 和 IgniterUserID 在满能量瞬间锁定,用户离房或下线仍按这里发奖。 +// RocketPendingLaunch 保存单枚已点火火箭的发射快照。 +type RocketPendingLaunch struct { + // RocketID 是这枚火箭从点火到发奖的幂等标识。 + RocketID string + // Level/FuelThreshold 是点火瞬间锁定的等级和阈值,后续配置变更不影响本枚火箭。 + Level int32 + FuelThreshold int64 + // IgnitedAtMS/LaunchAtMS/ResetAtMS 确定延迟发射和 UTC 日界校验。 + IgnitedAtMS int64 + LaunchAtMS int64 + ResetAtMS int64 + // Top1UserID/IgniterUserID 在点火瞬间锁定,用户离房后仍按这个事实结算特殊奖励。 Top1UserID int64 IgniterUserID int64 - // BoxID 是单次宝箱从积攒到开箱的幂等标识,奖励抽取和 wallet command_id 都依赖它。 - BoxID string - // ConfigVersion 记录本轮宝箱使用的后台配置版本,开箱时不被中途配置变更影响。 + // ConfigVersion 锁定本枚火箭的配置版本,CoverURL 给区域飘屏和客户端展示使用。 ConfigVersion int64 - // LastRewards 保存最近一次开箱发奖结果,用于断线重连后补 UI。 - LastRewards []TreasureRewardGrant + CoverURL string } -// Clone 深拷贝宝箱状态,避免 Room Cell 失败命令污染当前状态。 -func (t *TreasureState) Clone() *TreasureState { +// RocketState 保存 Room Cell 内当前火箭进度和最近一次发射结果。 +type RocketState struct { + // CurrentLevel 是当前正在积攒的火箭等级,UTC 日重置后回到 1。 + CurrentLevel int32 + // CurrentFuel 是当前等级已累计燃料,满级后的溢出不跨等级继承。 + CurrentFuel int64 + // FuelThreshold 是当前等级阈值快照,便于客户端不依赖配置二次计算。 + FuelThreshold int64 + // Status 区分 charging/completed;已点火火箭在 PendingLaunches 中独立排队,不阻塞当前进度。 + Status string + // IgnitedAtMS/LaunchAtMS 保留最近一次点火快照,客户端可用 PendingLaunches 获得完整队列。 + IgnitedAtMS int64 + LaunchAtMS int64 + LaunchedAtMS int64 + // ResetAtMS 是下一次 UTC 自然日重置毫秒时间。 + ResetAtMS int64 + // Top1UserID 和 IgniterUserID 在燃料满瞬间锁定,用户离房或下线仍按这里发奖。 + Top1UserID int64 + IgniterUserID int64 + // RocketID 是单次火箭从积攒到发射的幂等标识,奖励抽取和 wallet command_id 都依赖它。 + RocketID string + // ConfigVersion 记录本轮火箭使用的后台配置版本,发射时不被中途配置变更影响。 + ConfigVersion int64 + // PendingLaunches 是已经满阈值但还没到延迟发射时间的火箭队列。 + PendingLaunches []RocketPendingLaunch + // LastRewards 保存最近一次发射发奖结果,用于断线重连后补 UI。 + LastRewards []RocketRewardGrant +} + +// Clone 深拷贝火箭状态,避免 Room Cell 失败命令污染当前状态。 +func (t *RocketState) Clone() *RocketState { if t == nil { return nil } cloned := *t - cloned.LastRewards = append([]TreasureRewardGrant(nil), t.LastRewards...) + cloned.PendingLaunches = append([]RocketPendingLaunch(nil), t.PendingLaunches...) + cloned.LastRewards = append([]RocketRewardGrant(nil), t.LastRewards...) return &cloned } @@ -218,8 +242,8 @@ type RoomState struct { GiftRank []RankItem // RoomExt 预留少量房间扩展字段,避免 v1 频繁改结构。 RoomExt map[string]string - // Treasure 是语音房宝箱状态,送礼能量和开箱必须跟随 Room Cell 串行提交。 - Treasure *TreasureState + // Rocket 是语音房火箭状态,送礼燃料和发射必须跟随 Room Cell 串行提交。 + Rocket *RocketState // Version 是房间状态版本,成功变更后递增,快照和 command log 都依赖它。 Version int64 } @@ -272,7 +296,7 @@ func (s *RoomState) Clone() *RoomState { Heat: s.Heat, GiftRank: append([]RankItem(nil), s.GiftRank...), RoomExt: make(map[string]string, len(s.RoomExt)), - Treasure: cloneTreasureState(s.Treasure), + Rocket: cloneRocketState(s.Rocket), Version: s.Version, } @@ -415,7 +439,7 @@ func (s *RoomState) ToProto() *roomv1.RoomSnapshot { Version: s.Version, RoomShortId: s.RoomExt["room_short_id"], Locked: s.RoomPasswordHash != "", - Treasure: treasureStateToProto(s.Treasure), + Rocket: rocketStateToProto(s.Rocket), BanStates: sortedModerationStates(s.BanUsers), } } @@ -442,7 +466,7 @@ func FromProto(snapshot *roomv1.RoomSnapshot) *RoomState { MuteUsers: make(map[int64]bool, len(snapshot.GetMuteUserIds())), GiftRank: make([]RankItem, 0, len(snapshot.GetGiftRank())), RoomExt: cloneStringMap(snapshot.GetRoomExt()), - Treasure: treasureStateFromProto(snapshot.GetTreasure()), + Rocket: rocketStateFromProto(snapshot.GetRocket()), Heat: snapshot.GetHeat(), Version: snapshot.GetVersion(), } @@ -586,22 +610,23 @@ func cloneStringMap(input map[string]string) map[string]string { return cloned } -func cloneTreasureState(input *TreasureState) *TreasureState { +func cloneRocketState(input *RocketState) *RocketState { if input == nil { return nil } cloned := *input - cloned.LastRewards = append([]TreasureRewardGrant(nil), input.LastRewards...) + cloned.PendingLaunches = append([]RocketPendingLaunch(nil), input.PendingLaunches...) + cloned.LastRewards = append([]RocketRewardGrant(nil), input.LastRewards...) return &cloned } -func treasureStateToProto(input *TreasureState) *roomv1.RoomTreasureState { +func rocketStateToProto(input *RocketState) *roomv1.RoomRocketState { if input == nil { return nil } - rewards := make([]*roomv1.RoomTreasureRewardGrant, 0, len(input.LastRewards)) + rewards := make([]*roomv1.RoomRocketRewardGrant, 0, len(input.LastRewards)) for _, reward := range input.LastRewards { - rewards = append(rewards, &roomv1.RoomTreasureRewardGrant{ + rewards = append(rewards, &roomv1.RoomRocketRewardGrant{ RewardRole: reward.RewardRole, UserId: reward.UserID, RewardItemId: reward.RewardItemID, @@ -612,30 +637,46 @@ func treasureStateToProto(input *TreasureState) *roomv1.RoomTreasureState { Status: reward.Status, }) } - return &roomv1.RoomTreasureState{ - CurrentLevel: input.CurrentLevel, - CurrentProgress: input.CurrentProgress, - EnergyThreshold: input.EnergyThreshold, - Status: input.Status, - CountdownStartedAtMs: input.CountdownStartedAtMS, - OpenAtMs: input.OpenAtMS, - OpenedAtMs: input.OpenedAtMS, - ResetAtMs: input.ResetAtMS, - Top1UserId: input.Top1UserID, - IgniterUserId: input.IgniterUserID, - BoxId: input.BoxID, - ConfigVersion: input.ConfigVersion, - LastRewards: rewards, + pending := make([]*roomv1.RoomRocketPendingLaunch, 0, len(input.PendingLaunches)) + for _, launch := range input.PendingLaunches { + pending = append(pending, &roomv1.RoomRocketPendingLaunch{ + RocketId: launch.RocketID, + Level: launch.Level, + FuelThreshold: launch.FuelThreshold, + IgnitedAtMs: launch.IgnitedAtMS, + LaunchAtMs: launch.LaunchAtMS, + ResetAtMs: launch.ResetAtMS, + Top1UserId: launch.Top1UserID, + IgniterUserId: launch.IgniterUserID, + ConfigVersion: launch.ConfigVersion, + CoverUrl: launch.CoverURL, + }) + } + return &roomv1.RoomRocketState{ + CurrentLevel: input.CurrentLevel, + CurrentFuel: input.CurrentFuel, + FuelThreshold: input.FuelThreshold, + Status: input.Status, + IgnitedAtMs: input.IgnitedAtMS, + LaunchAtMs: input.LaunchAtMS, + LaunchedAtMs: input.LaunchedAtMS, + ResetAtMs: input.ResetAtMS, + Top1UserId: input.Top1UserID, + IgniterUserId: input.IgniterUserID, + RocketId: input.RocketID, + ConfigVersion: input.ConfigVersion, + LastRewards: rewards, + PendingLaunches: pending, } } -func treasureStateFromProto(input *roomv1.RoomTreasureState) *TreasureState { +func rocketStateFromProto(input *roomv1.RoomRocketState) *RocketState { if input == nil { return nil } - rewards := make([]TreasureRewardGrant, 0, len(input.GetLastRewards())) + rewards := make([]RocketRewardGrant, 0, len(input.GetLastRewards())) for _, reward := range input.GetLastRewards() { - rewards = append(rewards, TreasureRewardGrant{ + rewards = append(rewards, RocketRewardGrant{ RewardRole: reward.GetRewardRole(), UserID: reward.GetUserId(), RewardItemID: reward.GetRewardItemId(), @@ -646,19 +687,35 @@ func treasureStateFromProto(input *roomv1.RoomTreasureState) *TreasureState { Status: reward.GetStatus(), }) } - return &TreasureState{ - CurrentLevel: input.GetCurrentLevel(), - CurrentProgress: input.GetCurrentProgress(), - EnergyThreshold: input.GetEnergyThreshold(), - Status: input.GetStatus(), - CountdownStartedAtMS: input.GetCountdownStartedAtMs(), - OpenAtMS: input.GetOpenAtMs(), - OpenedAtMS: input.GetOpenedAtMs(), - ResetAtMS: input.GetResetAtMs(), - Top1UserID: input.GetTop1UserId(), - IgniterUserID: input.GetIgniterUserId(), - BoxID: input.GetBoxId(), - ConfigVersion: input.GetConfigVersion(), - LastRewards: rewards, + pending := make([]RocketPendingLaunch, 0, len(input.GetPendingLaunches())) + for _, launch := range input.GetPendingLaunches() { + pending = append(pending, RocketPendingLaunch{ + RocketID: launch.GetRocketId(), + Level: launch.GetLevel(), + FuelThreshold: launch.GetFuelThreshold(), + IgnitedAtMS: launch.GetIgnitedAtMs(), + LaunchAtMS: launch.GetLaunchAtMs(), + ResetAtMS: launch.GetResetAtMs(), + Top1UserID: launch.GetTop1UserId(), + IgniterUserID: launch.GetIgniterUserId(), + ConfigVersion: launch.GetConfigVersion(), + CoverURL: launch.GetCoverUrl(), + }) + } + return &RocketState{ + CurrentLevel: input.GetCurrentLevel(), + CurrentFuel: input.GetCurrentFuel(), + FuelThreshold: input.GetFuelThreshold(), + Status: input.GetStatus(), + IgnitedAtMS: input.GetIgnitedAtMs(), + LaunchAtMS: input.GetLaunchAtMs(), + LaunchedAtMS: input.GetLaunchedAtMs(), + ResetAtMS: input.GetResetAtMs(), + Top1UserID: input.GetTop1UserId(), + IgniterUserID: input.GetIgniterUserId(), + RocketID: input.GetRocketId(), + ConfigVersion: input.GetConfigVersion(), + PendingLaunches: pending, + LastRewards: rewards, } } diff --git a/services/room-service/internal/storage/mysql/repository.go b/services/room-service/internal/storage/mysql/repository.go index dac7c891..d775196e 100644 --- a/services/room-service/internal/storage/mysql/repository.go +++ b/services/room-service/internal/storage/mysql/repository.go @@ -252,38 +252,38 @@ func (r *Repository) Migrate(ctx context.Context) error { updated_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, - `CREATE TABLE IF NOT EXISTS room_treasure_configs ( + `CREATE TABLE IF NOT EXISTS room_rocket_configs ( app_code VARCHAR(32) NOT NULL, enabled TINYINT(1) NOT NULL DEFAULT 0, config_version BIGINT NOT NULL DEFAULT 1, - energy_source VARCHAR(32) NOT NULL, - open_delay_ms BIGINT NOT NULL, + fuel_source VARCHAR(32) NOT NULL, + launch_delay_ms BIGINT NOT NULL, broadcast_enabled TINYINT(1) NOT NULL DEFAULT 1, broadcast_scope VARCHAR(32) NOT NULL, broadcast_delay_ms BIGINT NOT NULL DEFAULT 0, reward_stack_policy VARCHAR(32) NOT NULL, levels_json JSON NOT NULL, - gift_energy_rules_json JSON NOT NULL, + gift_fuel_rules_json JSON NOT NULL, updated_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0, created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code), - KEY idx_room_treasure_enabled (app_code, enabled) + KEY idx_room_rocket_enabled (app_code, enabled) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `INSERT IGNORE INTO room_seat_configs (app_code, allowed_seat_counts, default_seat_count, created_at_ms, updated_at_ms) VALUES ('lalu', '[10,15,20,25,30]', 15, 0, 0)`, - `INSERT IGNORE INTO room_treasure_configs ( + `INSERT IGNORE INTO room_rocket_configs ( app_code, enabled, config_version, - energy_source, - open_delay_ms, + fuel_source, + launch_delay_ms, broadcast_enabled, broadcast_scope, broadcast_delay_ms, reward_stack_policy, levels_json, - gift_energy_rules_json, + gift_fuel_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms @@ -298,13 +298,11 @@ func (r *Repository) Migrate(ctx context.Context) error { 0, 'allow_stack', JSON_ARRAY( - JSON_OBJECT('level', 1, 'energyThreshold', 1000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 2, 'energyThreshold', 3000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 3, 'energyThreshold', 6000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 4, 'energyThreshold', 10000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 5, 'energyThreshold', 15000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 6, 'energyThreshold', 21000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), - JSON_OBJECT('level', 7, 'energyThreshold', 28000, 'coverUrl', '', 'animationUrl', '', 'openingAnimationUrl', '', 'openedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()) + JSON_OBJECT('level', 1, 'fuelThreshold', 1000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 2, 'fuelThreshold', 3000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 3, 'fuelThreshold', 6000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 4, 'fuelThreshold', 10000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()), + JSON_OBJECT('level', 5, 'fuelThreshold', 15000, 'coverUrl', '', 'animationUrl', '', 'launchAnimationUrl', '', 'launchedImageUrl', '', 'inRoomRewards', JSON_ARRAY(), 'top1Rewards', JSON_ARRAY(), 'igniterRewards', JSON_ARRAY()) ), JSON_ARRAY(), 0, @@ -321,7 +319,7 @@ func (r *Repository) Migrate(ctx context.Context) error { `ALTER TABLE room_follows MODIFY COLUMN app_code VARCHAR(32) NOT NULL`, `ALTER TABLE room_region_pins MODIFY COLUMN app_code VARCHAR(32) NOT NULL`, `ALTER TABLE room_seat_configs MODIFY COLUMN app_code VARCHAR(32) NOT NULL`, - `ALTER TABLE room_treasure_configs MODIFY COLUMN app_code VARCHAR(32) NOT NULL`, + `ALTER TABLE room_rocket_configs MODIFY COLUMN app_code VARCHAR(32) NOT NULL`, } for _, statement := range statements { @@ -936,18 +934,18 @@ func (r *Repository) UpsertRoomSeatConfig(ctx context.Context, config roomservic return err } -// GetRoomTreasureConfig 读取当前 App 的语音房宝箱配置。 -func (r *Repository) GetRoomTreasureConfig(ctx context.Context) (roomservice.RoomTreasureConfig, bool, error) { +// GetRoomRocketConfig 读取当前 App 的语音房火箭配置。 +func (r *Repository) GetRoomRocketConfig(ctx context.Context) (roomservice.RoomRocketConfig, bool, error) { row := r.db.QueryRowContext(ctx, - `SELECT app_code, enabled, config_version, energy_source, open_delay_ms, + `SELECT app_code, enabled, config_version, fuel_source, launch_delay_ms, broadcast_enabled, broadcast_scope, broadcast_delay_ms, reward_stack_policy, - levels_json, gift_energy_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms - FROM room_treasure_configs + levels_json, gift_fuel_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms + FROM room_rocket_configs WHERE app_code = ?`, appcode.FromContext(ctx), ) - var config roomservice.RoomTreasureConfig + var config roomservice.RoomRocketConfig var enabled int var broadcastEnabled int var rawLevels string @@ -956,8 +954,8 @@ func (r *Repository) GetRoomTreasureConfig(ctx context.Context) (roomservice.Roo &config.AppCode, &enabled, &config.ConfigVersion, - &config.EnergySource, - &config.OpenDelayMS, + &config.FuelSource, + &config.LaunchDelayMS, &broadcastEnabled, &config.BroadcastScope, &config.BroadcastDelayMS, @@ -969,30 +967,30 @@ func (r *Repository) GetRoomTreasureConfig(ctx context.Context) (roomservice.Roo &config.UpdatedAtMS, ); err != nil { if errors.Is(err, sql.ErrNoRows) { - return roomservice.RoomTreasureConfig{}, false, nil + return roomservice.RoomRocketConfig{}, false, nil } - return roomservice.RoomTreasureConfig{}, false, err + return roomservice.RoomRocketConfig{}, false, err } config.Enabled = enabled == 1 config.BroadcastEnabled = broadcastEnabled == 1 if err := json.Unmarshal([]byte(rawLevels), &config.Levels); err != nil { - return roomservice.RoomTreasureConfig{}, false, err + return roomservice.RoomRocketConfig{}, false, err } - if err := json.Unmarshal([]byte(rawRules), &config.GiftEnergyRules); err != nil { - return roomservice.RoomTreasureConfig{}, false, err + if err := json.Unmarshal([]byte(rawRules), &config.GiftFuelRules); err != nil { + return roomservice.RoomRocketConfig{}, false, err } return config, true, nil } -// UpsertRoomTreasureConfig 写入当前 App 的语音房宝箱配置。 -func (r *Repository) UpsertRoomTreasureConfig(ctx context.Context, config roomservice.RoomTreasureConfig) error { +// UpsertRoomRocketConfig 写入当前 App 的语音房火箭配置。 +func (r *Repository) UpsertRoomRocketConfig(ctx context.Context, config roomservice.RoomRocketConfig) error { appCode := normalizedRecordAppCode(ctx, config.AppCode) rawLevels, err := json.Marshal(config.Levels) if err != nil { return err } - rawRules, err := json.Marshal(config.GiftEnergyRules) + rawRules, err := json.Marshal(config.GiftFuelRules) if err != nil { return err } @@ -1005,29 +1003,29 @@ func (r *Repository) UpsertRoomTreasureConfig(ctx context.Context, config roomse createdAtMS = nowMS } _, err = r.db.ExecContext(ctx, - `INSERT INTO room_treasure_configs ( - app_code, enabled, config_version, energy_source, open_delay_ms, + `INSERT INTO room_rocket_configs ( + app_code, enabled, config_version, fuel_source, launch_delay_ms, broadcast_enabled, broadcast_scope, broadcast_delay_ms, reward_stack_policy, - levels_json, gift_energy_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms + levels_json, gift_fuel_rules_json, updated_by_admin_id, created_at_ms, updated_at_ms ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE enabled = VALUES(enabled), config_version = VALUES(config_version), - energy_source = VALUES(energy_source), - open_delay_ms = VALUES(open_delay_ms), + fuel_source = VALUES(fuel_source), + launch_delay_ms = VALUES(launch_delay_ms), broadcast_enabled = VALUES(broadcast_enabled), broadcast_scope = VALUES(broadcast_scope), broadcast_delay_ms = VALUES(broadcast_delay_ms), reward_stack_policy = VALUES(reward_stack_policy), levels_json = VALUES(levels_json), - gift_energy_rules_json = VALUES(gift_energy_rules_json), + gift_fuel_rules_json = VALUES(gift_fuel_rules_json), updated_by_admin_id = VALUES(updated_by_admin_id), updated_at_ms = VALUES(updated_at_ms)`, appCode, boolToInt(config.Enabled), config.ConfigVersion, - config.EnergySource, - config.OpenDelayMS, + config.FuelSource, + config.LaunchDelayMS, boolToInt(config.BroadcastEnabled), config.BroadcastScope, config.BroadcastDelayMS, diff --git a/services/room-service/internal/transport/grpc/server.go b/services/room-service/internal/transport/grpc/server.go index 8d5b85d1..ac9c39aa 100644 --- a/services/room-service/internal/transport/grpc/server.go +++ b/services/room-service/internal/transport/grpc/server.go @@ -167,9 +167,9 @@ func (s *Server) AdminDeleteRoom(ctx context.Context, req *roomv1.AdminDeleteRoo return mapServiceResult(s.svc.AdminDeleteRoom(ctx, req)) } -func (s *Server) AdminUpdateRoomTreasureConfig(ctx context.Context, req *roomv1.AdminUpdateRoomTreasureConfigRequest) (*roomv1.AdminUpdateRoomTreasureConfigResponse, error) { +func (s *Server) AdminUpdateRoomRocketConfig(ctx context.Context, req *roomv1.AdminUpdateRoomRocketConfigRequest) (*roomv1.AdminUpdateRoomRocketConfigResponse, error) { ctx = contextWithMetaApp(ctx, req.GetMeta()) - return mapServiceResult(s.svc.AdminUpdateRoomTreasureConfig(ctx, req)) + return mapServiceResult(s.svc.AdminUpdateRoomRocketConfig(ctx, req)) } func (s *Server) AdminUpdateRoomSeatConfig(ctx context.Context, req *roomv1.AdminUpdateRoomSeatConfigRequest) (*roomv1.AdminUpdateRoomSeatConfigResponse, error) { @@ -428,9 +428,9 @@ func (s *Server) AdminGetRoom(ctx context.Context, req *roomv1.AdminGetRoomReque return mapServiceResult(s.svc.AdminGetRoom(ctx, req)) } -func (s *Server) AdminGetRoomTreasureConfig(ctx context.Context, req *roomv1.AdminGetRoomTreasureConfigRequest) (*roomv1.AdminGetRoomTreasureConfigResponse, error) { +func (s *Server) AdminGetRoomRocketConfig(ctx context.Context, req *roomv1.AdminGetRoomRocketConfigRequest) (*roomv1.AdminGetRoomRocketConfigResponse, error) { ctx = contextWithMetaApp(ctx, req.GetMeta()) - return mapServiceResult(s.svc.AdminGetRoomTreasureConfig(ctx, req)) + return mapServiceResult(s.svc.AdminGetRoomRocketConfig(ctx, req)) } func (s *Server) AdminGetRoomSeatConfig(ctx context.Context, req *roomv1.AdminGetRoomSeatConfigRequest) (*roomv1.AdminGetRoomSeatConfigResponse, error) { @@ -500,16 +500,16 @@ func (s *Server) ListRoomBackgrounds(ctx context.Context, req *roomv1.ListRoomBa return mapServiceResult(s.svc.ListRoomBackgrounds(ctx, req)) } -// GetRoomTreasure 代理到房间宝箱只读查询。 -func (s *Server) GetRoomTreasure(ctx context.Context, req *roomv1.GetRoomTreasureRequest) (*roomv1.GetRoomTreasureResponse, error) { - // 宝箱查询不刷新 presence;当前进度仍以 Room Cell 快照和 UTC 日边界为准。 +// GetRoomRocket 代理到房间火箭只读查询。 +func (s *Server) GetRoomRocket(ctx context.Context, req *roomv1.GetRoomRocketRequest) (*roomv1.GetRoomRocketResponse, error) { + // 火箭查询不刷新 presence;当前进度仍以 Room Cell 快照和 UTC 日边界为准。 ctx = contextWithMetaApp(ctx, req.GetMeta()) - if resp, forwarded, err := forwardQuery(s, ctx, req.GetMeta().GetAppCode(), req.GetRoomId(), func(callCtx context.Context, client roomv1.RoomQueryServiceClient) (*roomv1.GetRoomTreasureResponse, error) { - return client.GetRoomTreasure(callCtx, req) + if resp, forwarded, err := forwardQuery(s, ctx, req.GetMeta().GetAppCode(), req.GetRoomId(), func(callCtx context.Context, client roomv1.RoomQueryServiceClient) (*roomv1.GetRoomRocketResponse, error) { + return client.GetRoomRocket(callCtx, req) }); forwarded { return resp, err } - return mapServiceResult(s.svc.GetRoomTreasure(ctx, req)) + return mapServiceResult(s.svc.GetRoomRocket(ctx, req)) } // ListRoomOnlineUsers 代理到房间在线用户分页读模型。 From 9001fce4b72147d371c6b0485a664d1885bbcff9 Mon Sep 17 00:00:00 2001 From: zhx Date: Fri, 5 Jun 2026 19:56:13 +0800 Subject: [PATCH 22/28] Configure room rocket launch messaging --- README.md | 10 +- api/proto/events/room/v1/events.pb.go | 13 +- api/proto/room/v1/room.pb.go | 2 +- api/proto/room/v1/room.proto | 2 +- docs/IM全局与区域广播架构.md | 38 +- docs/flutter对接/幸运礼物Flutter对接.md | 5 +- docs/flutter对接/礼物TabFlutter对接.md | 10 +- docs/flutter对接/语音房火箭Flutter对接.md | 802 +++++------------- docs/notice-service架构.md | 2 +- docs/定时任务服务架构.md | 6 +- docs/房间Outbox补偿开发.md | 16 +- docs/语音房功能清单.md | 2 +- docs/语音房火箭功能架构.md | 431 ++-------- pkg/rocketmqx/rocketmqx.go | 4 +- .../internal/integration/roomclient/client.go | 6 +- .../internal/modules/roomrocket/service.go | 10 +- .../modules/roomrocket/service_test.go | 10 +- ...ion.sql => 018_room_rocket_navigation.sql} | 0 .../internal/service/broadcast/service.go | 28 +- .../transport/http/roomapi/room_view.go | 54 +- .../room-service/configs/config.docker.yaml | 6 +- .../configs/config.tencent.example.yaml | 6 +- services/room-service/configs/config.yaml | 6 +- .../room-service/internal/config/config.go | 6 +- .../internal/config/config_test.go | 2 +- .../internal/integration/clients_grpc.go | 2 +- .../internal/integration/rocketmq_outbox.go | 2 +- .../internal/integration/tencent_im.go | 21 +- .../internal/room/service/gift.go | 4 +- .../internal/room/service/recovery.go | 22 +- .../internal/room/service/repository.go | 2 +- .../internal/room/service/room_rocket.go | 36 +- .../internal/room/service/room_rocket_test.go | 113 ++- .../room-service/internal/room/state/state.go | 2 +- 34 files changed, 556 insertions(+), 1125 deletions(-) rename server/admin/migrations/{018_room_treasure_navigation.sql => 018_room_rocket_navigation.sql} (100%) diff --git a/README.md b/README.md index e0aa3c94..59d27669 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ HY Voice Room 是语音房后端 monorepo。当前架构不再自研 IM 长连 核心边界: - `gateway-service` 是客户端 HTTP JSON 入口,负责鉴权、协议转换、签发腾讯云 IM UserSig,以及调用内部 gRPC 服务。 -- `room-service` 是房间业务状态 owner,负责 Room Cell、麦位、房间 presence、本地礼物榜、送礼落房间、语音房宝箱、snapshot、command log、outbox、Redis lease、RocketMQ room outbox relay,以及腾讯云 IM 群组/系统消息桥接。 +- `room-service` 是房间业务状态 owner,负责 Room Cell、麦位、房间 presence、本地礼物榜、送礼落房间、语音房火箭、snapshot、command log、outbox、Redis lease、RocketMQ room outbox relay,以及腾讯云 IM 群组/系统消息桥接。 - `wallet-service` 当前提供 `DebitGift` 送礼扣费语义,余额、流水和幂等记录落 MySQL;`room-service` 的 `SendGift` 同步调用它。 - `user-service` 当前承接登录、三方注册、密码、refresh session、用户主数据、默认短号和临时靓号基础能力。 - `activity-service` 当前承接每日任务、活动/系统消息基础能力和房间事件 consumer;可通过 room outbox direct gRPC 或 RocketMQ `hyapp_room_outbox` 独立 consumer group 消费房间事实。 @@ -143,7 +143,7 @@ Authorization: Bearer - `gateway-service` 创建房间时从 access token 取当前 `user_id` 写入 `RequestMeta.actor_user_id`;`room-service` 由该 actor 收敛 owner,外部 CreateRoom 请求体不接收 `owner_user_id`。 - `X-Request-ID`/`request_id` 由后端生成,只做链路追踪;写操作的 `command_id` 由前端按用户动作生成,用于服务端幂等。 - `room-service` 在 `CreateRoom` 成功后写 `room_outbox`,由 outbox worker 异步创建或补偿同名腾讯云 IM 群组。 -- `room-service` 在上下麦、禁言、踢人、送礼、宝箱进度和开箱等命令提交后只写房间状态、command log 和 outbox;腾讯云 IM 房间系统自定义消息由 outbox worker direct 投递,或由 IM bridge consumer 从 RocketMQ 消费后投递。 +- `room-service` 在上下麦、禁言、踢人、送礼、火箭进度和发射等命令提交后只写房间状态、command log 和 outbox;腾讯云 IM 房间系统自定义消息由 outbox worker direct 投递,或由 IM bridge consumer 从 RocketMQ 消费后投递。 - `notice-service` 消费钱包余额变更 outbox 和房间踢人 outbox,向单个用户发送 `wallet_notice`、`room_notice` 私有自定义消息;owner service 不直接调用腾讯云 IM 单聊。 - `gateway-service` 已提供 `/api/v1/tencent-im/callback`,支持腾讯云 IM 入群前和发言前回调,并分别回查 `VerifyRoomPresence` 和 `CheckSpeakPermission`。 @@ -183,7 +183,7 @@ docs/flutter对接/Flutter App 通知与钱包余额对接.md | Topic | Producer | Consumer Group | 用途 | | --- | --- | --- | --- | -| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-activity-room-outbox` | activity-service 消费 `RoomGiftSent`、`RoomTreasureCountdownStarted` 等房间事实 | +| `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-activity-room-outbox` | activity-service 消费 `RoomGiftSent`、`RoomRocketIgnited` 等房间事实 | | `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-notice-room-outbox` | notice-service 消费 `RoomUserKicked` 等私有通知事实 | | `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-room-im-bridge` | room-service IM bridge 消费房间群系统消息和群成员控制事实 | | `hyapp_room_outbox` | `hyapp-room-outbox-producer` | `hyapp-user-mictime-room-outbox` | user-service 消费 `RoomMicChanged` 并更新用户麦时读模型 | @@ -195,9 +195,9 @@ docs/flutter对接/Flutter App 通知与钱包余额对接.md | `hyapp_wallet_outbox` | `hyapp-wallet-outbox-producer` | `hyapp-notice-wallet-outbox` | notice-service 消费余额、账务等私有通知事实 | | `hyapp_wallet_outbox` | `hyapp-wallet-outbox-producer` | `hyapp-statistics-wallet-outbox` | statistics-service 消费 `WalletRechargeRecorded` 并更新充值聚合 | | `hyapp_game_outbox` | `hyapp-game-outbox-producer` | `hyapp-statistics-game-outbox` | statistics-service 消费 `GameOrderSettled` 并更新游戏聚合 | -| `hyapp_room_treasure_open` | `hyapp-room-treasure-open-producer` | `hyapp-room-treasure-open` | 宝箱倒计时到点唤醒 room-service 开箱命令 | +| `hyapp_room_rocket_launch` | `hyapp-room-rocket-launch-producer` | `hyapp-room-rocket-launch` | 火箭点火后到点唤醒 room-service 发射命令 | -RocketMQ 不拥有业务状态。`room_outbox`、`wallet_outbox`、`user_outbox`、`game_outbox` 仍是各 owner service MySQL 内的可靠事实源;MQ 发布失败时 outbox worker 退避重试,到达重试上限后进入死信。宝箱延迟消息只负责唤醒,到点后 room-service 会重新校验 `box_id`、等级、`open_at_ms`、状态和 UTC 重置边界。 +RocketMQ 不拥有业务状态。`room_outbox`、`wallet_outbox`、`user_outbox`、`game_outbox` 仍是各 owner service MySQL 内的可靠事实源;MQ 发布失败时 outbox worker 退避重试,到达重试上限后进入死信。火箭延迟消息只负责唤醒,到点后 room-service 会重新校验 `rocket_id`、等级、`launch_at_ms`、状态和 UTC 重置边界。 ## Storage Model diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index 02adbad7..d5b88b7a 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -1651,6 +1651,7 @@ type RoomRocketIgnited struct { CommandId string `protobuf:"bytes,11,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` RoomShortId string `protobuf:"bytes,12,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` RocketCoverUrl string `protobuf:"bytes,13,opt,name=rocket_cover_url,json=rocketCoverUrl,proto3" json:"rocket_cover_url,omitempty"` + ResetAtMs int64 `protobuf:"varint,14,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1776,6 +1777,13 @@ func (x *RoomRocketIgnited) GetRocketCoverUrl() string { return "" } +func (x *RoomRocketIgnited) GetResetAtMs() int64 { + if x != nil { + return x.ResetAtMs + } + return 0 +} + // RoomRocketLaunched 表达火箭已经发射,在线用户名单按发射瞬间 Room Cell presence 结算。 type RoomRocketLaunched struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2094,7 +2102,7 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "gift_count\x18\f \x01(\x05R\tgiftCount\x12\x1d\n" + "\n" + "command_id\x18\r \x01(\tR\tcommandId\x12*\n" + - "\x11visible_region_id\x18\x0e \x01(\x03R\x0fvisibleRegionId\"\xe2\x03\n" + + "\x11visible_region_id\x18\x0e \x01(\x03R\x0fvisibleRegionId\"\x82\x04\n" + "\x11RoomRocketIgnited\x12\x1b\n" + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + "\x05level\x18\x02 \x01(\x05R\x05level\x12!\n" + @@ -2112,7 +2120,8 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\n" + "command_id\x18\v \x01(\tR\tcommandId\x12\"\n" + "\rroom_short_id\x18\f \x01(\tR\vroomShortId\x12(\n" + - "\x10rocket_cover_url\x18\r \x01(\tR\x0erocketCoverUrl\"\xe6\x02\n" + + "\x10rocket_cover_url\x18\r \x01(\tR\x0erocketCoverUrl\x12\x1e\n" + + "\vreset_at_ms\x18\x0e \x01(\x03R\tresetAtMs\"\xe6\x02\n" + "\x12RoomRocketLaunched\x12\x1b\n" + "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + "\x05level\x18\x02 \x01(\x05R\x05level\x12\x1d\n" + diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 488289fe..86dccba6 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -935,7 +935,7 @@ func (x *RoomRocketLevel) GetIgniterRewards() []*RoomRocketRewardItem { return nil } -// RoomRocketRewardGrant 是一次火箭打开后给某个用户结算出的具体奖励。 +// RoomRocketRewardGrant 是一次火箭发射后给某个用户结算出的具体奖励。 type RoomRocketRewardGrant struct { state protoimpl.MessageState `protogen:"open.v1"` RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index 829764f2..997b7013 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -124,7 +124,7 @@ message RoomRocketLevel { repeated RoomRocketRewardItem igniter_rewards = 9; } -// RoomRocketRewardGrant 是一次火箭打开后给某个用户结算出的具体奖励。 +// RoomRocketRewardGrant 是一次火箭发射后给某个用户结算出的具体奖励。 message RoomRocketRewardGrant { string reward_role = 1; int64 user_id = 2; diff --git a/docs/IM全局与区域广播架构.md b/docs/IM全局与区域广播架构.md index 6505b9d9..2bcedf12 100644 --- a/docs/IM全局与区域广播架构.md +++ b/docs/IM全局与区域广播架构.md @@ -38,7 +38,7 @@ docs/房间Outbox补偿开发.md | 播报发送能力 | `activity-service` | 服务端向全局/区域播报群发送自定义消息 | | 旧区域群成员移除 | `activity-service` | 用户区域变化后,对旧区域群执行 `delete_group_member(user_id)` | | 贵重礼物播报触发 | `activity-service` consuming room outbox | 基于 `RoomGiftSent` 事实判断阈值并发区域播报 | -| 火箭倒计时播报触发 | `activity-service` consuming room outbox | 基于 `RoomRocketCountdownStarted` 事实按后台配置发区域或全局播报 | +| 火箭倒计时播报触发 | `activity-service` consuming room outbox | 基于 `RoomRocketIgnited` 事实按后台配置发区域或全局播报 | 本阶段不做: @@ -107,7 +107,7 @@ func Parse(groupID string) ParsedGroup | 红包资金事实 | `wallet-service` 或独立 red-packet domain | IM 只携带入口和展示字段 | | 客户端 IM 长连接 | Tencent IM SDK | 本仓库不自建 WebSocket | -`room-service` 只需要继续产出 `RoomGiftSent`、`RoomRocketCountdownStarted` 等 outbox 事实。贵重礼物和火箭倒计时是否需要区域/全局播报,由 `activity-service` 通过 direct gRPC 或 RocketMQ `hyapp_room_outbox` consumer group 消费后判断,这样不会把区域播报策略塞进 Room Cell 主链路。 +`room-service` 只需要继续产出 `RoomGiftSent`、`RoomRocketIgnited` 等 outbox 事实。贵重礼物和火箭倒计时是否需要区域/全局播报,由 `activity-service` 通过 direct gRPC 或 RocketMQ `hyapp_room_outbox` consumer group 消费后判断,这样不会把区域播报策略塞进 Room Cell 主链路。 ## Client Flow @@ -406,7 +406,7 @@ sequenceDiagram ## Room Rocket Broadcast -火箭燃料满进入倒计时时,Room Cell 写 `RoomRocketCountdownStarted` outbox。activity-service 消费该事实后按后台配置决定发区域播报还是全局播报;发射到点、奖励结算和火箭状态推进仍由 room-service 负责。 +火箭燃料满进入倒计时时,Room Cell 写 `RoomRocketIgnited` outbox。activity-service 消费该事实后按后台配置决定发区域播报还是全局播报;发射到点、奖励结算和火箭状态推进仍由 room-service 负责。 ```mermaid sequenceDiagram @@ -421,11 +421,12 @@ sequenceDiagram C->>G: POST /api/v1/rooms/gift/send G->>R: SendGift R->>W: DebitGift - W-->>R: receipt + heat/gift point - R->>R: add effective rocket energy - R->>R: status=countdown when threshold reached + W-->>R: receipt + heat_value + R->>R: add effective rocket fuel + R->>R: append pending_launch when threshold reached + R->>R: start next level immediately R-->>G: SendGiftResponse - R->>MQ: RoomRocketCountdownStarted + R->>MQ: RoomRocketIgnited MQ->>A: consume by hyapp-activity-room-outbox A->>IM: send_group_msg(region/global broadcast group) ``` @@ -434,15 +435,22 @@ sequenceDiagram ```json { - "event_id": "room_rocket:lalu_room_xxx:box_1", + "event_id": "room_rocket:lalu_room_xxx:rocket_1", "broadcast_type": "room_rocket", "scope": "region", "app_code": "lalu", "region_id": 1001, "room_id": "lalu_room_xxx", - "box_id": "box_1", - "level": 3, - "open_at_ms": 1770000000000, + "rocket_id": "rocket_1", + "rocket_level": 3, + "rocket_cover_url": "https://cdn.example/rocket-l3.png", + "launch_at_ms": 1770000000000, + "igniter": { + "user_id": "10001", + "short_id": "80001", + "nickname": "Alice", + "avatar": "https://cdn.example/avatar.png" + }, "action": { "type": "enter_room", "room_id": "lalu_room_xxx" @@ -450,7 +458,7 @@ sequenceDiagram } ``` -倒计时期间继续送礼不会累加到下一火箭,溢出燃料也不会跨级;这些规则由 room-service 在 `RoomRocketProgressChanged` 和 `RoomRocketCountdownStarted` 事实中表达,activity-service 不能自行推导火箭进度。 +当前等级满阈值后,room-service 立刻把该火箭加入 `pending_launches`,并把下一等级作为当前进度继续累计;单次送礼溢出的燃料作废,不顺延。activity-service 只按 `RoomRocketIgnited` 做飘屏,不自行推导火箭进度。 ## Red Packet Broadcast @@ -464,7 +472,7 @@ sequenceDiagram | 过期退款 | wallet/red-packet domain + cron | | IM 播报 | activity-service broadcast | -红包创建成功后,红包领域写 `RedPacketCreated` 事件,activity-service 转成区域/全局播报。客户端点击播报只打开红包入口,领取时必须调用后端接口,不能信任 IM payload 中的金额。 +红包创建成功后,红包领域写 `RedPacketCreated` 事件,activity-service 转成区域/全局播报。客户端点击播报只发射红包入口,领取时必须调用后端接口,不能信任 IM payload 中的金额。 ## App Code And Region Safety @@ -496,7 +504,7 @@ sequenceDiagram 5. `activity-service` 增加 broadcast group reconciler,启动时确保全局和 active 区域群。 6. `activity-service` 增加 `PublishRegionBroadcast/PublishGlobalBroadcast` 和 broadcast outbox。 7. 扩展 `RoomGiftSent` 事件字段,activity-service 消费后按阈值发 `super_gift` 区域播报。 -8. 消费 `RoomRocketCountdownStarted`,按后台配置发 `room_rocket` 区域或全局播报。 +8. 消费 `RoomRocketIgnited`,按后台配置发 `room_rocket` 区域或全局播报。 9. 红包领域落账务事实后,复用同一播报能力发送 `red_packet` 消息。 ## Test Expectations @@ -513,5 +521,5 @@ sequenceDiagram | group reconciler | 已存在群视为成功,失败可重试 | | broadcast outbox | 同一 `event_id` 幂等,失败后 retry | | super gift | 未达阈值不播报,达阈值发送到用户房间所在区域群 | -| room rocket | 火箭燃料满后只按 `RoomRocketCountdownStarted` 播报一次;区域/全局 scope 来自后台配置 | +| room rocket | 火箭燃料满后只按 `RoomRocketIgnited` 播报一次;区域/全局 scope 来自后台配置 | | red packet | IM payload 不影响领取接口的后端金额校验 | diff --git a/docs/flutter对接/幸运礼物Flutter对接.md b/docs/flutter对接/幸运礼物Flutter对接.md index d405ca71..b4c47373 100644 --- a/docs/flutter对接/幸运礼物Flutter对接.md +++ b/docs/flutter对接/幸运礼物Flutter对接.md @@ -115,7 +115,7 @@ Content-Type: application/json | `room_heat` | int64 | 送礼后的房间热度。 | | `gift_rank` | array | 当前房间礼物榜。 | | `room` | object | 房间快照。 | -| `treasure` | object | 房间宝箱状态。 | +| `rocket` | object | 房间火箭状态。 | | `lucky_gift` | object | 幸运礼物抽奖结果;普通礼物可为空。 | `lucky_gift` 返回字段: @@ -159,7 +159,7 @@ Content-Type: application/json "room_heat": 123456, "gift_rank": [], "room": {}, - "treasure": {}, + "rocket": {}, "lucky_gift": { "enabled": true, "draw_id": "lucky_draw_test", @@ -328,4 +328,3 @@ Content-Type: application/json | `reward_status=pending` / `granting` | 到账处理中;等待钱包通知、刷新余额或后端补偿。 | | `reward_status=failed` | 展示异常状态,记录 `request_id/draw_id/command_id` 方便排查。 | | HTTP 超时 | 保留原 `command_id` 重试,不生成新命令。 | - diff --git a/docs/flutter对接/礼物TabFlutter对接.md b/docs/flutter对接/礼物TabFlutter对接.md index 0b874510..8bb6c2f6 100644 --- a/docs/flutter对接/礼物TabFlutter对接.md +++ b/docs/flutter对接/礼物TabFlutter对接.md @@ -20,11 +20,11 @@ 1. 用户进入房间并完成 `JoinRoom`。 2. App 可在启动或进入房间前调用 `GET /api/v1/gift-tabs` 预加载 Tab 配置。 -3. 打开礼物 Tab 时调用 `GET /api/v1/rooms/{room_id}/gift-panel`。 +3. 发射礼物 Tab 时调用 `GET /api/v1/rooms/{room_id}/gift-panel`。 4. 用 `tabs` 渲染当前房间分类,用 `gifts` 渲染礼物网格,用 `recipients` 渲染收礼人。 5. 用户选择收礼人、礼物和数量。 6. 点击发送时生成稳定 `command_id`,调用 `POST /api/v1/rooms/gift/send`。 -7. 发送成功后用响应里的 `room_heat`、`gift_rank`、`treasure` 更新房间 UI;如果有 `lucky_gift` 且已入账,用 `coin_balance_after` 立即刷新金币余额。 +7. 发送成功后用响应里的 `room_heat`、`gift_rank`、`rocket` 更新房间 UI;如果有 `lucky_gift` 且已入账,用 `coin_balance_after` 立即刷新金币余额。 8. 监听房间 IM `room_gift_sent`,同步播放礼物动效。 9. 普通礼物和未中奖余额仍监听私有钱包通知或主动刷新余额,不本地扣减余额作为最终值。 @@ -202,7 +202,7 @@ X-App-Code: lalu | 字段 | 说明 | | --- | --- | -| `coin_balance` | 当前登录用户 COIN 可用余额快照。只用于打开面板时展示,最终余额仍以后续钱包事实为准。 | +| `coin_balance` | 当前登录用户 COIN 可用余额快照。只用于发射面板时展示,最终余额仍以后续钱包事实为准。 | | `recipients` | 当前房间可收礼人。当前主流程只启用 `target_type=user` 的单个用户。 | | `tabs` | 礼物分类。`key=all` 是全量分类;其他 tab 通常对应 `gift_type_code`。 | | `gifts` | 当前房间国家维度可用的 active 礼物列表。 | @@ -295,7 +295,7 @@ Content-Type: application/json } ], "room": {}, - "treasure": {}, + "rocket": {}, "lucky_gift": { "enabled": true, "draw_id": "lucky_draw_test", @@ -329,7 +329,7 @@ Content-Type: application/json | `room_heat` | 最新房间热度。 | | `gift_rank` | 最新房间礼物榜。 | | `room` | 房间快照,字段较大;App 可按已有房间快照解析逻辑局部更新。 | -| `treasure` | 房间宝箱状态;宝箱 UI 以该字段或宝箱 IM 事件更新。 | +| `rocket` | 房间火箭状态;火箭 UI 以该字段或火箭 IM 事件更新。 | | `lucky_gift` | 幸运礼物抽奖结果;普通礼物可为空。`reward_status=granted` 且中奖时,`coin_balance_after` 是当前用户返奖入账后的余额。 | 发送后处理: diff --git a/docs/flutter对接/语音房火箭Flutter对接.md b/docs/flutter对接/语音房火箭Flutter对接.md index 5d3f10fa..a211f3e4 100644 --- a/docs/flutter对接/语音房火箭Flutter对接.md +++ b/docs/flutter对接/语音房火箭Flutter对接.md @@ -1,611 +1,277 @@ -# 语音房火箭 Flutter 对接 +# 语音房火箭接口对接 -本文描述 Flutter App 对接语音房火箭所需的 HTTP 接口、请求参数、返回值、错误处理和腾讯云 IM 自定义消息 key。火箭进度、发射和发奖事实由 `room-service` Room Cell 持有;客户端只展示服务端返回或 IM 推送的状态,不能本地计算燃料、奖励或发射结果。 +## 规则 -## 基础约定 +- 火箭最高 5 级。 +- 房间送礼成功后,按礼物 `heat_value` 增加当前等级火箭燃料。 +- 当前等级满后立刻点火,并把该等级火箭放入 `pending_launches` 等待发射。 +- 点火后下一等级马上开始累计燃料。 +- 单次送礼超过当前等级阈值时,超过部分直接作废,不顺延到下一等级。 +- 发射延迟由后台 `launch_delay_ms` 配置。 +- 发射结算三类奖励:点火人、贡献第一、在房用户。在房用户按发射瞬间房间 presence 抽奖。 -本地开发地址: +## 获取火箭 -```text -http://127.0.0.1:13000 -``` - -业务接口统一响应 envelope: - -```json -{ - "code": "OK", - "message": "ok", - "request_id": "req_xxx", - "data": {} -} -``` - -| 字段 | 说明 | -| --- | --- | -| `code` | 成功固定 `OK`;失败为稳定错误码。 | -| `message` | 短错误文案,不用于客户端分支判断。 | -| `request_id` | 服务端链路追踪 ID;客户端日志要记录。 | -| `data` | 成功业务数据;失败时通常不存在。 | - -通用请求头: - -| Header | 必填 | 说明 | -| --- | --- | --- | -| `Authorization` | 是 | `Bearer `。 | -| `X-App-Code` | 否 | App 编码,默认 `lalu`;登录态接口最终以 token 内 app_code 为准。 | -| `Content-Type` | POST 必填 | `application/json`。 | - -所有 `*_ms` 都是 Unix epoch milliseconds。业务切日按 UTC,不按用户本地时区。 - -## 客户端流程 - -1. 用户成功 `JoinRoom` 后调用 `GET /api/v1/rooms/{room_id}/rocket` 初始化 7 级物料和当前进度。 -2. 用户送礼调用 `POST /api/v1/rooms/gift/send`;成功响应里的 `data.rocket` 可立即更新当前火箭状态。 -3. 房间内监听腾讯 IM 群 `TIMCustomElem.Ext=room_system_message`,处理火箭进度、倒计时、发射和发奖。 -4. App 全局或区域播报监听 `TIMCustomElem.Ext=im_broadcast` 且 `broadcast_type=room_rocket`。 -5. 任意 IM 丢失、字段解析失败、版本倒退或页面重进时,重新调用 `GET /api/v1/rooms/{room_id}/rocket` 纠正本地状态。 - -客户端必须用 `event_id` 去重,用 `room_version` 丢弃旧房间消息。 - -## 获取火箭信息 - -```http -GET /api/v1/rooms/{room_id}/rocket -Authorization: Bearer -X-App-Code: lalu -``` - -路径参数: - -| 参数 | 类型 | 必填 | 说明 | -| --- | --- | --- | --- | -| `room_id` | string | 是 | 当前语音房 ID,例如 `lalu_534d076a-7cbd-4b23-a297-0c10a3c2fa72`。 | - -成功响应: - -```json -{ - "code": "OK", - "message": "ok", - "request_id": "req_xxx", - "data": { - "enabled": true, - "levels": [ - { - "level": 1, - "energy_threshold": 1000, - "cover_url": "https://cdn.example/chest/lv1/cover.png", - "animation_url": "https://cdn.example/chest/lv1/idle.svga", - "opening_animation_url": "https://cdn.example/chest/lv1/opening.svga", - "opened_image_url": "https://cdn.example/chest/lv1/opened.png", - "in_room_rewards": [ - { - "reward_item_id": "lv1_in_room_1", - "resource_group_id": 1001, - "weight": 10000, - "display_name": "Gold Pack", - "icon_url": "https://cdn.example/reward/gold.png" - } - ], - "top1_rewards": [], - "igniter_rewards": [] - } - ], - "state": { - "current_level": 1, - "current_progress": 0, - "energy_threshold": 1000, - "status": "idle", - "reset_at_ms": 1779321600000, - "top1_user_id": "", - "igniter_user_id": "", - "box_id": "", - "config_version": 3, - "last_rewards": [] - }, - "broadcast_scope": "region", - "open_delay_ms": 30000, - "broadcast_delay_ms": 0, - "reward_stack_policy": "allow_stack", - "server_time_ms": 1779259000000 - } -} -``` - -`data` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `enabled` | bool | 火箭总开关。`false` 时客户端隐藏或置灰火箭入口。 | -| `levels` | array | 固定 7 个等级的物料、阈值和奖励池。 | -| `state` | object | 当前房间当前 UTC 日的火箭状态。 | -| `broadcast_scope` | string | `none`、`region`、`global`。 | -| `open_delay_ms` | int64 | 燃料满后到发射的倒计时配置。 | -| `broadcast_delay_ms` | int64 | 后台配置字段;当前房间事件会立即进入播报链路。 | -| `reward_stack_policy` | string | `allow_stack` 或 `priority_only`。 | -| `server_time_ms` | int64 | 服务端当前时间,倒计时要以它校准本地时钟偏差。 | - -`levels[]` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `level` | int32 | 等级,1 到 7。 | -| `energy_threshold` | int64 | 当前等级燃料满阈值。 | -| `cover_url` | string | 静态封面图。 | -| `animation_url` | string | 未发射/蓄能态动效。 | -| `opening_animation_url` | string | 发射动效。 | -| `opened_image_url` | string | 发射后展示图。 | -| `in_room_rewards` | array | 发射时仍在房用户的奖励候选展示。 | -| `top1_rewards` | array | 倒计时开始时贡献第一用户奖励候选展示。 | -| `igniter_rewards` | array | 点火人奖励候选展示。 | - -奖励候选字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `reward_item_id` | string | 后台配置的奖励项 ID。 | -| `resource_group_id` | int64 | 钱包资源组 ID。 | -| `weight` | int64 | 抽奖权重,只用于展示或调试,不参与客户端抽奖。 | -| `display_name` | string | 奖励展示名称。 | -| `icon_url` | string | 奖励图标。 | - -`state` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `current_level` | int32 | 当前等级,1 到 7。 | -| `current_progress` | int64 | 当前等级已累计有效燃料。 | -| `energy_threshold` | int64 | 当前等级阈值。 | -| `status` | string | 当前返回 `idle` 或 `countdown`。 | -| `countdown_started_at_ms` | int64 | 倒计时开始时间;非倒计时可为空或 0。 | -| `open_at_ms` | int64 | 预计发射时间;`status=countdown` 时有效。 | -| `opened_at_ms` | int64 | 最近一次发射时间。 | -| `reset_at_ms` | int64 | 下一个 UTC 0 点;到点后进度按新 UTC 日重置。 | -| `top1_user_id` | string | 倒计时开始时锁定的贡献第一;GET 接口中按字符串返回。 | -| `igniter_user_id` | string | 点火人;GET 接口中按字符串返回。 | -| `box_id` | string | 当前倒计时火箭或最近状态的单轮幂等 ID。 | -| `config_version` | int64 | 当前状态关联的后台配置版本。 | -| `last_rewards` | array | 最近一次发射发奖结果;客户端可用于展示发射结果兜底。 | - -`last_rewards[]` 字段: - -| 字段 | 类型 | 说明 | -| --- | --- | --- | -| `reward_role` | string | `in_room`、`top1`、`igniter`。 | -| `user_id` | string | 获奖用户 ID 字符串。 | -| `reward_item_id` | string | 奖励项 ID。 | -| `resource_group_id` | int64 | 资源组 ID。 | -| `display_name` | string | 奖励展示名称。 | -| `icon_url` | string | 奖励图标。 | -| `grant_id` | string | 钱包发放记录 ID。 | -| `status` | string | 当前成功发放为 `succeeded`。 | - -展示规则: - -- 进度条使用 `current_progress / energy_threshold`,并且最大显示 100%。 -- 倒计时使用 `open_at_ms - server_time_ms` 初始化,再用本地 timer 驱动。 -- 不要把送礼溢出燃料展示到下一等级;服务端规则是溢出作废。 -- 如果 `status=countdown`,继续送礼不会改变火箭进度、点火人、贡献第一或 `open_at_ms`。 - -## 送礼并更新火箭 - -```http -POST /api/v1/rooms/gift/send -Authorization: Bearer -X-App-Code: lalu -Content-Type: application/json -``` - -请求体: - -```json -{ - "room_id": "lalu_xxx", - "command_id": "cmd_send_gift_lalu_xxx_12345678_1779259000000", - "target_type": "user", - "target_user_ids": [12345678], - "gift_id": "rocket", - "gift_count": 1 -} -``` +地址:`GET /api/v1/rooms/{room_id}/rocket` 参数: -| 字段 | 类型 | 必填 | 说明 | +| 参数 | 位置 | 必填 | 说明 | | --- | --- | --- | --- | -| `room_id` | string | 是 | 当前房间 ID。 | -| `command_id` | string | 是 | 本次送礼动作幂等键;同一次 HTTP 重试必须复用。 | -| `target_type` | string | 否 | 当前只支持 `user`;为空按 `user` 处理。 | -| `target_user_ids` | int64[] | 是 | 收礼用户列表;`target_type=user` 时必须且只能 1 个。 | -| `target_user_id` | int64 | 否 | 旧客户端兼容字段;新客户端优先用 `target_user_ids`。 | -| `gift_id` | string | 是 | 礼物 ID。 | -| `gift_count` | int32 | 是 | 礼物数量,必须大于 0。 | +| `room_id` | path | 是 | 房间 ID | -成功响应核心字段: +返回值: -```json -{ - "code": "OK", - "message": "ok", - "request_id": "req_xxx", - "data": { - "result": { - "applied": true, - "room_version": 7, - "server_time_ms": 1779259502200 - }, - "billing_receipt_id": "bill_xxx", - "room_heat": 500, - "gift_rank": [ - { - "user_id": 12345678, - "score": 500, - "gift_value": 500, - "updated_at_ms": 1779259502104 - } - ], - "room": {}, - "rocket": { - "current_level": 2, - "current_progress": 200, - "energy_threshold": 200, - "status": "countdown", - "countdown_started_at_ms": 1779259502104, - "open_at_ms": 1779259512104, - "reset_at_ms": 1779321600000, - "top1_user_id": 12345678, - "igniter_user_id": 12345678, - "box_id": "room_rocket_box_xxx", - "config_version": 3 - } - } -} -``` +| 字段 | 说明 | +| --- | --- | +| `enabled` | 火箭是否开启 | +| `levels` | 1 到 5 级配置 | +| `levels[].fuel_threshold` | 等级燃料阈值 | +| `levels[].cover_url` | 火箭小封面图 | +| `levels[].animation_url` | 常态动效 | +| `levels[].launch_animation_url` | 发射动效 | +| `levels[].launched_image_url` | 发射后图 | +| `levels[].in_room_rewards` | 在房奖励候选 | +| `levels[].top1_rewards` | 贡献第一奖励候选 | +| `levels[].igniter_rewards` | 点火人奖励候选 | +| `state.current_level` | 当前正在累计的等级 | +| `state.current_fuel` | 当前等级已累计燃料 | +| `state.fuel_threshold` | 当前等级阈值 | +| `state.status` | `charging` 或 `completed` | +| `state.rocket_id` | 当前正在累计火箭 ID | +| `state.pending_launches` | 已点火待发射火箭列表 | +| `state.pending_launches[].rocket_id` | 待发射火箭 ID | +| `state.pending_launches[].level` | 待发射等级 | +| `state.pending_launches[].ignited_at_ms` | 点火 UTC 毫秒 | +| `state.pending_launches[].launch_at_ms` | 预计发射 UTC 毫秒 | +| `state.pending_launches[].top1_user_id` | 点火时锁定贡献第一 | +| `state.pending_launches[].igniter_user_id` | 点火人 | +| `state.pending_launches[].cover_url` | 小封面图 | +| `state.last_rewards` | 最近一次发射奖励结果 | +| `server_time_ms` | 服务端 UTC 毫秒 | -字段说明: +## 送礼 -| 字段 | 类型 | 说明 | +地址:`POST /api/v1/rooms/gift/send` + +参数: + +| 参数 | 必填 | 说明 | | --- | --- | --- | -| `data.result.applied` | bool | 命令是否产生新状态;同一 `command_id` 重试可能返回历史结果。 | -| `data.result.room_version` | int64 | 房间版本,用于和 IM 消息去重、排序。 | -| `data.billing_receipt_id` | string | 钱包扣费回执。 | -| `data.room_heat` | int64 | 送礼后的房间热度。 | -| `data.gift_rank` | array | 送礼后的本地贡献榜快照。 | -| `data.room` | object | 房间快照。 | -| `data.rocket` | object | 送礼后火箭状态;送礼人可立即用它刷新 UI。 | +| `room_id` | 是 | 房间 ID | +| `command_id` | 是 | 客户端本次送礼幂等 ID | +| `target_type` | 否 | 默认 `user` | +| `target_user_id` | 否 | 单收礼用户 ID | +| `target_user_ids` | 否 | 多收礼用户 ID | +| `gift_id` | 是 | 礼物 ID | +| `gift_count` | 是 | 礼物数量 | +| `pool_id` | 否 | 幸运礼物奖池 ID | -注意:`GET /rocket` 的用户 ID 字段按字符串返回,`POST /gift/send` 透出的 protobuf 状态里部分用户 ID 可能是数字。Flutter 侧建议用统一 helper 兼容 `String` 和 `num`。 +返回值: -```dart -String readId(dynamic value) { - if (value == null) return ''; - if (value is String) return value; - if (value is num) return value.toInt().toString(); - return ''; -} -``` - -幂等规则: - -| 场景 | 处理 | +| 字段 | 说明 | | --- | --- | -| HTTP 超时后重试同一次送礼 | 复用原 `command_id`。 | -| 用户点了第二次送礼按钮 | 生成新的 `command_id`。 | -| 同一个 `command_id` 换了礼物、数量或目标 | 服务端返回冲突错误。 | +| `result` | 命令提交结果 | +| `billing_receipt_id` | 钱包扣费回执 | +| `room_heat` | 最新房间热度 | +| `gift_rank` | 最新房间礼物榜 | +| `rocket` | 送礼后的火箭状态,字段同 `state` | +| `lucky_gift` | 本次送礼聚合幸运礼物结果 | +| `lucky_gifts` | 多目标送礼时每个目标的幸运礼物结果 | -## 错误处理 +## 后台配置 -失败响应: +地址:`GET /v1/admin/activity/room-rocket/config` -```json -{ - "code": "PERMISSION_DENIED", - "message": "permission denied", - "request_id": "req_xxx" -} -``` +参数:无 -通用错误: +返回值: -| HTTP | `code` | 场景 | Flutter 处理 | -| --- | --- | --- | --- | -| 400 | `INVALID_JSON` | 请求体不是合法 JSON。 | 修正客户端请求,不重试。 | -| 400 | `INVALID_ARGUMENT` | 缺字段、数量非法、room_id 格式非法、暂不支持的 `target_type`。 | 修正参数,不自动重试。 | -| 401 | `UNAUTHORIZED` | token 缺失、过期或无效。 | 走登录刷新或重新登录。 | -| 403 | `PROFILE_REQUIRED` | 用户资料未完成。 | 跳转资料补全流程。 | -| 403 | `PERMISSION_DENIED` | 不在房间、被 ban、无权限读取或操作。 | 退出房间页或刷新房间状态。 | -| 404 | `NOT_FOUND` | 房间不存在、送礼人不在房、收礼人不在房、礼物不可用。 | 刷新房间状态;礼物不可用时刷新礼物面板。 | -| 409 | `ROOM_CLOSED` | 房间已关闭。 | 退出房间页并刷新列表。 | -| 409 | `CONFLICT` | 状态或唯一约束冲突。 | 刷新后重试。 | -| 409 | `IDEMPOTENCY_CONFLICT` | `command_id` 复用但请求内容不同。 | 新用户动作生成新 `command_id`;重试旧动作必须保持原请求体。 | -| 409 | `INSUFFICIENT_BALANCE` | 钱包余额不足。 | 弹充值/余额不足提示。 | -| 409 | `LEDGER_CONFLICT` | 钱包并发账本冲突。 | 可短延迟重试一次,仍失败则刷新余额。 | -| 502 | `UPSTREAM_ERROR` | room/wallet 等依赖暂不可用。 | 提示稍后重试,可保留原 `command_id` 重试同一次送礼。 | -| 500 | `INTERNAL_ERROR` | 服务端内部错误。 | 提示失败并记录 `request_id`。 | - -火箭相关额外规则: - -- 获取火箭信息要求当前用户仍在房间业务 presence 内;离房后调用会返回 `PERMISSION_DENIED` 或 `NOT_FOUND`。 -- 火箭关闭时,`GET /rocket` 仍可能返回 `enabled=false` 和 7 级配置;客户端不展示进度入口即可。 -- 发奖自动完成,没有 App 领取接口;客户端不要补发或重复调用钱包接口。 - -## 房间群 IM 消息 - -房间内火箭进度、倒计时、发射和发奖通过腾讯云 IM 房间群 `TIMCustomElem` 投递。 - -| 字段 | 值 | +| 字段 | 说明 | | --- | --- | -| `MsgType` | `TIMCustomElem` | -| `MsgContent.Ext` | `room_system_message` | -| `MsgContent.Desc` | 等于 `Data.event_type` | -| `MsgContent.Data` | JSON 字符串 | -| `CloudCustomData` | 与 `MsgContent.Data` 相同的 JSON 字符串 | +| `enabled` | 是否开启 | +| `fuelSource` | 固定为 `heat_value` | +| `launchDelayMs` | 点火后延迟发射毫秒 | +| `broadcastEnabled` | 是否发区域或全局飘屏 | +| `broadcastScope` | `region`、`global`、`none` | +| `rewardStackPolicy` | `allow_stack` 或 `priority_only` | +| `levels` | 5 级配置 | +| `giftFuelRules` | 礼物燃料规则 | -`Data` 外层结构: +地址:`PUT /v1/admin/activity/room-rocket/config` -```json -{ - "event_id": "evt_xxx", - "room_id": "lalu_xxx", - "event_type": "room_rocket_progress_changed", - "actor_user_id": 12345678, - "target_user_id": 0, - "room_version": 8, - "attributes": { - "box_id": "room_rocket_box_xxx" - } -} -``` +参数: -通用字段: - -| 字段 | 类型 | 说明 | +| 参数 | 必填 | 说明 | | --- | --- | --- | -| `event_id` | string | IM 去重键。 | -| `room_id` | string | 房间 ID。 | -| `event_type` | string | 事件类型,见下表。 | -| `actor_user_id` | int64 | 触发用户;倒计时/发射通常为点火人。 | -| `target_user_id` | int64 | 目标用户;倒计时/发射通常为 top1。 | -| `room_version` | int64 | 房间版本,本地版本更高时丢弃旧消息。 | -| `attributes` | map | 业务字段;值全部按字符串传输,Flutter 侧按需转 int/bool/JSON。 | +| `enabled` | 是 | 是否开启 | +| `fuelSource` | 是 | 固定传 `heat_value` | +| `launchDelayMs` | 是 | 点火后延迟发射毫秒 | +| `broadcastEnabled` | 是 | 是否发飘屏 | +| `broadcastScope` | 是 | `region`、`global`、`none` | +| `broadcastDelayMs` | 是 | 保留字段,当前点火后立即入 outbox | +| `rewardStackPolicy` | 是 | `allow_stack` 或 `priority_only` | +| `levels` | 是 | 必须 5 级 | +| `levels[].fuelThreshold` | 是 | 等级阈值 | +| `levels[].coverUrl` | 否 | 小封面图 | +| `levels[].animationUrl` | 否 | 常态动效 | +| `levels[].launchAnimationUrl` | 否 | 发射动效 | +| `levels[].launchedImageUrl` | 否 | 发射后图 | +| `levels[].inRoomRewards` | 否 | 在房奖励池 | +| `levels[].top1Rewards` | 否 | 贡献第一奖励池 | +| `levels[].igniterRewards` | 否 | 点火人奖励池 | +| `giftFuelRules[].giftId` | 否 | 指定礼物 ID | +| `giftFuelRules[].giftTypeCode` | 否 | 指定礼物类型 | +| `giftFuelRules[].multiplierPpm` | 否 | 燃料倍率,1 倍为 `1000000` | +| `giftFuelRules[].fixedFuel` | 否 | 固定燃料 | +| `giftFuelRules[].excluded` | 否 | 是否排除该礼物 | -火箭房间群事件: +返回值:同获取后台配置。 -| `event_type` | `Desc` | 用途 | -| --- | --- | --- | -| `room_rocket_progress_changed` | `room_rocket_progress_changed` | 有效火箭燃料增加。 | -| `room_rocket_countdown_started` | `room_rocket_countdown_started` | 当前等级燃料满,进入倒计时。 | -| `room_rocket_opened` | `room_rocket_opened` | 火箭已打开,包含公开奖励摘要。 | -| `room_rocket_reward_granted` | `room_rocket_reward_granted` | 发奖结果事件,包含奖励列表。 | +## 房间 IM -### room_rocket_progress_changed +来源:腾讯云 IM 房间群。 -示例: +基础字段: -```json -{ - "event_id": "evt_progress", - "room_id": "lalu_xxx", - "event_type": "room_rocket_progress_changed", - "actor_user_id": 12345678, - "room_version": 6, - "attributes": { - "box_id": "room_rocket_box_xxx", - "level": "2", - "added_energy": "300", - "effective_added_energy": "200", - "overflow_energy": "100", - "current_progress": "200", - "energy_threshold": "200", - "status": "countdown", - "reset_at_ms": "1779321600000", - "gift_id": "rocket", - "gift_count": "3", - "command_id": "cmd_send_gift_xxx" - } -} -``` - -处理: - -- 更新当前等级进度为 `current_progress`。 -- `effective_added_energy` 是本次实际计入火箭的燃料。 -- `overflow_energy` 是作废燃料,不能加到下一等级。 -- 如果 `status=countdown`,立即切换倒计时态,等待 `room_rocket_countdown_started` 补齐 `open_at_ms`;如该消息丢失,调用 GET 兜底。 - -### room_rocket_countdown_started - -示例: - -```json -{ - "event_id": "evt_countdown", - "room_id": "lalu_xxx", - "event_type": "room_rocket_countdown_started", - "actor_user_id": 12345678, - "target_user_id": 12345678, - "room_version": 6, - "attributes": { - "box_id": "room_rocket_box_xxx", - "level": "2", - "current_progress": "200", - "energy_threshold": "200", - "countdown_start_ms": "1779259502104", - "open_at_ms": "1779259512104", - "broadcast_scope": "region", - "visible_region_id": "1001", - "top1_user_id": "12345678", - "igniter_user_id": "12345678", - "command_id": "cmd_send_gift_xxx" - } -} -``` - -处理: - -- 按 `open_at_ms` 展示发射倒计时。 -- `top1_user_id` 和 `igniter_user_id` 在此刻锁定;后续离房或下线也不影响这两类奖励发放。 -- 倒计时期间再收到普通 `room_gift_sent`,只更新礼物表现和热度,不改变火箭倒计时。 - -注意:房间群 IM 字段名是 `countdown_start_ms`,HTTP state 字段名是 `countdown_started_at_ms`。 - -### room_rocket_opened - -示例: - -```json -{ - "event_id": "evt_opened", - "room_id": "lalu_xxx", - "event_type": "room_rocket_opened", - "actor_user_id": 12345678, - "target_user_id": 12345678, - "room_version": 8, - "attributes": { - "box_id": "room_rocket_box_xxx", - "level": "2", - "next_level": "3", - "opened_at_ms": "1779259512668", - "reset_at_ms": "1779321600000", - "top1_user_id": "12345678", - "igniter_user_id": "12345678", - "rewards_json": "[{\"reward_role\":\"in_room\",\"user_id\":12345678,\"reward_item_id\":\"lv2_in_room_1\",\"resource_group_id\":1001,\"display_name\":\"Gold Pack\",\"icon_url\":\"https://cdn.example/reward/gold.png\",\"grant_id\":\"rgr_xxx\",\"status\":\"succeeded\"}]" - } -} -``` - -处理: - -- 播放当前等级 `opening_animation_url`,再展示 `opened_image_url` 或奖励弹窗。 -- 解析 `rewards_json` 得到奖励列表;如果解析失败,调用 GET 获取 `state.last_rewards`。 -- 本地状态进入 `next_level`,进度归 0,状态归 `idle`。 - -### room_rocket_reward_granted - -示例: - -```json -{ - "event_id": "evt_reward", - "room_id": "lalu_xxx", - "event_type": "room_rocket_reward_granted", - "room_version": 8, - "attributes": { - "box_id": "room_rocket_box_xxx", - "level": "2", - "rewards_json": "[{\"reward_role\":\"top1\",\"user_id\":12345678,\"reward_item_id\":\"lv2_top1_1\",\"resource_group_id\":1002,\"display_name\":\"Top Reward\",\"icon_url\":\"https://cdn.example/reward/top.png\",\"grant_id\":\"rgr_xxx\",\"status\":\"succeeded\"}]" - } -} -``` - -处理: - -- 解析 `rewards_json`。 -- 当前登录用户在奖励列表中时,展示“获得奖励”提示。 -- 同一用户可能同时命中 `in_room`、`top1`、`igniter`,是否叠加由 `reward_stack_policy` 决定;客户端按服务端发下来的列表展示。 - -当前没有单独的 C2C 火箭中奖私信,也没有 App 消息 Tab 火箭入箱消息。后续如新增私有通知,应以新的 C2C `Ext` 文档为准,不复用房间群消息假装私信。 - -## 区域/全局播报 IM - -燃料满进入倒计时后,如果后台配置允许播报,`activity-service` 会向区域或全局播报群发送 `TIMCustomElem`。 - -| 字段 | 值 | +| 字段 | 说明 | | --- | --- | -| `MsgType` | `TIMCustomElem` | -| `MsgContent.Ext` | `im_broadcast` | -| `MsgContent.Desc` | `room_rocket` | -| `MsgContent.Data` | JSON 字符串 | -| `CloudCustomData` | 与 `MsgContent.Data` 相同的 JSON 字符串 | +| `TIMCustomElem.Ext` | `room_system_message` | +| `event_type` | 事件类型 | +| `room_id` | 房间 ID | +| `event_id` | 消息 ID | +| `occurred_at_ms` | 服务端 UTC 毫秒 | -`Data` 示例: +### room_rocket_fuel_changed -```json -{ - "event_id": "room_rocket_broadcast:lalu_xxx:room_rocket_box_xxx", - "broadcast_type": "room_rocket", - "scope": "region", - "app_code": "lalu", - "region_id": 1001, - "room_id": "lalu_xxx", - "box_id": "room_rocket_box_xxx", - "level": 2, - "open_at_ms": 1779259512104, - "top1_user_id": 12345678, - "igniter_user_id": 12345678, - "sent_at_ms": 1779259502200, - "room_version": 6, - "source_event_id": "evt_countdown", - "current_progress": 200, - "energy_threshold": 200, - "countdown_started_at_ms": 1779259502104, - "action": { - "type": "enter_room", - "room_id": "lalu_xxx" - } -} -``` +用途:刷新当前等级进度。 -处理: +字段: -- `broadcast_type=room_rocket` 时展示火箭倒计时播报。 -- 点击播报按 `action.type=enter_room` 跳转或进房。 -- `scope=region` 表示区域播报群;`scope=global` 表示全局播报群。 -- 播报只负责引导和展示,不代替房间内火箭状态;进房后仍调用 GET 初始化。 - -## 普通送礼房间 IM - -送礼成功还会产生普通房间群消息: - -| 字段 | 值 | +| 字段 | 说明 | | --- | --- | -| `MsgContent.Ext` | `room_system_message` | -| `MsgContent.Desc` | `room_gift_sent` | -| `Data.event_type` | `room_gift_sent` | +| `rocket_id` | 当前累计火箭 ID | +| `level` | 当前累计等级 | +| `added_fuel` | 本次理论燃料 | +| `effective_added_fuel` | 本次实际计入燃料 | +| `overflow_fuel` | 本次作废燃料 | +| `current_fuel` | 当前等级燃料 | +| `fuel_threshold` | 当前等级阈值 | +| `status` | `charging` 或本次满阈值时的 `ignited` | +| `gift_id` | 礼物 ID | +| `gift_count` | 礼物数量 | -火箭 UI 不应该只靠 `room_gift_sent` 推算燃料;燃料以 `room_rocket_progress_changed`、`room_rocket_countdown_started`、`POST /gift/send.data.rocket` 或 GET 结果为准。 +### room_rocket_ignited -## Flutter 解析建议 +用途:当前等级满阈值,加入待发射队列;客户端立即把下一等级作为当前进度。 -IM `attributes` 的值都是字符串,建议统一封装解析: +字段: -```dart -int readInt(dynamic value, [int fallback = 0]) { - if (value == null) return fallback; - if (value is num) return value.toInt(); - if (value is String) return int.tryParse(value) ?? fallback; - return fallback; -} - -String readString(dynamic value) { - if (value == null) return ''; - if (value is String) return value; - if (value is num) return value.toInt().toString(); - return value.toString(); -} - -List> readRewardsJson(dynamic value) { - final raw = readString(value); - if (raw.isEmpty) return const []; - final decoded = jsonDecode(raw); - if (decoded is! List) return const []; - return decoded.whereType().map((item) { - return item.map((key, val) => MapEntry(key.toString(), val)); - }).toList(); -} -``` - -推荐本地状态更新策略: - -| 输入 | 处理 | +| 字段 | 说明 | | --- | --- | -| `GET /rocket` | 覆盖本地完整火箭状态和 7 级物料。 | -| `POST /gift/send.data.rocket` | 送礼人立即刷新当前状态。 | -| `room_rocket_progress_changed` | 同房间、版本不旧时更新进度。 | -| `room_rocket_countdown_started` | 切换倒计时,并锁定 top1/点火人展示。 | -| `room_rocket_opened` | 播放发射动效,状态切到下一等级 idle。 | -| `room_rocket_reward_granted` | 展示当前用户中奖提示;按 `event_id` 去重。 | -| `im_broadcast + room_rocket` | 展示区域/全局播报入口,不直接改当前房间状态。 | +| `rocket_id` | 待发射火箭 ID | +| `level` | 待发射等级 | +| `rocket_level` | 同 `level` | +| `room_short_id` | 房间短号 | +| `rocket_cover_url` | 小封面图 | +| `current_fuel` | 满阈值燃料 | +| `fuel_threshold` | 满阈值 | +| `ignited_at_ms` | 点火时间 | +| `launch_at_ms` | 预计发射时间 | +| `reset_at_ms` | UTC 日重置时间 | +| `top1_user_id` | 点火时贡献第一 | +| `igniter_user_id` | 点火人 | -如果客户端发现本地状态和服务端事件无法合并,例如当前 `box_id` 不一致、`level` 倒退、`room_version` 缺失,直接调用 `GET /api/v1/rooms/{room_id}/rocket` 重新同步。 +### room_rocket_launched + +用途:火箭已到点发射,客户端播放发射表现。 + +字段: + +| 字段 | 说明 | +| --- | --- | +| `rocket_id` | 已发射火箭 ID | +| `level` | 已发射等级 | +| `next_level` | 当前正在累计等级 | +| `launched_at_ms` | 发射时间 | +| `top1_user_id` | 贡献第一 | +| `igniter_user_id` | 点火人 | +| `rewards_json` | 奖励摘要 | + +## 区域或全局飘屏 IM + +来源:腾讯云 IM 区域群或全局群。 + +基础字段: + +| 字段 | 说明 | +| --- | --- | +| `TIMCustomElem.Ext` | `im_broadcast` | +| `TIMCustomElem.Desc` | `room_rocket` | + +消息体: + +| 字段 | 说明 | +| --- | --- | +| `broadcast_type` | `room_rocket` | +| `scope` | `region` 或 `global` | +| `room_id` | 房间 ID | +| `room_short_id` | 房间短号 | +| `rocket_id` | 待发射火箭 ID | +| `rocket_level` | 火箭等级 | +| `rocket_cover_url` | 小封面图 | +| `launch_at_ms` | 预计发射时间 | +| `igniter.user_id` | 点火人用户 ID | +| `igniter.short_id` | 点火人短 ID | +| `igniter.nickname` | 点火人昵称 | +| `igniter.avatar` | 点火人头像 | + +## 奖励房间 IM + +来源:腾讯云 IM 房间群。 + +基础字段: + +| 字段 | 说明 | +| --- | --- | +| `TIMCustomElem.Ext` | `im_broadcast` | +| `TIMCustomElem.Desc` | `room_rocket_reward_granted` | + +消息体: + +| 字段 | 说明 | +| --- | --- | +| `broadcast_type` | `room_rocket_reward_granted` | +| `scope` | `room` | +| `room_id` | 房间 ID | +| `rocket_id` | 已发射火箭 ID | +| `rocket_level` | 已发射等级 | +| `rewards` | 本次所有获得奖励的人 | +| `rewards[].reward_role` | `in_room`、`top1`、`igniter` | +| `rewards[].user.user_id` | 用户 ID | +| `rewards[].user.short_id` | 用户短 ID | +| `rewards[].user.nickname` | 用户昵称 | +| `rewards[].user.avatar` | 用户头像 | +| `rewards[].resource_group_id` | 资源组 ID | +| `rewards[].display_name` | 奖励展示名 | +| `rewards[].icon_url` | 奖励图标 | +| `rewards[].grant_id` | 发奖回执 | +| `rewards[].status` | 发奖状态 | + +## 客户端处理 + +- 进房先调 `GET /api/v1/rooms/{room_id}/rocket`。 +- 送礼成功优先用返回的 `rocket` 刷新状态。 +- 收到 `room_rocket_fuel_changed` 刷新进度。 +- 收到 `room_rocket_ignited` 把该火箭加入待发射队列,并显示下一等级当前进度。 +- 收到 `room_rocket_launched` 播放发射表现。 +- 收到 `room_rocket_reward_granted` 展示本次所有中奖人和奖励。 +- 如果 IM 丢失或乱序,用 GET 接口兜底。 +- 不要用普通 `room_gift_sent` 自行推算火箭燃料。 + +## 高频和延迟处理 + +- 送礼只同步写 Room Cell 状态和 room outbox,不同步请求腾讯 IM。 +- 房间进度 IM 走 room outbox 补偿投递,失败会重试。 +- 点火后延迟发射通过 RocketMQ delayed wakeup 唤醒;到点后 room-service 重新校验 `rocket_id`、`level`、`launch_at_ms`、UTC 重置边界。 +- 奖励 IM 一次性包含所有中奖人,避免按用户逐条发 IM。 diff --git a/docs/notice-service架构.md b/docs/notice-service架构.md index 506acedf..27051f19 100644 --- a/docs/notice-service架构.md +++ b/docs/notice-service架构.md @@ -267,7 +267,7 @@ rocketmq: 1. 钱包余额通知:已按 `walletnotice` 模块落地。 2. 房间踢人私有通知:已按 `roomnotice` 模块落地,只消费 `RoomUserKicked` 的 C2C 通知。 3. 幸运礼物中奖:仍由 `wallet-service` 写余额 outbox;notice 不需要新增特殊账务逻辑,只要客户端按 `balance_version` 更新。 -4. 语音房宝箱私有通知:如产品需要私聊提醒,可在 `roomnotice` 中消费 `RoomTreasureRewardGranted` 或由活动/系统消息模块转发;奖励入账事实仍由 room-service 调 wallet 完成,notice 只投通知。 +4. 语音房火箭私有通知:如产品需要私聊提醒,可在 `roomnotice` 中消费 `RoomRocketRewardGranted` 或由活动/系统消息模块转发;奖励入账事实仍由 room-service 调 wallet 完成,notice 只投通知。 5. 活动/系统私有通知:新增 `activitynotice` 模块,读取 activity outbox,复用 `notice_delivery_events` 或新增同语义位点表。 6. 站内 inbox:新增 inbox 模块,写 notice-service 自己的 inbox 表,再按客户端分页接口读取。 7. Push:新增 push 模块,和 IM 投递使用不同 `channel`,独立重试和死信。 diff --git a/docs/定时任务服务架构.md b/docs/定时任务服务架构.md index 076661d7..feae2e68 100644 --- a/docs/定时任务服务架构.md +++ b/docs/定时任务服务架构.md @@ -18,7 +18,7 @@ | `room-service` | stale presence cleanup | `services/room-service/internal/room/service/presence.go` | 留在 `room-service` | | `room-service` | mic publish timeout cleanup | `services/room-service/internal/room/service/mic_publish_timeout.go` | 留在 `room-service` | | `room-service` | room outbox relay to direct publishers / RocketMQ | `services/room-service/internal/room/service/outbox_worker.go` | 留在 `room-service` 或后续拆 `room-worker`,不进通用 cron | -| `room-service` | room rocket delayed open wakeup | `services/room-service/internal/room/service/room_rocket.go`、`services/room-service/internal/room/service/room_rocket_mq.go` | 留在 `room-service`;RocketMQ 只唤醒,到点后仍走 Room Cell 命令链路 | +| `room-service` | room rocket delayed launch wakeup | `services/room-service/internal/room/service/room_rocket.go`、`services/room-service/internal/room/service/room_rocket_mq.go` | 留在 `room-service`;RocketMQ 只唤醒,到点后仍走 Room Cell 命令链路 | | `user-service` | region rebuild task | `UserCronService.ProcessRegionRebuildBatch` | 已迁移到 cron-service 调度,旧内置 ticker 已删除 | | `user-service` | login IP risk job | `UserCronService.ProcessLoginIPRiskBatch` | 已迁移到 cron-service 调度,旧内置 ticker 已删除 | | `user-service` | invite recharge wallet outbox consumer | `services/user-service/internal/service/invite/service.go` | 先不迁,需补 durable cursor 或事件总线 | @@ -95,7 +95,7 @@ graph LR | Room Cell stale presence cleanup | 依赖本节点已装载 Room Cell 和 Redis lease,必须由 `room-service` owner 执行命令链路 | | Mic publish timeout cleanup | 必须对当前 Room Cell 状态做二次校验并执行 `MicDown`,不能让 cron 直接清麦 | | room outbox relay | 这是 room-service 的事件投递补偿,不是通用定时任务;需要和 direct publisher、RocketMQ 发布、outbox 状态语义绑定 | -| room rocket open timer | 火箭状态属于 Room Cell;延迟消息只负责唤醒,发射必须由 room-service 重新校验 `box_id/open_at_ms/UTC reset` 后执行命令 | +| room rocket launch timer | 火箭状态属于 Room Cell;延迟消息只负责唤醒,发射必须由 room-service 重新校验 `rocket_id/launch_at_ms/UTC reset` 后执行命令 | | wallet ledger transaction | 金币、钻石、积分、余额的加减和冻结必须在 `wallet-service` 事务内完成 | | wallet outbox publish | 属于 wallet-service outbox relay 或 MQ 投递,不应该由通用 cron 直接扫表改状态 | | invite recharge outbox consumer | 当前使用 in-memory cursor 扫 wallet outbox,迁移前必须先做 durable offset 或正式事件总线 | @@ -269,7 +269,7 @@ cron-service 可以直接开启多个实例;调度层通过 `cron_task_leases` - activity room outbox consumer。 - notice room outbox consumer。 - room IM bridge MQ consumer。 -- room rocket delayed open consumer。 +- room rocket delayed launch consumer。 这些需要的是事件消费基础设施:RocketMQ、Redis Stream、或 MySQL durable offset。cron-service 不能用“每隔几秒从头扫 outbox”的方式替代事件消费者。即使某些消费者内部有低频扫描补偿,也必须留在业务 owner service 中,因为它们需要理解 outbox 状态、消费幂等和领域状态校验。 diff --git a/docs/房间Outbox补偿开发.md b/docs/房间Outbox补偿开发.md index d76fff6c..779d4d95 100644 --- a/docs/房间Outbox补偿开发.md +++ b/docs/房间Outbox补偿开发.md @@ -37,7 +37,7 @@ gateway -> room-service command outbox worker -> claim pending/retryable rows - -> if RoomRocketCountdownStarted, schedule rocket open delayed wakeup when configured + -> if RoomRocketIgnited, schedule rocket launch delayed wakeup when configured -> publish by mode: direct: Tencent IM publisher + activity gRPC publisher mq: RocketMQ room_outbox publisher @@ -78,9 +78,9 @@ outbox worker | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-activity-room-outbox` | activity-service 消费房间事实,做活动、播报、系统消息等后续处理 | | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-notice-room-outbox` | notice-service 消费私有通知相关事实,例如 `RoomUserKicked` | | `hyapp_room_outbox` | `room-service` outbox worker | `hyapp-room-im-bridge` | room-service IM bridge 消费房间群系统消息和群成员控制事实 | -| `hyapp_room_rocket_open` | `room-service` rocket scheduler | `hyapp-room-rocket-open` | 火箭倒计时到点唤醒 Room Cell 发射命令 | +| `hyapp_room_rocket_launch` | `room-service` rocket scheduler | `hyapp-room-rocket-open` | 火箭倒计时到点唤醒 Room Cell 发射命令 | -`hyapp_room_rocket_open` 不是业务状态源。消息只携带 `app_code、room_id、box_id、level、open_at_ms、command_id` 等唤醒参数;真正能否发射仍由 room-service 加载 Room Cell 后校验当前火箭状态、等级、`box_id`、`open_at_ms` 和 UTC 重置边界。 +`hyapp_room_rocket_launch` 不是业务状态源。消息只携带 `app_code、room_id、rocket_id、level、launch_at_ms、command_id` 等唤醒参数;真正能否发射仍由 room-service 加载 Room Cell 后校验当前火箭状态、等级、`rocket_id`、`launch_at_ms` 和 UTC 重置边界。 ## 配置 @@ -103,9 +103,9 @@ rocketmq: tencent_im_consumer_enabled: false tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - rocket_open: + rocket_launch: enabled: false - topic: "hyapp_room_rocket_open" + topic: "hyapp_room_rocket_launch" producer_group: "hyapp-room-rocket-open-producer" consumer_group: "hyapp-room-rocket-open" consumer_max_reconsume_times: 16 @@ -129,7 +129,7 @@ outbox_worker: | `rocketmq.enabled` | 控制 RocketMQ client 是否启用;本地默认关闭,线上示例开启 | | `rocketmq.room_outbox.enabled` | 控制 room outbox 是否可发布到 MQ;`publish_mode=mq/dual` 时必须开启 | | `rocketmq.room_outbox.tencent_im_consumer_enabled` | 控制 room-service 是否作为 IM bridge consumer 消费 `hyapp_room_outbox` | -| `rocketmq.rocket_open.enabled` | 控制火箭倒计时是否发布和消费延迟唤醒消息 | +| `rocketmq.rocket_launch.enabled` | 控制火箭点火后是否发布和消费延迟发射唤醒消息 | | `outbox_worker.publish_mode` | 本地默认 `direct`,线上建议 `mq`,迁移期可用 `dual` | | `poll_interval` | worker 空轮询间隔,必须大于 0,避免 busy loop | | `batch_size` | 每轮最大抢占条数,必须大于 0,避免全表扫描 | @@ -143,7 +143,7 @@ outbox_worker: | RocketMQ room outbox publisher | 把 protobuf outbox 包装成统一 `room_outbox_event`,发布到 `hyapp_room_outbox` | | Tencent IM direct publisher | `RoomCreated` 对已同步创建的房间群执行幂等 EnsureGroup;房间系统事件发送腾讯云 IM 群自定义消息 | | Activity direct publisher | 本地或未接 MQ 时直接调用 activity-service room event 消费入口 | -| Rocket open scheduler | 在 `RoomRocketCountdownStarted` 后发布到点延迟消息,唤醒 room-service 发射 | +| Rocket launch scheduler | 在 `RoomRocketIgnited` 后发布到点延迟消息,唤醒 room-service 发射 | | Activity MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,按 `event_id` 幂等推进活动/播报逻辑 | | Notice MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,写 `notice_delivery_events` 后投 C2C 私有通知 | | Room IM bridge MQ consumer | 独立 consumer group 消费 `hyapp_room_outbox`,投递房间群系统消息和群成员控制 | @@ -193,6 +193,6 @@ RocketMQ consumer 失败时不修改 `room_outbox`。consumer 应依赖 RocketMQ | MQ 不可用,`mq/dual` | 房间写命令仍成功,outbox 进入重试;MQ 恢复后补发 | | activity consumer 不可用,`mq` | `room_outbox` 不回退;RocketMQ 和 activity 消费位点负责积压与重试 | | poison event | 达到 `max_retry_count` 后进入 `failed`,不再每秒刷日志 | -| 火箭倒计时 | `RoomRocketCountdownStarted` 发布延迟唤醒;到点后 room-service 重新校验状态再发射 | +| 火箭倒计时 | `RoomRocketIgnited` 发布延迟唤醒;到点后 room-service 重新校验状态再发射 | | 正常投递 | 同一 `event_id` 可被多个 consumer group 独立消费且重复投递不产生重复副作用 | | 真实链路 | create/join/mic/sendGift/leave 均有 `room_command_timing` | diff --git a/docs/语音房功能清单.md b/docs/语音房功能清单.md index bb56f688..0565c10f 100644 --- a/docs/语音房功能清单.md +++ b/docs/语音房功能清单.md @@ -136,7 +136,7 @@ | 礼物配置 | `PARTIAL` | `wallet_gift_prices` 提供服务端价格和 `COIN`/`DIAMOND` 收费资产,`gift_configs` 提供礼物类型、有效期和特效;SendGift 请求只传 `gift_id/gift_count`;礼物配置已绑定 `resource_type=gift` 资源 | 客户端礼物表现联调、资源版本缓存刷新未做 | | 背包/道具 | `PARTIAL` | `user_resource_entitlements`、`user_resource_equipment` 支持资源发放、我的资源和可佩戴资源装备 | 背包扣减、免费礼物、道具过期扫描未做 | | 礼物消息补偿 | `DONE` | GiftSent/Heat/Rank 事件进入 outbox,由 worker direct 投 IM/activity,或发布到 RocketMQ 后由各 consumer group 消费 | 客户端去重和展示策略未验收 | -| 语音房火箭 | `DONE` | `room_rocket_configs`、`GetRoomRocket`、`RoomRocketProgressChanged/CountdownStarted/Opened/RewardGranted`,发射支持本地扫描和 RocketMQ 延迟唤醒 | App UI、后台配置运营验收和真实 MQ 联调 | +| 语音房火箭 | `DONE` | `room_rocket_configs`、`GetRoomRocket`、`RoomRocketFuelChanged/Ignited/Launched/RewardGranted`,发射支持本地扫描和 RocketMQ 延迟唤醒 | App UI、后台配置运营验收和真实 MQ 联调 | ## Activity And Lucky Gift diff --git a/docs/语音房火箭功能架构.md b/docs/语音房火箭功能架构.md index 687e3d64..265f6b76 100644 --- a/docs/语音房火箭功能架构.md +++ b/docs/语音房火箭功能架构.md @@ -1,378 +1,125 @@ # 语音房火箭功能架构 -本文定义当前语音房火箭的产品规则、服务边界、App 接口、后台配置、MQ 唤醒、room outbox 事件和验收边界。火箭是房间内送礼驱动的互动玩法:用户在语音房送礼积攒燃料,当前等级燃料满后进入倒计时,倒计时结束时由 `room-service` 按 Room Cell 快照结算并调用 `wallet-service` 发放资源组奖励。所有周期、重置和统计口径统一使用 UTC。 - -## 当前实现结论 - -| 能力 | 当前事实 | -| --- | --- | -| App 初始化 | `GET /api/v1/rooms/{room_id}/rocket` 返回 7 级物料、当前等级、当前进度、重置时间、奖励展示配置 | -| 送礼累积 | `SendGift` 同步调用 `wallet-service.DebitGift` 成功后,Room Cell 内更新热度、礼物榜和火箭进度 | -| 燃料满 | 当前等级进度封顶为阈值,锁定点火人、贡献第一、`box_id`、`open_at_ms` 和 UTC `reset_at_ms` | -| 溢出和倒计时送礼 | 当前等级溢出燃料作废;倒计时期间送礼不累加到下一级,也不改变点火人或贡献第一 | -| 到期发射 | `room-service` 通过 RocketMQ 延迟消息到 `open_at_ms` 唤醒;本地已加载 Cell 扫描 worker 仍作为兜底 | -| 奖励结算 | `room-service` 在发射命令内按配置加权抽取奖励,并调用 `wallet-service.GrantResourceGroup` 幂等发放 | -| 离房/下线 | `top1` 和 `igniter` 在倒计时开始时锁定;发射前离房或下线仍结算对应角色奖励 | -| 在房奖励 | 只发给发射命令执行时 Room Cell `OnlineUsers` 中的用户 | -| 播报 | `activity-service` 消费 `RoomRocketCountdownStarted`,按 `broadcast_scope` 发区域或全局播报 | -| 事件分发 | `room_outbox` 先落 MySQL,再由 outbox worker 发布 RocketMQ;activity、notice、IM bridge 各自 consumer group 消费 | - -## Non-Goals - -| 不做 | 原因 | -| --- | --- | -| 客户端提交燃料、奖励或中奖结果 | 燃料和奖励必须来自服务端扣费、配置和确定性抽奖 | -| 只用 Redis 保存火箭进度 | MySQL snapshot、command log 和 `room_outbox` 才是恢复来源 | -| activity-service 判断谁在房 | 房间 presence 和发射快照必须由 Room Cell 产出 | -| activity-service 发放火箭奖励 | 当前发奖在 `room-service` 发射命令内调用 `wallet-service`,避免跨服务二次改写房间结算事实 | -| cron-service 到点发射 | 到点唤醒属于房间事件消费和 Room Cell 命令触发,不是通用 cron 任务 | -| 倒计时期间继续排队燃料 | 产品规则明确无效,不累加到下一个火箭 | - ## 服务边界 -| 模块 | 拥有 | 不拥有 | -| --- | --- | --- | -| `room-service` | 火箭进度、等级、状态机、点火人、贡献第一、发射在线用户快照、抽奖结果、房间火箭 IM outbox、RocketMQ 延迟发射唤醒消费 | 用户完整资料、全局/区域播报群成员、钱包余额账本 | -| `wallet-service` | 送礼扣费、资源组发放、钱包账务、发放幂等 | 火箭进度、中奖资格、房间 presence | -| `activity-service` | 燃料满后区域/全局播报、成长值等房间事件派生消费 | Room Cell 状态、火箭奖励结算 | -| `notice-service` | 通过 room outbox/MQ 消费需要私信的房间事实,写自己的投递位点和死信 | 房间群系统消息、群成员控制、房间状态 | -| `gateway-service` | App HTTP envelope、鉴权、协议转换、调用 room gRPC | 燃料、抽奖和发奖事实 | -| `server/admin` | 后台菜单、配置表单、审计、调用 owner service 管理接口 | 直接写 room/wallet/activity 业务表 | +- `room-service` 是火箭进度、点火、待发射队列和奖励结算 owner。 +- `gateway-service` 只提供 App HTTP 入口和鉴权后的协议转换。 +- `server/admin` 只读写 `room-service` 内部配置接口,不直连 room 数据库。 +- `wallet-service` 负责资源组发放。 +- `activity-service` 负责区域/全局飘屏和带用户资料的奖励房间 IM。 +- 腾讯云 IM 负责房间群、区域群和全局群投递。 -火箭进度和发射必须经过 Room Cell 命令链路。MQ 只承担“到点唤醒”和“已提交事实分发”,不能成为火箭状态 owner。 +## 状态模型 -## 状态机 +`RoomRocketState` 保存当前正在累计的火箭和已点火待发射队列。 -```mermaid -stateDiagram-v2 - [*] --> idle - idle --> idle: SendGift progress countdown: SendGift progress>=threshold - countdown --> opened: open_at_ms reached - opened --> idle: next level - opened --> exhausted: level 7 opened - idle --> idle: UTC day reset - countdown --> idle: UTC day reset before open - exhausted --> idle: next UTC day -``` - -| 状态 | 语义 | +| 字段 | 说明 | | --- | --- | -| `idle` | 当前等级可累积燃料 | -| `countdown` | 当前等级已满,`open_at_ms` 已确定,本轮进度、点火人、贡献第一和配置版本锁定 | -| `opened` | 本轮已发射,奖励已在命令内完成抽取和资源组发放请求 | -| `exhausted` | 当天 7 级都已开启,等下一个 UTC 自然日 | +| `current_level` | 当前正在累计的等级,最高 5 | +| `current_fuel` | 当前等级燃料 | +| `fuel_threshold` | 当前等级阈值 | +| `status` | `charging` 或 `completed` | +| `rocket_id` | 当前正在累计的火箭 ID | +| `pending_launches` | 已点火、等待延迟发射的火箭 | +| `last_rewards` | 最近一次发射奖励结果 | -当前实现没有单独持久化 `round_id` 表。`box_id` 是单轮火箭幂等和奖励选择的核心 ID,发射命令 ID 固定为: +`pending_launches` 中每一项锁定: -```text -cmd_room_rocket_open_ -``` - -奖励发放命令 ID 固定由 `box_id + role + user_id + reward_item_id` 派生,重复发射或 MQ 重投不会重复发放同一条奖励。 - -## 燃料规则 - -| 规则 | 决策 | +| 字段 | 说明 | | --- | --- | -| 燃料来源 | 默认使用 `DebitGiftResponse.gift_point_added`;后台可配置 `gift_id` 或 `gift_type_code` 的倍率、覆盖值和排除规则 | -| 生效条件 | wallet 扣费成功、Room Cell 提交 `SendGift`、礼物燃料值大于 0 | -| 幂等 | 同一 `SendGift.command_id` 只能增加一次火箭燃料 | -| 点火人 | 第一笔让当前等级 `progress >= threshold` 的送礼用户 | -| 贡献第一 | 当前等级倒计时前累计有效燃料最高用户 | -| 溢出燃料 | 单笔礼物超过当前等级剩余阈值时,只计入补满当前等级所需燃料,多余燃料作废 | -| 倒计时送礼 | 当前等级已经燃料满,继续送礼不再增加火箭燃料,也不会排队到下一等级 | -| 7 级后送礼 | 当天不再累计火箭燃料,礼物仍正常扣费、热度和榜单照常更新 | +| `rocket_id` | 本枚火箭幂等 ID | +| `level` | 点火等级 | +| `fuel_threshold` | 点火阈值 | +| `ignited_at_ms` | 点火时间 | +| `launch_at_ms` | 预计发射时间 | +| `reset_at_ms` | UTC 日重置时间 | +| `top1_user_id` | 点火时贡献第一 | +| `igniter_user_id` | 点火人 | +| `config_version` | 点火配置版本 | +| `cover_url` | 小封面图 | -无效燃料只进入 `RoomRocketProgressChanged` 的审计字段,不计入当前等级贡献、不计入下一等级进度、不改变点火人或贡献第一。 +## 送礼加燃料 -## 发射与 MQ 唤醒 +1. `SendGift` 先调用 wallet 扣费。 +2. 扣费成功后,Room Cell 串行更新热度、礼物榜和火箭。 +3. 燃料来自 wallet 返回的 `heat_value`。 +4. 当前等级未满时,增加 `min(本次燃料, 剩余阈值)`。 +5. 超过阈值的燃料直接写入 `overflow_fuel`,不进入下一等级。 +6. 当前等级满后: + - 写入 `RoomRocketFuelChanged`。 + - 写入 `RoomRocketIgnited`。 + - 将当前火箭追加到 `pending_launches`。 + - 如果未到 5 级,立刻把当前状态切到下一等级,`current_fuel=0`。 + - 如果 5 级已满,状态切到 `completed`,UTC 重置前不再累计新火箭。 -```mermaid -sequenceDiagram - participant C as App - participant R as room-service - participant W as wallet-service - participant DB as hyapp_room - participant MQ as RocketMQ - participant A as activity-service - participant IM as Tencent IM +## 发射结算 - C->>R: SendGift(command_id) - R->>W: DebitGift(command_id) - W-->>R: gift_point_added, heat_value - R->>R: Room Cell updates rocket - R->>DB: command_log + snapshot + room_outbox - R-->>C: SendGiftResponse.rocket - R->>DB: outbox worker claims RoomRocketCountdownStarted - R->>MQ: delayed RoomRocketOpenDue(open_at_ms) - R->>MQ: room_outbox event - MQ-->>A: RoomRocketCountdownStarted - A-->>IM: region/global broadcast - MQ-->>R: RoomRocketOpenDue at open_at_ms - R->>R: OpenRoomRocket command - R->>W: GrantResourceGroup per reward - R->>DB: command_log + snapshot + opened/reward outbox -``` +1. `RoomRocketIgnited` 被 outbox worker 处理后,安排 RocketMQ delayed wakeup。 +2. 本地扫描 worker 也会扫描已加载且仍持有 lease 的 Room Cell,作为兜底。 +3. 到点后 `LaunchRoomRocket` 命令重新加载 Room Cell。 +4. 命令必须校验: + - `rocket_id` 存在于 `pending_launches`。 + - `level` 匹配。 + - `launch_at_ms <= now_ms`。 + - `now_ms < reset_at_ms`。 +5. 结算时按发射瞬间 `OnlineUsers` 抽在房奖励。 +6. `top1` 和 `igniter` 使用点火时锁定的用户,离房后仍发对应奖励。 +7. 发奖完成后移除该 `pending_launches` 项,当前正在累计的火箭不被发射命令推进。 -关键规则: +## 奖励 -- 延迟消息只唤醒,不直接修改状态。 -- MQ 提前投递时,`room-service` 先检查 `open_at_ms`,未到点返回可重试错误,不写 no-op command log,避免污染发射 `command_id`。 -- MQ 重复投递、outbox 重试或扫描 worker 同时触发时,`command_id` 和 wallet grant command 保证幂等。 -- 如果 `reset_at_ms` 已过,UTC 日界优先,昨天倒计时火箭不再结算。 -- 本地 `room_rocket_open_scan_interval` 只扫描本节点已加载且仍持有 lease 的 Cell,是兜底,不解决未加载房间;未加载房间依赖 MQ delayed wakeup。 - -## 奖励规则 - -| 奖励角色 | 资格 | +| 奖励 | 用户来源 | | --- | --- | -| `in_room` | 发射命令执行时 Room Cell `OnlineUsers` 内的每个用户 | -| `top1` | 倒计时开始时锁定的贡献第一用户 | -| `igniter` | 倒计时开始时锁定的点火人 | - -奖励配置按等级拆分,每个角色是一个加权奖励池。奖励项引用 `resource_group_id`,由 `wallet-service` 按资源组发放金币、钻石或资源权益。 - -```json -{ - "level": 3, - "reward_role": "top1", - "items": [ - { - "reward_item_id": "lv3_top1_a", - "resource_group_id": 12003, - "weight": 9000, - "display_name": "Top1 Reward", - "icon_url": "https://cdn.example/reward.png" - } - ] -} -``` +| 点火人奖励 | `pending_launches[].igniter_user_id` | +| 贡献第一奖励 | `pending_launches[].top1_user_id` | +| 在房奖励 | 发射命令执行时 Room Cell `OnlineUsers` | `reward_stack_policy`: -| 策略 | 语义 | +| 值 | 说明 | | --- | --- | -| `allow_stack` | 同一用户可同时获得在房、top1、igniter 多个角色奖励 | -| `priority_only` | 同一用户只获得优先级最高的一份,优先级为 `igniter -> top1 -> in_room` | +| `allow_stack` | 同一用户可同时拿在房、top1、点火人奖励 | +| `priority_only` | 先点火人,再 top1,再在房;同一用户只拿一份 | -## App 接口 +## IM -### 获取火箭信息 - -```http -GET /api/v1/rooms/{room_id}/rocket -Authorization: Bearer -``` - -Response `data` 核心字段: - -```json -{ - "enabled": true, - "server_time_ms": 1779120000000, - "reset_at_ms": 1779148800000, - "broadcast_scope": "region", - "open_delay_ms": 30000, - "broadcast_delay_ms": 0, - "reward_stack_policy": "allow_stack", - "state": { - "current_level": 3, - "current_progress": 3600, - "energy_threshold": 10000, - "status": "idle", - "open_at_ms": 0, - "top1_user_id": "10001", - "igniter_user_id": "0", - "box_id": "box_xxx", - "last_rewards": [] - }, - "levels": [ - { - "level": 1, - "energy_threshold": 3000, - "cover_url": "https://cdn.example/chest/lv1/cover.png", - "animation_url": "https://cdn.example/chest/lv1/idle.svga", - "opening_animation_url": "https://cdn.example/chest/lv1/opening.svga", - "opened_image_url": "https://cdn.example/chest/lv1/opened.png", - "in_room_rewards": [], - "top1_rewards": [], - "igniter_rewards": [] - } - ] -} -``` - -规则: - -- `levels` 固定返回 7 个等级。 -- `reset_at_ms` 是下一个 UTC 零点,不是用户本地零点。 -- 客户端只展示服务端返回的当前等级进度;不要自行把溢出燃料展示到下一等级。 -- 当前没有单独的 App 领奖接口,奖励自动发放,最近一次发射奖励通过 `state.last_rewards` 展示。 - -### SendGift 响应 - -`SendGiftResponse` 已携带 `rocket` 状态,送礼人成功送礼后可立即更新火箭 UI,不必等待 IM。 - -## 房间 IM 事件 - -房间内火箭 IM 走腾讯云房间群 `TIMCustomElem`,由 room outbox 事件转换。当前事件类型: - -| Event | 客户端 `event_type` | 用途 | +| 事实 | IM | 投递方 | | --- | --- | --- | -| `RoomRocketProgressChanged` | `room_rocket_progress_changed` | 火箭进度增加 | -| `RoomRocketCountdownStarted` | `room_rocket_countdown_started` | 燃料满进入倒计时 | -| `RoomRocketOpened` | `room_rocket_opened` | 火箭打开并给出公开奖励摘要 | -| `RoomRocketRewardGranted` | `room_rocket_reward_granted` | 发奖结果事件,包含奖励列表 | +| `RoomRocketFuelChanged` | `room_rocket_fuel_changed` | room-service IM bridge | +| `RoomRocketIgnited` | `room_rocket_ignited` | room-service IM bridge | +| `RoomRocketIgnited` | `room_rocket` 区域/全局飘屏 | activity-service | +| `RoomRocketLaunched` | `room_rocket_launched` | room-service IM bridge | +| `RoomRocketRewardGranted` | `room_rocket_reward_granted` 房间奖励 IM | activity-service | -### Progress Changed +奖励 IM 由 activity-service 查询用户公开资料后组装,包含头像、昵称、短 ID 和奖励信息。room-service 不反查 user-service。 -```json -{ - "event_type": "room_rocket_progress_changed", - "box_id": "box_xxx", - "level": 3, - "added_energy": 500, - "effective_added_energy": 500, - "overflow_energy": 0, - "current_progress": 3600, - "energy_threshold": 10000, - "status": "idle", - "reset_at_ms": 1779148800000, - "gift_id": "rose", - "gift_count": 10 -} -``` +## 高频处理 -### Countdown Started +- Room Cell 串行处理送礼命令,所以同房高频送礼不会并发写乱进度。 +- 满阈值时只把火箭追加到 `pending_launches`,不会阻塞下一等级继续累计。 +- 房间状态 IM 通过 room outbox 补偿投递,不在送礼主链路同步调用腾讯 IM。 +- 奖励 IM 合并为一条消息,`rewards` 内包含所有中奖人,避免按用户逐条堆积。 +- RocketMQ delayed wakeup 只负责唤醒,最终发射仍由 Room Cell 命令校验。 -```json -{ - "event_type": "room_rocket_countdown_started", - "box_id": "box_xxx", - "level": 3, - "current_progress": 10000, - "energy_threshold": 10000, - "open_at_ms": 1779120030000, - "broadcast_scope": "region", - "visible_region_id": 1001, - "top1_user_id": "10001", - "igniter_user_id": "10002" -} -``` +## UTC 重置 -### Opened / Reward Granted - -```json -{ - "event_type": "room_rocket_opened", - "box_id": "box_xxx", - "level": 3, - "next_level": 4, - "opened_at_ms": 1779120030000, - "top1_user_id": "10001", - "igniter_user_id": "10002", - "rewards_json": "[...]" -} -``` - -群 IM 承载公开摘要。后续如要做个人中奖私信或消息 Tab,应由 `notice-service` 或 inbox consumer 消费 `RoomRocketRewardGranted`,不要让 `room-service` 同步投递私信。 +- 火箭周期按 UTC 自然日。 +- 到达 `reset_at_ms` 后,查询或下一次送礼会投影为 1 级新进度。 +- 跨过 UTC 日界仍未发射的待发射火箭不结算。 ## 后台配置 -后台配置带 `config_version`。倒计时开始后,当前火箭的 `box_id`、等级、进度、`open_at_ms`、点火人和贡献第一不再因配置修改而变化;当前实现发射时读取最新启用配置的奖励池,因此运营在倒计时窗口内修改奖励配置要按发布窗口处理。 +配置表:`room_rocket_configs` -| 字段 | 含义 | +| 字段 | 说明 | | --- | --- | -| `enabled` | 总开关 | -| `energy_source` | 默认 `gift_point_added` | -| `open_delay_ms` | 燃料满到发射的倒计时 | -| `broadcast_enabled` | 是否燃料满后播报 | -| `broadcast_scope` | `none/region/global` | -| `broadcast_delay_ms` | 燃料满后多久发播报,当前代码写入配置和读模型,实际倒计时事件立即进入 room outbox | -| `reward_stack_policy` | `allow_stack` 或 `priority_only` | -| `levels` | 7 个等级配置,包含阈值、物料 URL 和三类奖励池 | -| `gift_energy_rules` | gift_id 或 gift_type_code 的燃料倍率、覆盖值和排除规则 | -| `updated_by_admin_id` | 审计字段 | +| `enabled` | 是否开启 | +| `fuel_source` | 固定 `heat_value` | +| `launch_delay_ms` | 点火到发射延迟 | +| `broadcast_enabled` | 是否发飘屏 | +| `broadcast_scope` | `region`、`global`、`none` | +| `reward_stack_policy` | 奖励叠加策略 | +| `levels_json` | 5 级阈值、物料和奖励池 | +| `gift_fuel_rules_json` | 礼物燃料规则 | -奖励池保存时应校验: - -- `resource_group_id` 必须存在且 active。 -- 同一奖励池权重总和必须大于 0。 -- 展示字段可以保存快照,但发放仍以 wallet-service 资源组事实为准。 -- 配置不能直接填写金币数量绕过资源组,除非新增明确的钱包奖励配置类型。 - -## room_outbox 与 RocketMQ - -`room_outbox` 是 MySQL 内的可靠事实源,RocketMQ 是发布后的事件总线。不能用 MQ 替代 outbox,因为房间状态提交成功但 MQ 发布失败时必须能从 MySQL 补偿。 - -当前 topic: - -| Topic | Producer | Consumer | -| --- | --- | --- | -| `hyapp_room_outbox` | `room-service` outbox worker | `activity-service`、`notice-service`、`room-service` IM bridge、后续 push/inbox | -| `hyapp_room_rocket_open` | `room-service` rocket open scheduler | `room-service` rocket open consumer | - -推荐线上配置: - -```yaml -outbox_worker: - enabled: true - publish_mode: "mq" - -rocketmq: - enabled: true - room_outbox: - enabled: true - topic: "hyapp_room_outbox" - rocket_open: - enabled: true - topic: "hyapp_room_rocket_open" -``` - -`publish_mode`: - -| 模式 | 行为 | -| --- | --- | -| `direct` | room outbox worker 直接投 activity gRPC 和 Tencent IM,适合本地默认 | -| `mq` | room outbox worker 只投 RocketMQ,activity/notice/IM bridge 各自消费,推荐线上 | -| `dual` | direct + MQ 双写,只用于迁移验证,所有消费者必须幂等 | - -## Daily Reset - -| 规则 | 决策 | -| --- | --- | -| 日期来源 | `time.Now().UTC()` | -| 重置时间 | 每天 UTC `00:00:00.000` | -| 时间区间 | `[day_start_ms, next_day_start_ms)` | -| idle | 到达新 UTC 日时回到 level 1,清空进度和贡献 | -| countdown | 如果 `open_at_ms` 跨过 `reset_at_ms`,UTC 日界优先,旧火箭不再结算 | -| exhausted | 下一个 UTC 日恢复 level 1 | - -必须覆盖 UTC 边界测试:`day_start_ms`、`next_day_start_ms - 1`、`next_day_start_ms`。不要重新引入 `time.Local`、`task_timezone` 或客户端时区。 - -## 验收清单 - -| 场景 | 验收 | -| --- | --- | -| 送礼成功 | wallet 扣费成功,Room Cell 进度增加,`SendGiftResponse.rocket` 返回最新状态 | -| 单笔溢出 | 进度封顶当前阈值,溢出燃料作废,不进入下一等级 | -| 倒计时送礼 | 礼物正常扣费和加热度,但火箭进度、点火人、贡献第一不变化 | -| 燃料满 | 写 `RoomRocketCountdownStarted`,outbox worker 安排 RocketMQ delayed open | -| 提前延迟消息 | 不写发射 no-op command log,MQ 后续可重试 | -| 到点发射 | 即使房间未加载,MQ 唤醒后 room-service 恢复 Room Cell 并发射 | -| top1/igniter 离房 | 仍发角色奖励 | -| 在房奖励 | 只发发射瞬间在线用户 | -| UTC 重置 | 到达 UTC 零点后进度回到 level 1,跨日倒计时不结算 | -| MQ/outbox 重投 | `event_id`、`box_id`、wallet grant command 保证幂等 | - -## 代码位置 - -| 模块 | 路径 | -| --- | --- | -| 火箭状态机和结算 | `services/room-service/internal/room/service/room_rocket.go` | -| MQ delayed open | `services/room-service/internal/room/service/room_rocket_mq.go` | -| outbox worker | `services/room-service/internal/room/service/outbox_worker.go` | -| RocketMQ 适配 | `pkg/rocketmqx`、`pkg/roommq`、`services/room-service/internal/integration/rocketmq_outbox.go` | -| App HTTP | `services/gateway-service/internal/transport/http/roomapi` | -| 后台配置 | `server/admin/internal/modules/roomrocket` | +`levels_json` 字段使用 `fuelThreshold`、`coverUrl`、`animationUrl`、`launchAnimationUrl`、`launchedImageUrl`、`inRoomRewards`、`top1Rewards`、`igniterRewards`。 diff --git a/pkg/rocketmqx/rocketmqx.go b/pkg/rocketmqx/rocketmqx.go index f7099254..5d947106 100644 --- a/pkg/rocketmqx/rocketmqx.go +++ b/pkg/rocketmqx/rocketmqx.go @@ -20,8 +20,8 @@ import ( const ( // Tencent Cloud RocketMQ accepts this property as an absolute Unix epoch // millisecond delivery timestamp. Open-source RocketMQ delay levels remain - // available through the native client, but the treasure open timer needs an - // exact backend-configured open_at_ms. + // available through the native client, but the rocket launch timer needs an + // exact backend-configured launch_at_ms. PropertyStartDeliverTime = "__STARTDELIVERTIME" ) diff --git a/server/admin/internal/integration/roomclient/client.go b/server/admin/internal/integration/roomclient/client.go index a4b1a4a7..9bd3574f 100644 --- a/server/admin/internal/integration/roomclient/client.go +++ b/server/admin/internal/integration/roomclient/client.go @@ -135,7 +135,7 @@ type GiftFuelRuleConfig struct { GiftID string GiftTypeCode string MultiplierPPM int64 - FixedFuel int64 + FixedFuel int64 Excluded bool } @@ -642,7 +642,7 @@ func roomRocketFuelRulesFromProto(input []*roomv1.RoomRocketGiftFuelRule) []Gift GiftID: rule.GetGiftId(), GiftTypeCode: rule.GetGiftTypeCode(), MultiplierPPM: rule.GetMultiplierPpm(), - FixedFuel: rule.GetFixedFuel(), + FixedFuel: rule.GetFixedFuel(), Excluded: rule.GetExcluded(), }) } @@ -657,7 +657,7 @@ func roomRocketFuelRulesToProto(input []GiftFuelRuleConfig) []*roomv1.RoomRocket GiftId: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPpm: rule.MultiplierPPM, - FixedFuel: rule.FixedFuel, + FixedFuel: rule.FixedFuel, Excluded: rule.Excluded, }) } diff --git a/server/admin/internal/modules/roomrocket/service.go b/server/admin/internal/modules/roomrocket/service.go index 910d093b..b9fdd1ac 100644 --- a/server/admin/internal/modules/roomrocket/service.go +++ b/server/admin/internal/modules/roomrocket/service.go @@ -71,7 +71,7 @@ type GiftFuelRuleConfig struct { GiftID string `json:"giftId"` GiftTypeCode string `json:"giftTypeCode"` MultiplierPPM int64 `json:"multiplierPpm"` - FixedFuel int64 `json:"fixedFuel"` + FixedFuel int64 `json:"fixedFuel"` Excluded bool `json:"excluded"` } @@ -161,10 +161,6 @@ func normalizeConfig(config RoomRocketConfig) (RoomRocketConfig, error) { return RoomRocketConfig{}, fmt.Errorf("%w: 配置版本不能小于 0", ErrInvalidArgument) } config.FuelSource = defaultString(strings.TrimSpace(config.FuelSource), defaultFuelSource) - if config.FuelSource == "gift_point_added" { - // gift_point_added 是历史配置值;GIFT_POINT 已下线,后台读取旧配置时统一切到真实礼物贡献口径。 - config.FuelSource = defaultFuelSource - } if config.FuelSource != defaultFuelSource { return RoomRocketConfig{}, fmt.Errorf("%w: 燃料来源不支持", ErrInvalidArgument) } @@ -408,7 +404,7 @@ func fuelRulesFromClient(input []roomclient.GiftFuelRuleConfig) []GiftFuelRuleCo GiftID: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPPM: rule.MultiplierPPM, - FixedFuel: rule.FixedFuel, + FixedFuel: rule.FixedFuel, Excluded: rule.Excluded, }) } @@ -423,7 +419,7 @@ func fuelRulesToClient(input []GiftFuelRuleConfig) []roomclient.GiftFuelRuleConf GiftID: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPPM: rule.MultiplierPPM, - FixedFuel: rule.FixedFuel, + FixedFuel: rule.FixedFuel, Excluded: rule.Excluded, }) } diff --git a/server/admin/internal/modules/roomrocket/service_test.go b/server/admin/internal/modules/roomrocket/service_test.go index 888dd4e6..18af318c 100644 --- a/server/admin/internal/modules/roomrocket/service_test.go +++ b/server/admin/internal/modules/roomrocket/service_test.go @@ -15,8 +15,6 @@ func TestNormalizeConfigDefaultsAndSortsLevels(t *testing.T) { {Level: 3, FuelThreshold: 600}, {Level: 4, FuelThreshold: 1_000}, {Level: 5, FuelThreshold: 1_500}, - {Level: 6, FuelThreshold: 2_100}, - {Level: 7, FuelThreshold: 2_800}, }, }) if err != nil { @@ -25,7 +23,7 @@ func TestNormalizeConfigDefaultsAndSortsLevels(t *testing.T) { if config.FuelSource != defaultFuelSource || config.LaunchDelayMS != defaultLaunchDelayMS || config.BroadcastScope != defaultBroadcastScope { t.Fatalf("default fields mismatch: %+v", config) } - if config.Levels[0].Level != 1 || config.Levels[6].Level != 7 { + if config.Levels[0].Level != 1 || config.Levels[4].Level != 5 { t.Fatalf("levels should be sorted by level: %+v", config.Levels) } } @@ -47,10 +45,10 @@ func TestNormalizeConfigRejectsInvalidLevels(t *testing.T) { }{ {name: "missing_level", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{{Level: 1, FuelThreshold: 1}}}}, {name: "duplicate", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ - {Level: 1, FuelThreshold: 1}, {Level: 1, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, + {Level: 1, FuelThreshold: 1}, {Level: 1, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, }}}, {name: "zero_threshold", config: RoomRocketConfig{AppCode: "lalu", Levels: []RoomRocketLevelConfig{ - {Level: 1, FuelThreshold: 0}, {Level: 2, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, {Level: 6, FuelThreshold: 6}, {Level: 7, FuelThreshold: 7}, + {Level: 1, FuelThreshold: 0}, {Level: 2, FuelThreshold: 2}, {Level: 3, FuelThreshold: 3}, {Level: 4, FuelThreshold: 4}, {Level: 5, FuelThreshold: 5}, }}}, } @@ -74,6 +72,6 @@ func TestNormalizeConfigRejectsIncompleteRewardAndFuelRule(t *testing.T) { config = defaultConfig("lalu") config.GiftFuelRules = []GiftFuelRuleConfig{{GiftID: "gift-1"}} if _, err := normalizeConfig(config); !errors.Is(err, ErrInvalidArgument) { - t.Fatalf("energy rule without multiplier or fixed energy should be invalid, got %v", err) + t.Fatalf("fuel rule without multiplier or fixed fuel should be invalid, got %v", err) } } diff --git a/server/admin/migrations/018_room_treasure_navigation.sql b/server/admin/migrations/018_room_rocket_navigation.sql similarity index 100% rename from server/admin/migrations/018_room_treasure_navigation.sql rename to server/admin/migrations/018_room_rocket_navigation.sql diff --git a/services/activity-service/internal/service/broadcast/service.go b/services/activity-service/internal/service/broadcast/service.go index 6596d8e7..9ccfe21b 100644 --- a/services/activity-service/internal/service/broadcast/service.go +++ b/services/activity-service/internal/service/broadcast/service.go @@ -649,19 +649,19 @@ func roomPasswordChangedPayload(envelope *roomeventsv1.EventEnvelope, event *roo func roomRocketPayload(envelope *roomeventsv1.EventEnvelope, rocket *roomeventsv1.RoomRocketIgnited, eventID string, sentAtMS int64, igniter SenderProfile) (string, error) { payload := map[string]any{ - "event_id": eventID, - "broadcast_type": broadcastdomain.TypeRoomRocket, - "scope": rocket.GetBroadcastScope(), - "app_code": envelope.GetAppCode(), - "region_id": rocket.GetVisibleRegionId(), - "room_id": envelope.GetRoomId(), - "room_short_id": rocket.GetRoomShortId(), - "rocket_id": rocket.GetRocketId(), - "rocket_level": rocket.GetLevel(), + "event_id": eventID, + "broadcast_type": broadcastdomain.TypeRoomRocket, + "scope": rocket.GetBroadcastScope(), + "app_code": envelope.GetAppCode(), + "region_id": rocket.GetVisibleRegionId(), + "room_id": envelope.GetRoomId(), + "room_short_id": rocket.GetRoomShortId(), + "rocket_id": rocket.GetRocketId(), + "rocket_level": rocket.GetLevel(), "rocket_cover_url": rocket.GetRocketCoverUrl(), - "launch_at_ms": rocket.GetLaunchAtMs(), - "top1_user_id": rocket.GetTop1UserId(), - "igniter_user_id": rocket.GetIgniterUserId(), + "launch_at_ms": rocket.GetLaunchAtMs(), + "top1_user_id": rocket.GetTop1UserId(), + "igniter_user_id": rocket.GetIgniterUserId(), "igniter": map[string]any{ "user_id": fmt.Sprintf("%d", rocket.GetIgniterUserId()), "short_id": strings.TrimSpace(igniter.Account), @@ -689,8 +689,8 @@ func roomRocketRewardPayload(envelope *roomeventsv1.EventEnvelope, event *roomev userID := reward.GetUserId() profile := profiles[userID] rewards = append(rewards, map[string]any{ - "reward_role": reward.GetRewardRole(), - "user_id": fmt.Sprintf("%d", userID), + "reward_role": reward.GetRewardRole(), + "user_id": fmt.Sprintf("%d", userID), "user": map[string]any{ "user_id": fmt.Sprintf("%d", userID), "short_id": strings.TrimSpace(profile.Account), diff --git a/services/gateway-service/internal/transport/http/roomapi/room_view.go b/services/gateway-service/internal/transport/http/roomapi/room_view.go index 094097d6..c36b1486 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_view.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_view.go @@ -199,19 +199,19 @@ type roomRocketRewardData struct { } type roomRocketStateData struct { - CurrentLevel int32 `json:"current_level"` - CurrentFuel int64 `json:"current_fuel"` - FuelThreshold int64 `json:"fuel_threshold"` - Status string `json:"status"` - IgnitedAtMS int64 `json:"ignited_at_ms,omitempty"` - LaunchAtMS int64 `json:"launch_at_ms,omitempty"` - LaunchedAtMS int64 `json:"launched_at_ms,omitempty"` - ResetAtMS int64 `json:"reset_at_ms"` - Top1UserID string `json:"top1_user_id,omitempty"` - IgniterUserID string `json:"igniter_user_id,omitempty"` - RocketID string `json:"rocket_id,omitempty"` - ConfigVersion int64 `json:"config_version,omitempty"` - LastRewards []roomRocketRewardGrantData `json:"last_rewards,omitempty"` + CurrentLevel int32 `json:"current_level"` + CurrentFuel int64 `json:"current_fuel"` + FuelThreshold int64 `json:"fuel_threshold"` + Status string `json:"status"` + IgnitedAtMS int64 `json:"ignited_at_ms,omitempty"` + LaunchAtMS int64 `json:"launch_at_ms,omitempty"` + LaunchedAtMS int64 `json:"launched_at_ms,omitempty"` + ResetAtMS int64 `json:"reset_at_ms"` + Top1UserID string `json:"top1_user_id,omitempty"` + IgniterUserID string `json:"igniter_user_id,omitempty"` + RocketID string `json:"rocket_id,omitempty"` + ConfigVersion int64 `json:"config_version,omitempty"` + LastRewards []roomRocketRewardGrantData `json:"last_rewards,omitempty"` PendingLaunches []roomRocketPendingLaunchData `json:"pending_launches,omitempty"` } @@ -225,7 +225,7 @@ type roomRocketPendingLaunchData struct { Top1UserID string `json:"top1_user_id,omitempty"` IgniterUserID string `json:"igniter_user_id,omitempty"` ConfigVersion int64 `json:"config_version,omitempty"` - CoverURL string `json:"cover_url,omitempty"` + CoverURL string `json:"cover_url,omitempty"` } type roomRocketRewardGrantData struct { @@ -460,19 +460,19 @@ func roomRocketStateFromProto(state *roomv1.RoomRocketState) roomRocketStateData return roomRocketStateData{} } return roomRocketStateData{ - CurrentLevel: state.GetCurrentLevel(), - CurrentFuel: state.GetCurrentFuel(), - FuelThreshold: state.GetFuelThreshold(), - Status: state.GetStatus(), - IgnitedAtMS: state.GetIgnitedAtMs(), - LaunchAtMS: state.GetLaunchAtMs(), - LaunchedAtMS: state.GetLaunchedAtMs(), - ResetAtMS: state.GetResetAtMs(), - Top1UserID: formatOptionalUserID(state.GetTop1UserId()), - IgniterUserID: formatOptionalUserID(state.GetIgniterUserId()), - RocketID: state.GetRocketId(), - ConfigVersion: state.GetConfigVersion(), - LastRewards: roomRocketRewardGrantsFromProto(state.GetLastRewards()), + CurrentLevel: state.GetCurrentLevel(), + CurrentFuel: state.GetCurrentFuel(), + FuelThreshold: state.GetFuelThreshold(), + Status: state.GetStatus(), + IgnitedAtMS: state.GetIgnitedAtMs(), + LaunchAtMS: state.GetLaunchAtMs(), + LaunchedAtMS: state.GetLaunchedAtMs(), + ResetAtMS: state.GetResetAtMs(), + Top1UserID: formatOptionalUserID(state.GetTop1UserId()), + IgniterUserID: formatOptionalUserID(state.GetIgniterUserId()), + RocketID: state.GetRocketId(), + ConfigVersion: state.GetConfigVersion(), + LastRewards: roomRocketRewardGrantsFromProto(state.GetLastRewards()), PendingLaunches: roomRocketPendingLaunchesFromProto(state.GetPendingLaunches()), } } diff --git a/services/room-service/configs/config.docker.yaml b/services/room-service/configs/config.docker.yaml index 799a8dbc..b7651a41 100644 --- a/services/room-service/configs/config.docker.yaml +++ b/services/room-service/configs/config.docker.yaml @@ -67,11 +67,11 @@ rocketmq: tencent_im_consumer_enabled: true tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - rocket_open: + rocket_launch: enabled: false topic: "hyapp_room_rocket_launch" - producer_group: "hyapp-room-rocket-open-producer" - consumer_group: "hyapp-room-rocket-open" + producer_group: "hyapp-room-rocket-launch-producer" + consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 outbox_worker: # Docker 和 testbox 走 MQ;room-service 同进程启动 IM bridge consumer 补偿房间群消息。 diff --git a/services/room-service/configs/config.tencent.example.yaml b/services/room-service/configs/config.tencent.example.yaml index 0a136145..55b3cb9e 100644 --- a/services/room-service/configs/config.tencent.example.yaml +++ b/services/room-service/configs/config.tencent.example.yaml @@ -77,11 +77,11 @@ rocketmq: tencent_im_consumer_enabled: true tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - rocket_open: + rocket_launch: enabled: true topic: "hyapp_room_rocket_launch" - producer_group: "hyapp-room-rocket-open-producer" - consumer_group: "hyapp-room-rocket-open" + producer_group: "hyapp-room-rocket-launch-producer" + consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 outbox_worker: # mq 模式下 outbox worker 只把事实投 MQ,并顺带安排火箭延迟发射唤醒。 diff --git a/services/room-service/configs/config.yaml b/services/room-service/configs/config.yaml index 6789596d..a6b42dff 100644 --- a/services/room-service/configs/config.yaml +++ b/services/room-service/configs/config.yaml @@ -70,11 +70,11 @@ rocketmq: tencent_im_consumer_enabled: false tencent_im_consumer_group: "hyapp-room-im-bridge" consumer_max_reconsume_times: 16 - rocket_open: + rocket_launch: enabled: false topic: "hyapp_room_rocket_launch" - producer_group: "hyapp-room-rocket-open-producer" - consumer_group: "hyapp-room-rocket-open" + producer_group: "hyapp-room-rocket-launch-producer" + consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 outbox_worker: # room_outbox 是腾讯云 IM 和 activity-service 的异步投递通道;失败退避重试,超过上限转死信。 diff --git a/services/room-service/internal/config/config.go b/services/room-service/internal/config/config.go index d69dd2dd..b495b8b3 100644 --- a/services/room-service/internal/config/config.go +++ b/services/room-service/internal/config/config.go @@ -123,7 +123,7 @@ type RocketMQConfig struct { SendTimeout time.Duration `yaml:"send_timeout"` Retry int `yaml:"retry"` RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"` - RocketLaunch RocketLaunchMQConfig `yaml:"rocket_open"` + RocketLaunch RocketLaunchMQConfig `yaml:"rocket_launch"` } // RoomOutboxMQConfig 控制 room_outbox fanout topic。 @@ -302,8 +302,8 @@ func defaultRocketMQConfig() RocketMQConfig { RocketLaunch: RocketLaunchMQConfig{ Enabled: false, Topic: "hyapp_room_rocket_launch", - ProducerGroup: "hyapp-room-rocket-open-producer", - ConsumerGroup: "hyapp-room-rocket-open", + ProducerGroup: "hyapp-room-rocket-launch-producer", + ConsumerGroup: "hyapp-room-rocket-launch", ConsumerMaxReconsumeTimes: 16, }, } diff --git a/services/room-service/internal/config/config_test.go b/services/room-service/internal/config/config_test.go index e71868c2..72a806ec 100644 --- a/services/room-service/internal/config/config_test.go +++ b/services/room-service/internal/config/config_test.go @@ -71,7 +71,7 @@ func TestLoadTencentExample(t *testing.T) { t.Fatalf("tencent example must configure outbox worker: %+v", cfg.OutboxWorker) } if cfg.OutboxWorker.PublishMode != OutboxPublishModeMQ || !cfg.RocketMQ.RoomOutbox.Enabled || !cfg.RocketMQ.RocketLaunch.Enabled { - t.Fatalf("tencent example must route room outbox and rocket open through RocketMQ: mode=%s mq=%+v", cfg.OutboxWorker.PublishMode, cfg.RocketMQ) + t.Fatalf("tencent example must route room outbox and rocket launch through RocketMQ: mode=%s mq=%+v", cfg.OutboxWorker.PublishMode, cfg.RocketMQ) } } diff --git a/services/room-service/internal/integration/clients_grpc.go b/services/room-service/internal/integration/clients_grpc.go index 3aadd92e..a2600081 100644 --- a/services/room-service/internal/integration/clients_grpc.go +++ b/services/room-service/internal/integration/clients_grpc.go @@ -36,7 +36,7 @@ func (c *grpcWalletClient) BatchDebitGift(ctx context.Context, req *walletv1.Bat // GrantResourceGroup 直接转调 wallet-service 资源组发放接口。 func (c *grpcWalletClient) GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest) (*walletv1.ResourceGrantResponse, error) { - // 宝箱奖励以 resource group 为后台配置单位,wallet-service 负责展开资产和权益。 + // 火箭奖励以 resource group 为后台配置单位,wallet-service 负责展开资产和权益。 return c.client.GrantResourceGroup(ctx, req) } diff --git a/services/room-service/internal/integration/rocketmq_outbox.go b/services/room-service/internal/integration/rocketmq_outbox.go index 963d3ee3..2b84dc72 100644 --- a/services/room-service/internal/integration/rocketmq_outbox.go +++ b/services/room-service/internal/integration/rocketmq_outbox.go @@ -52,7 +52,7 @@ type RocketMQRocketLaunchScheduler struct { topic string } -// NewRocketMQRocketLaunchScheduler creates the delayed open scheduler. +// NewRocketMQRocketLaunchScheduler creates the delayed launch scheduler. func NewRocketMQRocketLaunchScheduler(producer *rocketmqx.Producer, topic string) *RocketMQRocketLaunchScheduler { return &RocketMQRocketLaunchScheduler{producer: producer, topic: topic} } diff --git a/services/room-service/internal/integration/tencent_im.go b/services/room-service/internal/integration/tencent_im.go index ead2452d..746b0c6e 100644 --- a/services/room-service/internal/integration/tencent_im.go +++ b/services/room-service/internal/integration/tencent_im.go @@ -302,10 +302,14 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room base.Attributes = map[string]string{ "rocket_id": body.GetRocketId(), "level": fmt.Sprintf("%d", body.GetLevel()), + "rocket_level": fmt.Sprintf("%d", body.GetLevel()), + "room_short_id": body.GetRoomShortId(), + "rocket_cover_url": body.GetRocketCoverUrl(), "current_fuel": fmt.Sprintf("%d", body.GetCurrentFuel()), "fuel_threshold": fmt.Sprintf("%d", body.GetFuelThreshold()), "ignited_at_ms": fmt.Sprintf("%d", body.GetIgnitedAtMs()), "launch_at_ms": fmt.Sprintf("%d", body.GetLaunchAtMs()), + "reset_at_ms": fmt.Sprintf("%d", body.GetResetAtMs()), "broadcast_scope": body.GetBroadcastScope(), "visible_region_id": fmt.Sprintf("%d", body.GetVisibleRegionId()), "top1_user_id": fmt.Sprintf("%d", body.GetTop1UserId()), @@ -336,20 +340,9 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room } return base, true, nil case "RoomRocketRewardGranted": - var body roomeventsv1.RoomRocketRewardGranted - if err := proto.Unmarshal(envelope.GetBody(), &body); err != nil { - return tencentim.RoomEvent{}, false, err - } - rewardsJSON, err := json.Marshal(body.GetRewards()) - if err != nil { - return tencentim.RoomEvent{}, false, err - } - base.Attributes = map[string]string{ - "rocket_id": body.GetRocketId(), - "level": fmt.Sprintf("%d", body.GetLevel()), - "rewards_json": string(rewardsJSON), - } - return base, true, nil + // 奖励 IM 需要头像、昵称和短 ID,room-service 不反查 user-service; + // activity-service 消费同一事实后做资料 enrichment 并投递房间播报。 + return tencentim.RoomEvent{}, false, nil default: // RoomCreated/HeatChanged/RankChanged 不单独推客户端,避免一条命令产生多条系统消息。 return tencentim.RoomEvent{}, false, nil diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index 81048079..5a2e9eb8 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -211,11 +211,11 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r records = append(records, progressEvent) } if rocketApply.ignited != nil { - countdownEvent, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited) + ignitedEvent, err := outbox.Build(current.RoomID, "RoomRocketIgnited", current.Version, now, rocketApply.ignited) if err != nil { return mutationResult{}, nil, err } - records = append(records, countdownEvent) + records = append(records, ignitedEvent) } return mutationResult{ diff --git a/services/room-service/internal/room/service/recovery.go b/services/room-service/internal/room/service/recovery.go index e2b06552..b129065f 100644 --- a/services/room-service/internal/room/service/recovery.go +++ b/services/room-service/internal/room/service/recovery.go @@ -419,17 +419,17 @@ func replay(current *state.RoomState, cmd command.Command, committedAtMS int64) func rocketStateFromSettledGift(cmd *command.SendGift) *state.RocketState { return &state.RocketState{ - CurrentLevel: cmd.RocketLevel, - CurrentFuel: cmd.RocketFuel, - FuelThreshold: cmd.RocketFuelThreshold, - Status: cmd.RocketStatus, - IgnitedAtMS: cmd.RocketIgnitedAtMS, - LaunchAtMS: cmd.RocketLaunchAtMS, - ResetAtMS: cmd.RocketResetAtMS, - Top1UserID: cmd.RocketTop1UserID, - IgniterUserID: cmd.RocketIgniterUserID, - RocketID: cmd.RocketID, - ConfigVersion: cmd.RocketConfigVersion, + CurrentLevel: cmd.RocketLevel, + CurrentFuel: cmd.RocketFuel, + FuelThreshold: cmd.RocketFuelThreshold, + Status: cmd.RocketStatus, + IgnitedAtMS: cmd.RocketIgnitedAtMS, + LaunchAtMS: cmd.RocketLaunchAtMS, + ResetAtMS: cmd.RocketResetAtMS, + Top1UserID: cmd.RocketTop1UserID, + IgniterUserID: cmd.RocketIgniterUserID, + RocketID: cmd.RocketID, + ConfigVersion: cmd.RocketConfigVersion, PendingLaunches: rocketPendingLaunchesFromCommand(cmd.RocketPendingLaunches), } } diff --git a/services/room-service/internal/room/service/repository.go b/services/room-service/internal/room/service/repository.go index 37b28a5b..16cbde3b 100644 --- a/services/room-service/internal/room/service/repository.go +++ b/services/room-service/internal/room/service/repository.go @@ -293,7 +293,7 @@ type GiftFuelRuleConfig struct { GiftID string `json:"giftId"` GiftTypeCode string `json:"giftTypeCode"` MultiplierPPM int64 `json:"multiplierPpm"` - FixedFuel int64 `json:"fixedFuel"` + FixedFuel int64 `json:"fixedFuel"` Excluded bool `json:"excluded"` } diff --git a/services/room-service/internal/room/service/room_rocket.go b/services/room-service/internal/room/service/room_rocket.go index 470552d7..c7373ca1 100644 --- a/services/room-service/internal/room/service/room_rocket.go +++ b/services/room-service/internal/room/service/room_rocket.go @@ -126,10 +126,6 @@ func normalizeRoomRocketConfig(config RoomRocketConfig) (RoomRocketConfig, error return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket config_version is invalid") } config.FuelSource = defaultRoomRocketString(config.FuelSource, roomRocketDefaultFuelSource) - if config.FuelSource == "gift_point_added" { - // 旧配置可能还存着 gift_point_added;GIFT_POINT 已下线,运行时统一按真实送礼贡献 heat_value 计算火箭燃料。 - config.FuelSource = roomRocketFuelHeatValue - } if config.FuelSource != roomRocketFuelHeatValue { return RoomRocketConfig{}, xerr.New(xerr.InvalidArgument, "room rocket fuel_source is invalid") } @@ -247,20 +243,20 @@ func roomRocketProtoStateForView(current *roomv1.RoomRocketState, config RoomRoc internal := state.RocketState{} if current != nil { internal = state.RocketState{ - CurrentLevel: current.GetCurrentLevel(), - CurrentFuel: current.GetCurrentFuel(), - FuelThreshold: current.GetFuelThreshold(), - Status: current.GetStatus(), - IgnitedAtMS: current.GetIgnitedAtMs(), - LaunchAtMS: current.GetLaunchAtMs(), - LaunchedAtMS: current.GetLaunchedAtMs(), - ResetAtMS: current.GetResetAtMs(), - Top1UserID: current.GetTop1UserId(), - IgniterUserID: current.GetIgniterUserId(), - RocketID: current.GetRocketId(), - ConfigVersion: current.GetConfigVersion(), + CurrentLevel: current.GetCurrentLevel(), + CurrentFuel: current.GetCurrentFuel(), + FuelThreshold: current.GetFuelThreshold(), + Status: current.GetStatus(), + IgnitedAtMS: current.GetIgnitedAtMs(), + LaunchAtMS: current.GetLaunchAtMs(), + LaunchedAtMS: current.GetLaunchedAtMs(), + ResetAtMS: current.GetResetAtMs(), + Top1UserID: current.GetTop1UserId(), + IgniterUserID: current.GetIgniterUserId(), + RocketID: current.GetRocketId(), + ConfigVersion: current.GetConfigVersion(), PendingLaunches: statePendingLaunchesFromProto(current.GetPendingLaunches()), - LastRewards: stateRewardsFromProto(current.GetLastRewards()), + LastRewards: stateRewardsFromProto(current.GetLastRewards()), } } normalized := rocketStateForNow(&internal, config, now, false) @@ -693,7 +689,7 @@ func rocketStateToEventRewards(input []state.RocketRewardGrant) []*roomeventsv1. return out } -// RunRoomRocketLaunchWorker 周期性扫描已装载房间,把到点的倒计时火箭走命令链路打开。 +// RunRoomRocketLaunchWorker 周期性扫描已装载房间,把到点的待发射火箭走命令链路发射。 func (s *Service) RunRoomRocketLaunchWorker(ctx context.Context, interval time.Duration) { if interval <= 0 { return @@ -849,7 +845,7 @@ func (s *Service) launchRoomRocket(ctx context.Context, cmd command.LaunchRoomRo current.Version++ - openedEvent, err := outbox.Build(current.RoomID, "RoomRocketLaunched", current.Version, now, &roomeventsv1.RoomRocketLaunched{ + launchedEvent, err := outbox.Build(current.RoomID, "RoomRocketLaunched", current.Version, now, &roomeventsv1.RoomRocketLaunched{ RocketId: pending.RocketID, Level: pending.Level, NextLevel: current.Rocket.CurrentLevel, @@ -863,7 +859,7 @@ func (s *Service) launchRoomRocket(ctx context.Context, cmd command.LaunchRoomRo if err != nil { return mutationResult{}, nil, err } - records := []outbox.Record{openedEvent} + records := []outbox.Record{launchedEvent} if len(rewards) > 0 { rewardEvent, err := outbox.Build(current.RoomID, "RoomRocketRewardGranted", current.Version, now, &roomeventsv1.RoomRocketRewardGranted{ RocketId: pending.RocketID, diff --git a/services/room-service/internal/room/service/room_rocket_test.go b/services/room-service/internal/room/service/room_rocket_test.go index 6ed40ebc..661f8e2f 100644 --- a/services/room-service/internal/room/service/room_rocket_test.go +++ b/services/room-service/internal/room/service/room_rocket_test.go @@ -175,13 +175,13 @@ func (r *rocketLaunchScheduleRecorder) ScheduleRoomRocketLaunch(_ context.Contex return nil } -func TestRoomRocketGiftOverflowAndIgnitedInvalidEnergy(t *testing.T) { +func TestRoomRocketGiftOverflowAndImmediateNextLevel(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} wallet := &rocketTestWallet{debits: []*walletv1.DebitGiftResponse{ - {BillingReceiptId: "receipt-fill", GiftPointAdded: 150, HeatValue: 150, GiftTypeCode: "normal"}, - {BillingReceiptId: "receipt-ignited", GiftPointAdded: 200, HeatValue: 200, GiftTypeCode: "normal"}, + {BillingReceiptId: "receipt-fill", GiftPointAdded: 250, HeatValue: 250, GiftTypeCode: "normal"}, + {BillingReceiptId: "receipt-next", GiftPointAdded: 50, HeatValue: 50, GiftTypeCode: "normal"}, }} svc := newRocketTestService(t, repository, wallet, now) writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) @@ -203,46 +203,60 @@ func TestRoomRocketGiftOverflowAndIgnitedInvalidEnergy(t *testing.T) { t.Fatalf("send fill gift failed: %v", err) } rocket := fillResp.GetRocket() - if rocket.GetCurrentLevel() != 1 || rocket.GetCurrentFuel() != 100 || rocket.GetStatus() != state.RocketStatusIgnited { - t.Fatalf("fill gift must cap level 1 progress and enter ignited: %+v", rocket) + if rocket.GetCurrentLevel() != 2 || rocket.GetCurrentFuel() != 0 || rocket.GetStatus() != state.RocketStatusCharging { + t.Fatalf("fill gift must ignite level 1 and immediately start level 2: %+v", rocket) } - if rocket.GetLaunchAtMs() != now.Now().Add(time.Second).UnixMilli() || rocket.GetResetAtMs() != time.Date(2026, 5, 21, 0, 0, 0, 0, time.UTC).UnixMilli() { + if len(rocket.GetPendingLaunches()) != 1 { + t.Fatalf("filled level must create exactly one pending launch: %+v", rocket) + } + pending := rocket.GetPendingLaunches()[0] + if pending.GetLevel() != 1 || pending.GetFuelThreshold() != 100 || pending.GetLaunchAtMs() != now.Now().Add(time.Second).UnixMilli() { + t.Fatalf("pending launch must lock the filled level snapshot: %+v", pending) + } + if rocket.GetResetAtMs() != time.Date(2026, 5, 21, 0, 0, 0, 0, time.UTC).UnixMilli() { t.Fatalf("rocket timers must use UTC business time: %+v", rocket) } - if rocket.GetTop1UserId() != ownerID || rocket.GetIgniterUserId() != ownerID { - t.Fatalf("top1 and igniter must lock at ignited start: %+v", rocket) + if pending.GetTop1UserId() != ownerID || pending.GetIgniterUserId() != ownerID { + t.Fatalf("top1 and igniter must lock at ignited start: %+v", pending) } progressEvents := rocketProgressEvents(t, ctx, repository) - if len(progressEvents) != 1 || progressEvents[0].GetAddedFuel() != 150 || progressEvents[0].GetEffectiveAddedFuel() != 100 || progressEvents[0].GetOverflowFuel() != 50 { - t.Fatalf("progress event must expose effective energy and discarded overflow: %+v", progressEvents) + if len(progressEvents) != 1 || progressEvents[0].GetAddedFuel() != 250 || progressEvents[0].GetEffectiveAddedFuel() != 100 || progressEvents[0].GetOverflowFuel() != 150 { + t.Fatalf("progress event must expose effective fuel and discarded overflow: %+v", progressEvents) + } + if progressEvents[0].GetLevel() != 1 || progressEvents[0].GetStatus() != state.RocketStatusIgnited { + t.Fatalf("progress event must describe the filled level, got %+v", progressEvents[0]) } if got := countRocketIgnitedEvents(t, ctx, repository); got != 1 { t.Fatalf("fill gift must emit one ignited event, got %d", got) } - countdownResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ - Meta: rocketMeta(roomID, viewerID, "ignited"), + nextResp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ + Meta: rocketMeta(roomID, viewerID, "next-level"), TargetType: "user", TargetUserId: ownerID, - GiftId: "gift-during-ignited", + GiftId: "gift-next-level", GiftCount: 1, }) if err != nil { - t.Fatalf("send ignited gift failed: %v", err) + t.Fatalf("send next-level gift failed: %v", err) } - if countdownResp.GetRocket().GetCurrentFuel() != 100 || countdownResp.GetRocket().GetStatus() != state.RocketStatusIgnited { - t.Fatalf("ignited gift must not change rocket progress: %+v", countdownResp.GetRocket()) + if nextResp.GetRocket().GetCurrentLevel() != 2 || nextResp.GetRocket().GetCurrentFuel() != 50 || nextResp.GetRocket().GetStatus() != state.RocketStatusCharging { + t.Fatalf("gift after ignition must add fuel to the next level immediately: %+v", nextResp.GetRocket()) } - if got := len(rocketProgressEvents(t, ctx, repository)); got != 1 { - t.Fatalf("ignited invalid energy must not emit a second progress event, got %d", got) + if len(nextResp.GetRocket().GetPendingLaunches()) != 1 { + t.Fatalf("new progress must keep the previous pending launch only: %+v", nextResp.GetRocket()) + } + progressEvents = rocketProgressEvents(t, ctx, repository) + if len(progressEvents) != 2 || progressEvents[1].GetLevel() != 2 || progressEvents[1].GetEffectiveAddedFuel() != 50 || progressEvents[1].GetOverflowFuel() != 0 { + t.Fatalf("second progress event must target level 2: %+v", progressEvents) } if got := countRocketIgnitedEvents(t, ctx, repository); got != 1 { - t.Fatalf("ignited invalid energy must not emit another ignited event, got %d", got) + t.Fatalf("next-level partial gift must not emit another ignited event, got %d", got) } } -func TestRoomRocketIgnitedOutboxSchedulesDelayedOpen(t *testing.T) { +func TestRoomRocketIgnitedOutboxSchedulesDelayedLaunch(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) now := &fixedRoomRocketClock{now: time.Date(2026, 5, 20, 12, 0, 0, 0, time.UTC)} @@ -270,11 +284,11 @@ func TestRoomRocketIgnitedOutboxSchedulesDelayedOpen(t *testing.T) { t.Fatalf("process outbox failed: %v", err) } if len(scheduler.schedules) != 1 { - t.Fatalf("scheduled opens=%d, want 1: %+v", len(scheduler.schedules), scheduler.schedules) + t.Fatalf("scheduled launches=%d, want 1: %+v", len(scheduler.schedules), scheduler.schedules) } scheduled := scheduler.schedules[0] - if scheduled.RoomID != roomID || scheduled.Level != 1 || scheduled.LaunchAtMS != now.Now().Add(time.Second).UnixMilli() || scheduled.CommandID == "" { - t.Fatalf("unexpected delayed open schedule: %+v", scheduled) + if scheduled.RoomID != roomID || scheduled.Level != 1 || scheduled.LaunchAtMS != now.Now().Add(time.Second).UnixMilli() || scheduled.ResetAtMS == 0 || scheduled.CommandID == "" { + t.Fatalf("unexpected delayed launch schedule: %+v", scheduled) } } @@ -288,7 +302,7 @@ func TestRoomRocketLaunchDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { svc := newRocketTestService(t, repository, wallet, now) writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-rocket-mq-open" + roomID := "room-rocket-mq-launch" ownerID := int64(901) createRocketRoom(t, ctx, svc, roomID, ownerID, 9009) resp, err := svc.SendGift(ctx, &roomv1.SendGiftRequest{ @@ -302,14 +316,19 @@ func TestRoomRocketLaunchDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { t.Fatalf("ignite rocket failed: %v", err) } rocket := resp.GetRocket() + if len(rocket.GetPendingLaunches()) != 1 { + t.Fatalf("ignite should create one pending launch: %+v", rocket) + } + pending := rocket.GetPendingLaunches()[0] due := roommq.RoomRocketLaunchDueMessage{ MessageType: roommq.MessageTypeRoomRocketLaunchDue, AppCode: appcode.Default, RoomID: roomID, - RocketID: rocket.GetRocketId(), - Level: rocket.GetCurrentLevel(), - LaunchAtMS: rocket.GetLaunchAtMs(), - CommandID: "cmd_room_rocket_launch_" + rocket.GetRocketId(), + RocketID: pending.GetRocketId(), + Level: pending.GetLevel(), + LaunchAtMS: pending.GetLaunchAtMs(), + ResetAtMS: pending.GetResetAtMs(), + CommandID: "cmd_room_rocket_launch_" + pending.GetRocketId(), } if err := svc.HandleRoomRocketLaunchDue(ctx, due); err == nil { @@ -317,7 +336,7 @@ func TestRoomRocketLaunchDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { } now.now = now.now.Add(time.Second) if err := svc.HandleRoomRocketLaunchDue(ctx, due); err != nil { - t.Fatalf("due delayed message should open rocket after retry: %v", err) + t.Fatalf("due delayed message should launch rocket after retry: %v", err) } info, err := svc.GetRoomRocket(ctx, &roomv1.GetRoomRocketRequest{ RoomId: roomID, @@ -330,11 +349,11 @@ func TestRoomRocketLaunchDueEarlyMessageDoesNotPoisonCommandID(t *testing.T) { if err != nil { t.Fatalf("get rocket failed: %v", err) } - if info.GetRocket().GetState().GetStatus() != state.RocketStatusCharging || info.GetRocket().GetState().GetCurrentLevel() != 2 { - t.Fatalf("rocket should open once after early retry: %+v", info.GetRocket().GetState()) + if info.GetRocket().GetState().GetStatus() != state.RocketStatusCharging || info.GetRocket().GetState().GetCurrentLevel() != 2 || len(info.GetRocket().GetState().GetPendingLaunches()) != 0 { + t.Fatalf("rocket should launch once after early retry: %+v", info.GetRocket().GetState()) } if len(wallet.grants) == 0 { - t.Fatal("open should grant configured rewards after retry") + t.Fatal("launch should grant configured rewards after retry") } } @@ -348,7 +367,7 @@ func TestRoomRocketLaunchGrantsLockedTop1AndIgniterAfterLeave(t *testing.T) { svc := newRocketTestService(t, repository, wallet, now) writeRocketConfig(t, ctx, repository, rocketConfigForTest(100, 1_000)) - roomID := "room-rocket-open" + roomID := "room-rocket-launch" ownerID := int64(301) igniterID := int64(302) createRocketRoom(t, ctx, svc, roomID, ownerID, 9002) @@ -369,7 +388,7 @@ func TestRoomRocketLaunchGrantsLockedTop1AndIgniterAfterLeave(t *testing.T) { now.now = now.now.Add(1100 * time.Millisecond) if err := svc.SweepRoomRocketLaunchings(ctx); err != nil { - t.Fatalf("sweep room rocket openings failed: %v", err) + t.Fatalf("sweep room rocket launches failed: %v", err) } if !hasRocketGrant(wallet.grants, igniterID, 2001) || !hasRocketGrant(wallet.grants, igniterID, 3001) { @@ -388,14 +407,14 @@ func TestRoomRocketLaunchGrantsLockedTop1AndIgniterAfterLeave(t *testing.T) { ViewerUserId: ownerID, }) if err != nil { - t.Fatalf("get rocket after open failed: %v", err) + t.Fatalf("get rocket after launch failed: %v", err) } stateView := info.GetRocket().GetState() - if stateView.GetCurrentLevel() != 2 || stateView.GetStatus() != state.RocketStatusCharging { - t.Fatalf("opened rocket must advance to next idle level: %+v", stateView) + if stateView.GetCurrentLevel() != 2 || stateView.GetStatus() != state.RocketStatusCharging || len(stateView.GetPendingLaunches()) != 0 { + t.Fatalf("launch rocket must keep current next-level progress and clear pending launch: %+v", stateView) } if len(stateView.GetLastRewards()) != 3 { - t.Fatalf("opened rocket must retain in-room, top1 and igniter grants for client display: %+v", stateView.GetLastRewards()) + t.Fatalf("launch rocket must retain in-room, top1 and igniter grants for client display: %+v", stateView.GetLastRewards()) } if got := rocketRewardUserIDs(stateView.GetLastRewards()); !slices.Equal(got, []int64{301, 302, 302}) { t.Fatalf("reward users mismatch: got %+v rewards=%+v", got, stateView.GetLastRewards()) @@ -429,8 +448,8 @@ func TestRoomRocketUTCResetCancelsCrossDayIgnited(t *testing.T) { if err != nil { t.Fatalf("send cross-day gift failed: %v", err) } - if fillResp.GetRocket().GetStatus() != state.RocketStatusIgnited || fillResp.GetRocket().GetLaunchAtMs() <= fillResp.GetRocket().GetResetAtMs() { - t.Fatalf("fixture must create a ignited whose open time crosses UTC reset: %+v", fillResp.GetRocket()) + if len(fillResp.GetRocket().GetPendingLaunches()) != 1 || fillResp.GetRocket().GetPendingLaunches()[0].GetLaunchAtMs() <= fillResp.GetRocket().GetResetAtMs() { + t.Fatalf("fixture must create a pending launch whose launch time crosses UTC reset: %+v", fillResp.GetRocket()) } now.now = time.Date(2026, 5, 21, 0, 0, 2, 0, time.UTC) @@ -486,16 +505,16 @@ func newRocketTestServiceWithScheduler(t *testing.T, repository *mysqltest.Repos }, router.NewMemoryDirectory(), repository, wallet, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) } -func rocketConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomRocketConfig { - levels := make([]roomservice.RoomRocketLevelConfig, 0, 7) - for level := int32(1); level <= 7; level++ { +func rocketConfigForTest(threshold int64, launchDelayMS int64) roomservice.RoomRocketConfig { + levels := make([]roomservice.RoomRocketLevelConfig, 0, 5) + for level := int32(1); level <= 5; level++ { levels = append(levels, roomservice.RoomRocketLevelConfig{ Level: level, FuelThreshold: threshold + int64(level-1)*100, CoverURL: fmt.Sprintf("https://example.test/rocket/%d-cover.png", level), AnimationURL: fmt.Sprintf("https://example.test/rocket/%d-idle.webp", level), - LaunchAnimationURL: fmt.Sprintf("https://example.test/rocket/%d-opening.webp", level), - LaunchedImageURL: fmt.Sprintf("https://example.test/rocket/%d-open.png", level), + LaunchAnimationURL: fmt.Sprintf("https://example.test/rocket/%d-launch.webp", level), + LaunchedImageURL: fmt.Sprintf("https://example.test/rocket/%d-launched.png", level), InRoomRewards: []roomservice.RoomRocketRewardItem{{ RewardItemID: fmt.Sprintf("level-%d-in-room", level), ResourceGroupID: 1000 + int64(level), @@ -523,8 +542,8 @@ func rocketConfigForTest(threshold int64, openDelayMS int64) roomservice.RoomRoc AppCode: appcode.Default, Enabled: true, ConfigVersion: 1, - FuelSource: "gift_point_added", - LaunchDelayMS: openDelayMS, + FuelSource: "heat_value", + LaunchDelayMS: launchDelayMS, BroadcastEnabled: true, BroadcastScope: "region", RewardStackPolicy: "allow_stack", diff --git a/services/room-service/internal/room/state/state.go b/services/room-service/internal/room/state/state.go index bfe84bfb..526aa5a7 100644 --- a/services/room-service/internal/room/state/state.go +++ b/services/room-service/internal/room/state/state.go @@ -166,7 +166,7 @@ type RocketPendingLaunch struct { IgniterUserID int64 // ConfigVersion 锁定本枚火箭的配置版本,CoverURL 给区域飘屏和客户端展示使用。 ConfigVersion int64 - CoverURL string + CoverURL string } // RocketState 保存 Room Cell 内当前火箭进度和最近一次发射结果。 From 471186a73c59fff0c8806f95a89c392f4b2485de Mon Sep 17 00:00:00 2001 From: zhx Date: Sat, 6 Jun 2026 00:19:43 +0800 Subject: [PATCH 23/28] Handle room pin scope and user region sync --- api/proto/events/room/v1/events.pb.go | 15 +- api/proto/events/room/v1/events.proto | 1 + api/proto/room/v1/room.pb.go | 69 +- api/proto/room/v1/room.proto | 6 + api/proto/user/v1/host.pb.go | 387 +++++++---- api/proto/user/v1/host.proto | 16 +- api/proto/user/v1/host_grpc.pb.go | 38 ++ api/proto/user/v1/user.pb.go | 642 ++++++++++-------- api/proto/user/v1/user.proto | 12 +- api/proto/user/v1/user_grpc.pb.go | 38 ++ docs/房间区域置顶.md | 335 ++++++++- server/admin/cmd/server/main.go | 26 +- .../admin/configs/config.tencent.example.yaml | 2 +- server/admin/docs/权限管理.md | 4 +- .../internal/integration/roomclient/client.go | 12 + .../internal/integration/userclient/client.go | 64 +- .../admin/internal/modules/appuser/handler.go | 2 +- .../admin/internal/modules/appuser/service.go | 122 +--- .../admin/internal/modules/hostorg/handler.go | 22 +- .../admin/internal/modules/hostorg/reader.go | 3 + .../admin/internal/modules/hostorg/request.go | 7 +- .../admin/internal/modules/hostorg/routes.go | 1 + .../admin/internal/modules/hostorg/service.go | 15 +- .../internal/modules/resource/handler.go | 57 +- .../internal/modules/roomadmin/handler.go | 5 +- .../admin/internal/modules/roomadmin/pin.go | 48 +- .../internal/modules/roomadmin/pin_test.go | 22 +- .../internal/modules/roomadmin/request.go | 4 + .../internal/modules/roomadmin/service.go | 45 ++ server/admin/internal/repository/seed.go | 3 +- .../configs/config.docker.yaml | 5 + .../configs/config.tencent.example.yaml | 5 + services/activity-service/configs/config.yaml | 5 + services/activity-service/internal/app/app.go | 64 +- .../internal/config/config.go | 26 +- .../internal/config/config_test.go | 5 +- .../configs/config.tencent.example.yaml | 2 +- .../internal/config/config_test.go | 27 + .../internal/transport/http/response_test.go | 3 + .../http/userapi/host_agency_handler.go | 2 - .../room-service/configs/config.docker.yaml | 5 + .../configs/config.tencent.example.yaml | 5 + services/room-service/configs/config.yaml | 5 + .../deploy/mysql/initdb/001_room_service.sql | 7 +- services/room-service/internal/app/app.go | 27 +- .../room-service/internal/config/config.go | 26 +- .../internal/integration/tencent_im.go | 1 + .../internal/room/service/admin.go | 1 + .../internal/room/service/admin_config_pin.go | 52 +- .../internal/room/service/gift.go | 1 + .../internal/room/service/list.go | 36 +- .../internal/room/service/list_score_test.go | 18 + .../internal/room/service/pin_test.go | 84 +++ .../internal/room/service/repository.go | 55 +- .../internal/room/service/user_region_sync.go | 74 ++ .../room/service/user_region_sync_test.go | 92 +++ .../internal/storage/mysql/repository.go | 182 +++-- .../internal/testutil/mysqltest/mysqltest.go | 41 +- .../mysql/initdb/001_statistics_service.sql | 1 + .../statistics-service/internal/app/app.go | 31 + .../internal/app/local_flow_test.go | 30 +- .../internal/storage/mysql/query.go | 11 +- .../internal/storage/mysql/repository.go | 17 +- services/user-service/internal/app/app.go | 1 + .../user-service/internal/domain/host/host.go | 5 + .../user-service/internal/domain/user/user.go | 4 +- .../internal/service/host/commands.go | 24 +- .../internal/service/host/service.go | 33 +- .../internal/service/host/service_test.go | 95 ++- .../service/user/country_outbox_test.go | 86 +++ .../internal/service/user/moderation.go | 17 +- .../internal/service/user/moderation_test.go | 24 +- .../internal/service/user/profile.go | 137 +++- .../internal/service/user/profile_test.go | 129 ++++ .../internal/service/user/service.go | 21 +- .../internal/storage/mysql/host/admin.go | 105 ++- .../storage/mysql/host/invitations.go | 82 +-- .../storage/mysql/region/rebuild_tasks.go | 63 +- .../mysql/region/rebuild_tasks_test.go | 85 +++ .../internal/storage/mysql/user/repository.go | 118 +++- .../internal/testutil/mysqltest/mysqltest.go | 2 +- .../internal/transport/grpc/host_admin.go | 23 +- .../internal/transport/grpc/server.go | 34 +- .../internal/service/wallet/service_test.go | 2 +- .../internal/storage/mysql/repository.go | 2 +- tools/migrate-room-visible-region/main.go | 163 +++++ 86 files changed, 3390 insertions(+), 834 deletions(-) create mode 100644 services/game-service/internal/config/config_test.go create mode 100644 services/room-service/internal/room/service/list_score_test.go create mode 100644 services/room-service/internal/room/service/user_region_sync.go create mode 100644 services/room-service/internal/room/service/user_region_sync_test.go create mode 100644 services/user-service/internal/service/user/country_outbox_test.go create mode 100644 services/user-service/internal/service/user/profile_test.go create mode 100644 services/user-service/internal/storage/mysql/region/rebuild_tasks_test.go create mode 100644 tools/migrate-room-visible-region/main.go diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index d5b88b7a..3c87687e 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -1175,6 +1175,7 @@ type RoomGiftSent struct { VisibleRegionId int64 `protobuf:"varint,7,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` CommandId string `protobuf:"bytes,8,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` PoolId string `protobuf:"bytes,9,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + CoinSpent int64 `protobuf:"varint,10,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1272,6 +1273,13 @@ func (x *RoomGiftSent) GetPoolId() string { return "" } +func (x *RoomGiftSent) GetCoinSpent() int64 { + if x != nil { + return x.CoinSpent + } + return 0 +} + // RoomHeatChanged 表达热度变化结果。 type RoomHeatChanged struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -2052,7 +2060,7 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"\\\n" + "\x10RoomUserUnbanned\x12\"\n" + "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"\xc3\x02\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"\xe2\x02\n" + "\fRoomGiftSent\x12$\n" + "\x0esender_user_id\x18\x01 \x01(\x03R\fsenderUserId\x12$\n" + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x17\n" + @@ -2065,7 +2073,10 @@ const file_proto_events_room_v1_events_proto_rawDesc = "" + "\x11visible_region_id\x18\a \x01(\x03R\x0fvisibleRegionId\x12\x1d\n" + "\n" + "command_id\x18\b \x01(\tR\tcommandId\x12\x17\n" + - "\apool_id\x18\t \x01(\tR\x06poolId\"J\n" + + "\apool_id\x18\t \x01(\tR\x06poolId\x12\x1d\n" + + "\n" + + "coin_spent\x18\n" + + " \x01(\x03R\tcoinSpent\"J\n" + "\x0fRoomHeatChanged\x12\x14\n" + "\x05delta\x18\x01 \x01(\x03R\x05delta\x12!\n" + "\fcurrent_heat\x18\x02 \x01(\x03R\vcurrentHeat\"_\n" + diff --git a/api/proto/events/room/v1/events.proto b/api/proto/events/room/v1/events.proto index 7b4ec45b..63f5b083 100644 --- a/api/proto/events/room/v1/events.proto +++ b/api/proto/events/room/v1/events.proto @@ -153,6 +153,7 @@ message RoomGiftSent { int64 visible_region_id = 7; string command_id = 8; string pool_id = 9; + int64 coin_spent = 10; } // RoomHeatChanged 表达热度变化结果。 diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 86dccba6..03e7d8b7 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -2228,6 +2228,7 @@ type AdminRoomPin struct { CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` UpdatedAtMs int64 `protobuf:"varint,12,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` Room *AdminRoomPinRoom `protobuf:"bytes,13,opt,name=room,proto3" json:"room,omitempty"` + PinType string `protobuf:"bytes,14,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2353,6 +2354,13 @@ func (x *AdminRoomPin) GetRoom() *AdminRoomPinRoom { return nil } +func (x *AdminRoomPin) GetPinType() string { + if x != nil { + return x.PinType + } + return "" +} + type AdminListRoomPinsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` @@ -2361,6 +2369,7 @@ type AdminListRoomPinsRequest struct { Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + PinType string `protobuf:"bytes,7,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2437,6 +2446,13 @@ func (x *AdminListRoomPinsRequest) GetVisibleRegionId() int64 { return 0 } +func (x *AdminListRoomPinsRequest) GetPinType() string { + if x != nil { + return x.PinType + } + return "" +} + type AdminListRoomPinsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Pins []*AdminRoomPin `protobuf:"bytes,1,rep,name=pins,proto3" json:"pins,omitempty"` @@ -2504,6 +2520,9 @@ type AdminCreateRoomPinRequest struct { Weight int64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` DurationDays int64 `protobuf:"varint,4,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` AdminId uint64 `protobuf:"varint,5,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + PinnedAtMs int64 `protobuf:"varint,6,opt,name=pinned_at_ms,json=pinnedAtMs,proto3" json:"pinned_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,7,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + PinType string `protobuf:"bytes,8,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -2573,6 +2592,27 @@ func (x *AdminCreateRoomPinRequest) GetAdminId() uint64 { return 0 } +func (x *AdminCreateRoomPinRequest) GetPinnedAtMs() int64 { + if x != nil { + return x.PinnedAtMs + } + return 0 +} + +func (x *AdminCreateRoomPinRequest) GetExpiresAtMs() int64 { + if x != nil { + return x.ExpiresAtMs + } + return 0 +} + +func (x *AdminCreateRoomPinRequest) GetPinType() string { + if x != nil { + return x.PinType + } + return "" +} + type AdminCreateRoomPinResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Pin *AdminRoomPin `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` @@ -4480,6 +4520,7 @@ type AdminListRoomsRequest struct { VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` SortBy string `protobuf:"bytes,7,opt,name=sort_by,json=sortBy,proto3" json:"sort_by,omitempty"` SortDirection string `protobuf:"bytes,8,opt,name=sort_direction,json=sortDirection,proto3" json:"sort_direction,omitempty"` + OwnerUserId int64 `protobuf:"varint,9,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -4570,6 +4611,13 @@ func (x *AdminListRoomsRequest) GetSortDirection() string { return "" } +func (x *AdminListRoomsRequest) GetOwnerUserId() int64 { + if x != nil { + return x.OwnerUserId + } + return 0 +} + type AdminListRoomsResponse struct { state protoimpl.MessageState `protogen:"open.v1"` Rooms []*AdminRoomListItem `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` @@ -9460,7 +9508,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\x12\x14\n" + "\x05title\x18\x05 \x01(\tR\x05title\x12\x1b\n" + "\tcover_url\x18\x06 \x01(\tR\bcoverUrl\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\"\xe0\x03\n" + + "\x06status\x18\a \x01(\tR\x06status\"\xfb\x03\n" + "\fAdminRoomPin\x12\x0e\n" + "\x02id\x18\x01 \x01(\x03R\x02id\x12*\n" + "\x11visible_region_id\x18\x02 \x01(\x03R\x0fvisibleRegionId\x12\x17\n" + @@ -9476,24 +9524,30 @@ const file_proto_room_v1_room_proto_rawDesc = "" + " \x01(\x04R\x12cancelledByAdminId\x12\"\n" + "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\x12\"\n" + "\rupdated_at_ms\x18\f \x01(\x03R\vupdatedAtMs\x123\n" + - "\x04room\x18\r \x01(\v2\x1f.hyapp.room.v1.AdminRoomPinRoomR\x04room\"\xd9\x01\n" + + "\x04room\x18\r \x01(\v2\x1f.hyapp.room.v1.AdminRoomPinRoomR\x04room\x12\x19\n" + + "\bpin_type\x18\x0e \x01(\tR\apinType\"\xf4\x01\n" + "\x18AdminListRoomPinsRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x12\n" + "\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" + "\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x18\n" + "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x16\n" + "\x06status\x18\x05 \x01(\tR\x06status\x12*\n" + - "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\"\x88\x01\n" + + "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\x12\x19\n" + + "\bpin_type\x18\a \x01(\tR\apinType\"\x88\x01\n" + "\x19AdminListRoomPinsResponse\x12/\n" + "\x04pins\x18\x01 \x03(\v2\x1b.hyapp.room.v1.AdminRoomPinR\x04pins\x12\x14\n" + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xbc\x01\n" + + "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x9d\x02\n" + "\x19AdminCreateRoomPinRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x16\n" + "\x06weight\x18\x03 \x01(\x03R\x06weight\x12#\n" + "\rduration_days\x18\x04 \x01(\x03R\fdurationDays\x12\x19\n" + - "\badmin_id\x18\x05 \x01(\x04R\aadminId\"q\n" + + "\badmin_id\x18\x05 \x01(\x04R\aadminId\x12 \n" + + "\fpinned_at_ms\x18\x06 \x01(\x03R\n" + + "pinnedAtMs\x12\"\n" + + "\rexpires_at_ms\x18\a \x01(\x03R\vexpiresAtMs\x12\x19\n" + + "\bpin_type\x18\b \x01(\tR\apinType\"q\n" + "\x1aAdminCreateRoomPinResponse\x12-\n" + "\x03pin\x18\x01 \x01(\v2\x1b.hyapp.room.v1.AdminRoomPinR\x03pin\x12$\n" + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"}\n" + @@ -9660,7 +9714,7 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\n" + "sort_score\x18\x11 \x01(\x03R\tsortScore\x12\"\n" + "\rcreated_at_ms\x18\x12 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x13 \x01(\x03R\vupdatedAtMs\"\x96\x02\n" + + "\rupdated_at_ms\x18\x13 \x01(\x03R\vupdatedAtMs\"\xba\x02\n" + "\x15AdminListRoomsRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x12\n" + "\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" + @@ -9669,7 +9723,8 @@ const file_proto_room_v1_room_proto_rawDesc = "" + "\x06status\x18\x05 \x01(\tR\x06status\x12*\n" + "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\x12\x17\n" + "\asort_by\x18\a \x01(\tR\x06sortBy\x12%\n" + - "\x0esort_direction\x18\b \x01(\tR\rsortDirection\"\x8c\x01\n" + + "\x0esort_direction\x18\b \x01(\tR\rsortDirection\x12\"\n" + + "\rowner_user_id\x18\t \x01(\x03R\vownerUserId\"\x8c\x01\n" + "\x16AdminListRoomsResponse\x126\n" + "\x05rooms\x18\x01 \x03(\v2 .hyapp.room.v1.AdminRoomListItemR\x05rooms\x12\x14\n" + "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index 997b7013..79bd073c 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -279,6 +279,7 @@ message AdminRoomPin { int64 created_at_ms = 11; int64 updated_at_ms = 12; AdminRoomPinRoom room = 13; + string pin_type = 14; } message AdminListRoomPinsRequest { @@ -288,6 +289,7 @@ message AdminListRoomPinsRequest { string keyword = 4; string status = 5; int64 visible_region_id = 6; + string pin_type = 7; } message AdminListRoomPinsResponse { @@ -302,6 +304,9 @@ message AdminCreateRoomPinRequest { int64 weight = 3; int64 duration_days = 4; uint64 admin_id = 5; + int64 pinned_at_ms = 6; + int64 expires_at_ms = 7; + string pin_type = 8; } message AdminCreateRoomPinResponse { @@ -540,6 +545,7 @@ message AdminListRoomsRequest { int64 visible_region_id = 6; string sort_by = 7; string sort_direction = 8; + int64 owner_user_id = 9; } message AdminListRoomsResponse { diff --git a/api/proto/user/v1/host.pb.go b/api/proto/user/v1/host.pb.go index 749e9a4b..57d6d79e 100644 --- a/api/proto/user/v1/host.pb.go +++ b/api/proto/user/v1/host.pb.go @@ -141,20 +141,21 @@ func (x *HostProfile) GetCurrentAgencyOwnerUserId() int64 { // Agency 是主播组织,owner 自动拥有 host 身份和 owner membership。 type Agency struct { - state protoimpl.MessageState `protogen:"open.v1"` - AgencyId int64 `protobuf:"varint,1,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` - OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - ParentBdUserId int64 `protobuf:"varint,4,opt,name=parent_bd_user_id,json=parentBdUserId,proto3" json:"parent_bd_user_id,omitempty"` - Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - JoinEnabled bool `protobuf:"varint,7,opt,name=join_enabled,json=joinEnabled,proto3" json:"join_enabled,omitempty"` - MaxHosts int32 `protobuf:"varint,8,opt,name=max_hosts,json=maxHosts,proto3" json:"max_hosts,omitempty"` - CreatedByUserId int64 `protobuf:"varint,9,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,11,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - Avatar string `protobuf:"bytes,12,opt,name=avatar,proto3" json:"avatar,omitempty"` - HostCount int32 `protobuf:"varint,13,opt,name=host_count,json=hostCount,proto3" json:"host_count,omitempty"` + state protoimpl.MessageState `protogen:"open.v1"` + AgencyId int64 `protobuf:"varint,1,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + ParentBdUserId int64 `protobuf:"varint,4,opt,name=parent_bd_user_id,json=parentBdUserId,proto3" json:"parent_bd_user_id,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + JoinEnabled bool `protobuf:"varint,7,opt,name=join_enabled,json=joinEnabled,proto3" json:"join_enabled,omitempty"` + // Deprecated: Agency 不再限制主播数量,该字段仅为历史兼容保留。 + MaxHosts int32 `protobuf:"varint,8,opt,name=max_hosts,json=maxHosts,proto3" json:"max_hosts,omitempty"` + CreatedByUserId int64 `protobuf:"varint,9,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,11,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + Avatar string `protobuf:"bytes,12,opt,name=avatar,proto3" json:"avatar,omitempty"` + HostCount int32 `protobuf:"varint,13,opt,name=host_count,json=hostCount,proto3" json:"host_count,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3315,7 +3316,6 @@ type CreateBDLeaderRequest struct { AdminUserId int64 `protobuf:"varint,3,opt,name=admin_user_id,json=adminUserId,proto3" json:"admin_user_id,omitempty"` TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -3385,13 +3385,6 @@ func (x *CreateBDLeaderRequest) GetReason() string { return "" } -func (x *CreateBDLeaderRequest) GetRegionId() int64 { - if x != nil { - return x.RegionId - } - return 0 -} - type CreateBDLeaderResponse struct { state protoimpl.MessageState `protogen:"open.v1"` BdProfile *BDProfile `protobuf:"bytes,1,opt,name=bd_profile,json=bdProfile,proto3" json:"bd_profile,omitempty"` @@ -3949,10 +3942,11 @@ type CreateAgencyRequest struct { ParentBdUserId int64 `protobuf:"varint,5,opt,name=parent_bd_user_id,json=parentBdUserId,proto3" json:"parent_bd_user_id,omitempty"` Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` JoinEnabled bool `protobuf:"varint,7,opt,name=join_enabled,json=joinEnabled,proto3" json:"join_enabled,omitempty"` - MaxHosts int32 `protobuf:"varint,8,opt,name=max_hosts,json=maxHosts,proto3" json:"max_hosts,omitempty"` - Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // Deprecated: Agency 不再限制主播数量,服务端会忽略该字段。 + MaxHosts int32 `protobuf:"varint,8,opt,name=max_hosts,json=maxHosts,proto3" json:"max_hosts,omitempty"` + Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *CreateAgencyRequest) Reset() { @@ -4228,6 +4222,126 @@ func (x *CloseAgencyResponse) GetAgency() *Agency { return nil } +type DeleteAgencyRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AdminUserId int64 `protobuf:"varint,3,opt,name=admin_user_id,json=adminUserId,proto3" json:"admin_user_id,omitempty"` + AgencyId int64 `protobuf:"varint,4,opt,name=agency_id,json=agencyId,proto3" json:"agency_id,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteAgencyRequest) Reset() { + *x = DeleteAgencyRequest{} + mi := &file_proto_user_v1_host_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteAgencyRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteAgencyRequest) ProtoMessage() {} + +func (x *DeleteAgencyRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_proto_msgTypes[61] + 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 DeleteAgencyRequest.ProtoReflect.Descriptor instead. +func (*DeleteAgencyRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{61} +} + +func (x *DeleteAgencyRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *DeleteAgencyRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *DeleteAgencyRequest) GetAdminUserId() int64 { + if x != nil { + return x.AdminUserId + } + return 0 +} + +func (x *DeleteAgencyRequest) GetAgencyId() int64 { + if x != nil { + return x.AgencyId + } + return 0 +} + +func (x *DeleteAgencyRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type DeleteAgencyResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Agency *Agency `protobuf:"bytes,1,opt,name=agency,proto3" json:"agency,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteAgencyResponse) Reset() { + *x = DeleteAgencyResponse{} + mi := &file_proto_user_v1_host_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteAgencyResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteAgencyResponse) ProtoMessage() {} + +func (x *DeleteAgencyResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_host_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 DeleteAgencyResponse.ProtoReflect.Descriptor instead. +func (*DeleteAgencyResponse) Descriptor() ([]byte, []int) { + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{62} +} + +func (x *DeleteAgencyResponse) GetAgency() *Agency { + if x != nil { + return x.Agency + } + return nil +} + type SetAgencyJoinEnabledRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` @@ -4242,7 +4356,7 @@ type SetAgencyJoinEnabledRequest struct { func (x *SetAgencyJoinEnabledRequest) Reset() { *x = SetAgencyJoinEnabledRequest{} - mi := &file_proto_user_v1_host_proto_msgTypes[61] + mi := &file_proto_user_v1_host_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4254,7 +4368,7 @@ func (x *SetAgencyJoinEnabledRequest) String() string { func (*SetAgencyJoinEnabledRequest) ProtoMessage() {} func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[61] + mi := &file_proto_user_v1_host_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4267,7 +4381,7 @@ func (x *SetAgencyJoinEnabledRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledRequest.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{61} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{63} } func (x *SetAgencyJoinEnabledRequest) GetMeta() *RequestMeta { @@ -4321,7 +4435,7 @@ type SetAgencyJoinEnabledResponse struct { func (x *SetAgencyJoinEnabledResponse) Reset() { *x = SetAgencyJoinEnabledResponse{} - mi := &file_proto_user_v1_host_proto_msgTypes[62] + mi := &file_proto_user_v1_host_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4333,7 +4447,7 @@ func (x *SetAgencyJoinEnabledResponse) String() string { func (*SetAgencyJoinEnabledResponse) ProtoMessage() {} func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_host_proto_msgTypes[62] + mi := &file_proto_user_v1_host_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4346,7 +4460,7 @@ func (x *SetAgencyJoinEnabledResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetAgencyJoinEnabledResponse.ProtoReflect.Descriptor instead. func (*SetAgencyJoinEnabledResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_host_proto_rawDescGZIP(), []int{62} + return file_proto_user_v1_host_proto_rawDescGZIP(), []int{64} } func (x *SetAgencyJoinEnabledResponse) GetAgency() *Agency { @@ -4650,15 +4764,14 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\tagency_id\x18\x02 \x01(\x03R\bagencyId\x12\x16\n" + "\x06status\x18\x03 \x01(\tR\x06status\"e\n" + "\x1dGetAgencyApplicationsResponse\x12D\n" + - "\fapplications\x18\x01 \x03(\v2 .hyapp.user.v1.AgencyApplicationR\fapplications\"\xe5\x01\n" + + "\fapplications\x18\x01 \x03(\v2 .hyapp.user.v1.AgencyApplicationR\fapplications\"\xc8\x01\n" + "\x15CreateBDLeaderRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + "\n" + "command_id\x18\x02 \x01(\tR\tcommandId\x12\"\n" + "\radmin_user_id\x18\x03 \x01(\x03R\vadminUserId\x12$\n" + "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06reason\x18\x05 \x01(\tR\x06reason\x12\x1b\n" + - "\tregion_id\x18\x06 \x01(\x03R\bregionId\"Q\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"Q\n" + "\x16CreateBDLeaderResponse\x127\n" + "\n" + "bd_profile\x18\x01 \x01(\v2\x18.hyapp.user.v1.BDProfileR\tbdProfile\"\xf5\x01\n" + @@ -4728,6 +4841,15 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\tagency_id\x18\x04 \x01(\x03R\bagencyId\x12\x16\n" + "\x06reason\x18\x05 \x01(\tR\x06reason\"D\n" + "\x13CloseAgencyResponse\x12-\n" + + "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency\"\xbd\x01\n" + + "\x13DeleteAgencyRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + + "\n" + + "command_id\x18\x02 \x01(\tR\tcommandId\x12\"\n" + + "\radmin_user_id\x18\x03 \x01(\x03R\vadminUserId\x12\x1b\n" + + "\tagency_id\x18\x04 \x01(\x03R\bagencyId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"E\n" + + "\x14DeleteAgencyResponse\x12-\n" + "\x06agency\x18\x01 \x01(\v2\x15.hyapp.user.v1.AgencyR\x06agency\"\xe8\x01\n" + "\x1bSetAgencyJoinEnabledRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x1d\n" + @@ -4758,7 +4880,7 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\tGetAgency\x12\x1f.hyapp.user.v1.GetAgencyRequest\x1a .hyapp.user.v1.GetAgencyResponse\x12x\n" + "\x17CheckBusinessCapability\x12-.hyapp.user.v1.CheckBusinessCapabilityRequest\x1a..hyapp.user.v1.CheckBusinessCapabilityResponse\x12c\n" + "\x10GetAgencyMembers\x12&.hyapp.user.v1.GetAgencyMembersRequest\x1a'.hyapp.user.v1.GetAgencyMembersResponse\x12r\n" + - "\x15GetAgencyApplications\x12+.hyapp.user.v1.GetAgencyApplicationsRequest\x1a,.hyapp.user.v1.GetAgencyApplicationsResponse2\x8b\x06\n" + + "\x15GetAgencyApplications\x12+.hyapp.user.v1.GetAgencyApplicationsRequest\x1a,.hyapp.user.v1.GetAgencyApplicationsResponse2\xe4\x06\n" + "\x14UserHostAdminService\x12]\n" + "\x0eCreateBDLeader\x12$.hyapp.user.v1.CreateBDLeaderRequest\x1a%.hyapp.user.v1.CreateBDLeaderResponse\x12K\n" + "\bCreateBD\x12\x1e.hyapp.user.v1.CreateBDRequest\x1a\x1f.hyapp.user.v1.CreateBDResponse\x12T\n" + @@ -4766,7 +4888,8 @@ const file_proto_user_v1_host_proto_rawDesc = "" + "\x10CreateCoinSeller\x12&.hyapp.user.v1.CreateCoinSellerRequest\x1a'.hyapp.user.v1.CreateCoinSellerResponse\x12l\n" + "\x13SetCoinSellerStatus\x12).hyapp.user.v1.SetCoinSellerStatusRequest\x1a*.hyapp.user.v1.SetCoinSellerStatusResponse\x12W\n" + "\fCreateAgency\x12\".hyapp.user.v1.CreateAgencyRequest\x1a#.hyapp.user.v1.CreateAgencyResponse\x12T\n" + - "\vCloseAgency\x12!.hyapp.user.v1.CloseAgencyRequest\x1a\".hyapp.user.v1.CloseAgencyResponse\x12o\n" + + "\vCloseAgency\x12!.hyapp.user.v1.CloseAgencyRequest\x1a\".hyapp.user.v1.CloseAgencyResponse\x12W\n" + + "\fDeleteAgency\x12\".hyapp.user.v1.DeleteAgencyRequest\x1a#.hyapp.user.v1.DeleteAgencyResponse\x12o\n" + "\x14SetAgencyJoinEnabled\x12*.hyapp.user.v1.SetAgencyJoinEnabledRequest\x1a+.hyapp.user.v1.SetAgencyJoinEnabledResponseB&Z$hyapp.local/api/proto/user/v1;userv1b\x06proto3" var ( @@ -4781,7 +4904,7 @@ func file_proto_user_v1_host_proto_rawDescGZIP() []byte { return file_proto_user_v1_host_proto_rawDescData } -var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 63) +var file_proto_user_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 65) var file_proto_user_v1_host_proto_goTypes = []any{ (*HostProfile)(nil), // 0: hyapp.user.v1.HostProfile (*Agency)(nil), // 1: hyapp.user.v1.Agency @@ -4844,132 +4967,138 @@ var file_proto_user_v1_host_proto_goTypes = []any{ (*CreateAgencyResponse)(nil), // 58: hyapp.user.v1.CreateAgencyResponse (*CloseAgencyRequest)(nil), // 59: hyapp.user.v1.CloseAgencyRequest (*CloseAgencyResponse)(nil), // 60: hyapp.user.v1.CloseAgencyResponse - (*SetAgencyJoinEnabledRequest)(nil), // 61: hyapp.user.v1.SetAgencyJoinEnabledRequest - (*SetAgencyJoinEnabledResponse)(nil), // 62: hyapp.user.v1.SetAgencyJoinEnabledResponse - (*RequestMeta)(nil), // 63: hyapp.user.v1.RequestMeta + (*DeleteAgencyRequest)(nil), // 61: hyapp.user.v1.DeleteAgencyRequest + (*DeleteAgencyResponse)(nil), // 62: hyapp.user.v1.DeleteAgencyResponse + (*SetAgencyJoinEnabledRequest)(nil), // 63: hyapp.user.v1.SetAgencyJoinEnabledRequest + (*SetAgencyJoinEnabledResponse)(nil), // 64: hyapp.user.v1.SetAgencyJoinEnabledResponse + (*RequestMeta)(nil), // 65: hyapp.user.v1.RequestMeta } var file_proto_user_v1_host_proto_depIdxs = []int32{ - 63, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 0: hyapp.user.v1.SearchAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 1: hyapp.user.v1.SearchAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 63, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 2: hyapp.user.v1.ApplyToAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 3: hyapp.user.v1.ApplyToAgencyResponse.application:type_name -> hyapp.user.v1.AgencyApplication - 63, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 4: hyapp.user.v1.ReviewAgencyApplicationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 5: hyapp.user.v1.ReviewAgencyApplicationResponse.application:type_name -> hyapp.user.v1.AgencyApplication 0, // 6: hyapp.user.v1.ReviewAgencyApplicationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 7: hyapp.user.v1.ReviewAgencyApplicationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 63, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 8: hyapp.user.v1.KickAgencyHostRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 9: hyapp.user.v1.KickAgencyHostResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 0, // 10: hyapp.user.v1.KickAgencyHostResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 63, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 11: hyapp.user.v1.InviteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 12: hyapp.user.v1.InviteAgencyResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 63, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 13: hyapp.user.v1.InviteBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 14: hyapp.user.v1.InviteBDResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation - 63, // 15: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 15: hyapp.user.v1.ListBDLeaderBDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 16: hyapp.user.v1.ListBDLeaderBDsResponse.bd_profiles:type_name -> hyapp.user.v1.BDProfile - 63, // 17: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 17: hyapp.user.v1.ListBDLeaderAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 18: hyapp.user.v1.ListBDLeaderAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 63, // 19: hyapp.user.v1.ListBDAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 19: hyapp.user.v1.ListBDAgenciesRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 20: hyapp.user.v1.ListBDAgenciesResponse.agencies:type_name -> hyapp.user.v1.Agency - 63, // 21: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 21: hyapp.user.v1.ProcessRoleInvitationRequest.meta:type_name -> hyapp.user.v1.RequestMeta 8, // 22: hyapp.user.v1.ProcessRoleInvitationResponse.invitation:type_name -> hyapp.user.v1.RoleInvitation 0, // 23: hyapp.user.v1.ProcessRoleInvitationResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 1, // 24: hyapp.user.v1.ProcessRoleInvitationResponse.agency:type_name -> hyapp.user.v1.Agency 6, // 25: hyapp.user.v1.ProcessRoleInvitationResponse.membership:type_name -> hyapp.user.v1.AgencyMembership 2, // 26: hyapp.user.v1.ProcessRoleInvitationResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 63, // 27: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 27: hyapp.user.v1.GetHostProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 0, // 28: hyapp.user.v1.GetHostProfileResponse.host_profile:type_name -> hyapp.user.v1.HostProfile - 63, // 29: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 29: hyapp.user.v1.GetBDProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 30: hyapp.user.v1.GetBDProfileResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 63, // 31: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 31: hyapp.user.v1.GetCoinSellerProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 32: hyapp.user.v1.GetCoinSellerProfileResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 63, // 33: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 33: hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta 4, // 34: hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse.coin_sellers:type_name -> hyapp.user.v1.CoinSellerListItem - 63, // 35: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 35: hyapp.user.v1.GetUserRoleSummaryRequest.meta:type_name -> hyapp.user.v1.RequestMeta 5, // 36: hyapp.user.v1.GetUserRoleSummaryResponse.summary:type_name -> hyapp.user.v1.UserRoleSummary - 63, // 37: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 37: hyapp.user.v1.GetAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 38: hyapp.user.v1.GetAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 63, // 39: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 63, // 40: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 39: hyapp.user.v1.CheckBusinessCapabilityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 40: hyapp.user.v1.GetAgencyMembersRequest.meta:type_name -> hyapp.user.v1.RequestMeta 6, // 41: hyapp.user.v1.GetAgencyMembersResponse.memberships:type_name -> hyapp.user.v1.AgencyMembership - 63, // 42: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 42: hyapp.user.v1.GetAgencyApplicationsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 7, // 43: hyapp.user.v1.GetAgencyApplicationsResponse.applications:type_name -> hyapp.user.v1.AgencyApplication - 63, // 44: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 44: hyapp.user.v1.CreateBDLeaderRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 45: hyapp.user.v1.CreateBDLeaderResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 63, // 46: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 46: hyapp.user.v1.CreateBDRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 47: hyapp.user.v1.CreateBDResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 63, // 48: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 48: hyapp.user.v1.SetBDStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta 2, // 49: hyapp.user.v1.SetBDStatusResponse.bd_profile:type_name -> hyapp.user.v1.BDProfile - 63, // 50: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 50: hyapp.user.v1.CreateCoinSellerRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 51: hyapp.user.v1.CreateCoinSellerResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 63, // 52: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 52: hyapp.user.v1.SetCoinSellerStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta 3, // 53: hyapp.user.v1.SetCoinSellerStatusResponse.coin_seller_profile:type_name -> hyapp.user.v1.CoinSellerProfile - 63, // 54: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 54: hyapp.user.v1.CreateAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 55: hyapp.user.v1.CreateAgencyResponse.agency:type_name -> hyapp.user.v1.Agency 0, // 56: hyapp.user.v1.CreateAgencyResponse.host_profile:type_name -> hyapp.user.v1.HostProfile 6, // 57: hyapp.user.v1.CreateAgencyResponse.membership:type_name -> hyapp.user.v1.AgencyMembership - 63, // 58: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 65, // 58: hyapp.user.v1.CloseAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 59: hyapp.user.v1.CloseAgencyResponse.agency:type_name -> hyapp.user.v1.Agency - 63, // 60: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 61: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency - 9, // 62: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest - 11, // 63: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest - 13, // 64: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest - 15, // 65: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest - 17, // 66: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest - 19, // 67: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest - 21, // 68: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest - 23, // 69: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest - 25, // 70: hyapp.user.v1.UserHostService.ListBDAgencies:input_type -> hyapp.user.v1.ListBDAgenciesRequest - 27, // 71: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest - 29, // 72: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest - 31, // 73: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest - 33, // 74: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest - 35, // 75: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest - 37, // 76: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest - 39, // 77: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest - 41, // 78: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest - 43, // 79: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest - 45, // 80: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest - 47, // 81: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest - 49, // 82: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest - 51, // 83: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest - 53, // 84: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest - 55, // 85: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest - 57, // 86: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest - 59, // 87: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest - 61, // 88: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest - 10, // 89: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse - 12, // 90: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse - 14, // 91: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse - 16, // 92: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse - 18, // 93: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse - 20, // 94: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse - 22, // 95: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse - 24, // 96: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse - 26, // 97: hyapp.user.v1.UserHostService.ListBDAgencies:output_type -> hyapp.user.v1.ListBDAgenciesResponse - 28, // 98: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse - 30, // 99: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse - 32, // 100: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse - 34, // 101: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse - 36, // 102: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse - 38, // 103: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse - 40, // 104: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse - 42, // 105: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse - 44, // 106: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse - 46, // 107: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse - 48, // 108: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse - 50, // 109: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse - 52, // 110: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse - 54, // 111: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse - 56, // 112: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse - 58, // 113: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse - 60, // 114: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse - 62, // 115: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse - 89, // [89:116] is the sub-list for method output_type - 62, // [62:89] is the sub-list for method input_type - 62, // [62:62] is the sub-list for extension type_name - 62, // [62:62] is the sub-list for extension extendee - 0, // [0:62] is the sub-list for field type_name + 65, // 60: hyapp.user.v1.DeleteAgencyRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 61: hyapp.user.v1.DeleteAgencyResponse.agency:type_name -> hyapp.user.v1.Agency + 65, // 62: hyapp.user.v1.SetAgencyJoinEnabledRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 63: hyapp.user.v1.SetAgencyJoinEnabledResponse.agency:type_name -> hyapp.user.v1.Agency + 9, // 64: hyapp.user.v1.UserHostService.SearchAgencies:input_type -> hyapp.user.v1.SearchAgenciesRequest + 11, // 65: hyapp.user.v1.UserHostService.ApplyToAgency:input_type -> hyapp.user.v1.ApplyToAgencyRequest + 13, // 66: hyapp.user.v1.UserHostService.ReviewAgencyApplication:input_type -> hyapp.user.v1.ReviewAgencyApplicationRequest + 15, // 67: hyapp.user.v1.UserHostService.KickAgencyHost:input_type -> hyapp.user.v1.KickAgencyHostRequest + 17, // 68: hyapp.user.v1.UserHostService.InviteAgency:input_type -> hyapp.user.v1.InviteAgencyRequest + 19, // 69: hyapp.user.v1.UserHostService.InviteBD:input_type -> hyapp.user.v1.InviteBDRequest + 21, // 70: hyapp.user.v1.UserHostService.ListBDLeaderBDs:input_type -> hyapp.user.v1.ListBDLeaderBDsRequest + 23, // 71: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:input_type -> hyapp.user.v1.ListBDLeaderAgenciesRequest + 25, // 72: hyapp.user.v1.UserHostService.ListBDAgencies:input_type -> hyapp.user.v1.ListBDAgenciesRequest + 27, // 73: hyapp.user.v1.UserHostService.ProcessRoleInvitation:input_type -> hyapp.user.v1.ProcessRoleInvitationRequest + 29, // 74: hyapp.user.v1.UserHostService.GetHostProfile:input_type -> hyapp.user.v1.GetHostProfileRequest + 31, // 75: hyapp.user.v1.UserHostService.GetBDProfile:input_type -> hyapp.user.v1.GetBDProfileRequest + 33, // 76: hyapp.user.v1.UserHostService.GetCoinSellerProfile:input_type -> hyapp.user.v1.GetCoinSellerProfileRequest + 35, // 77: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:input_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionRequest + 37, // 78: hyapp.user.v1.UserHostService.GetUserRoleSummary:input_type -> hyapp.user.v1.GetUserRoleSummaryRequest + 39, // 79: hyapp.user.v1.UserHostService.GetAgency:input_type -> hyapp.user.v1.GetAgencyRequest + 41, // 80: hyapp.user.v1.UserHostService.CheckBusinessCapability:input_type -> hyapp.user.v1.CheckBusinessCapabilityRequest + 43, // 81: hyapp.user.v1.UserHostService.GetAgencyMembers:input_type -> hyapp.user.v1.GetAgencyMembersRequest + 45, // 82: hyapp.user.v1.UserHostService.GetAgencyApplications:input_type -> hyapp.user.v1.GetAgencyApplicationsRequest + 47, // 83: hyapp.user.v1.UserHostAdminService.CreateBDLeader:input_type -> hyapp.user.v1.CreateBDLeaderRequest + 49, // 84: hyapp.user.v1.UserHostAdminService.CreateBD:input_type -> hyapp.user.v1.CreateBDRequest + 51, // 85: hyapp.user.v1.UserHostAdminService.SetBDStatus:input_type -> hyapp.user.v1.SetBDStatusRequest + 53, // 86: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:input_type -> hyapp.user.v1.CreateCoinSellerRequest + 55, // 87: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:input_type -> hyapp.user.v1.SetCoinSellerStatusRequest + 57, // 88: hyapp.user.v1.UserHostAdminService.CreateAgency:input_type -> hyapp.user.v1.CreateAgencyRequest + 59, // 89: hyapp.user.v1.UserHostAdminService.CloseAgency:input_type -> hyapp.user.v1.CloseAgencyRequest + 61, // 90: hyapp.user.v1.UserHostAdminService.DeleteAgency:input_type -> hyapp.user.v1.DeleteAgencyRequest + 63, // 91: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:input_type -> hyapp.user.v1.SetAgencyJoinEnabledRequest + 10, // 92: hyapp.user.v1.UserHostService.SearchAgencies:output_type -> hyapp.user.v1.SearchAgenciesResponse + 12, // 93: hyapp.user.v1.UserHostService.ApplyToAgency:output_type -> hyapp.user.v1.ApplyToAgencyResponse + 14, // 94: hyapp.user.v1.UserHostService.ReviewAgencyApplication:output_type -> hyapp.user.v1.ReviewAgencyApplicationResponse + 16, // 95: hyapp.user.v1.UserHostService.KickAgencyHost:output_type -> hyapp.user.v1.KickAgencyHostResponse + 18, // 96: hyapp.user.v1.UserHostService.InviteAgency:output_type -> hyapp.user.v1.InviteAgencyResponse + 20, // 97: hyapp.user.v1.UserHostService.InviteBD:output_type -> hyapp.user.v1.InviteBDResponse + 22, // 98: hyapp.user.v1.UserHostService.ListBDLeaderBDs:output_type -> hyapp.user.v1.ListBDLeaderBDsResponse + 24, // 99: hyapp.user.v1.UserHostService.ListBDLeaderAgencies:output_type -> hyapp.user.v1.ListBDLeaderAgenciesResponse + 26, // 100: hyapp.user.v1.UserHostService.ListBDAgencies:output_type -> hyapp.user.v1.ListBDAgenciesResponse + 28, // 101: hyapp.user.v1.UserHostService.ProcessRoleInvitation:output_type -> hyapp.user.v1.ProcessRoleInvitationResponse + 30, // 102: hyapp.user.v1.UserHostService.GetHostProfile:output_type -> hyapp.user.v1.GetHostProfileResponse + 32, // 103: hyapp.user.v1.UserHostService.GetBDProfile:output_type -> hyapp.user.v1.GetBDProfileResponse + 34, // 104: hyapp.user.v1.UserHostService.GetCoinSellerProfile:output_type -> hyapp.user.v1.GetCoinSellerProfileResponse + 36, // 105: hyapp.user.v1.UserHostService.ListActiveCoinSellersInMyRegion:output_type -> hyapp.user.v1.ListActiveCoinSellersInMyRegionResponse + 38, // 106: hyapp.user.v1.UserHostService.GetUserRoleSummary:output_type -> hyapp.user.v1.GetUserRoleSummaryResponse + 40, // 107: hyapp.user.v1.UserHostService.GetAgency:output_type -> hyapp.user.v1.GetAgencyResponse + 42, // 108: hyapp.user.v1.UserHostService.CheckBusinessCapability:output_type -> hyapp.user.v1.CheckBusinessCapabilityResponse + 44, // 109: hyapp.user.v1.UserHostService.GetAgencyMembers:output_type -> hyapp.user.v1.GetAgencyMembersResponse + 46, // 110: hyapp.user.v1.UserHostService.GetAgencyApplications:output_type -> hyapp.user.v1.GetAgencyApplicationsResponse + 48, // 111: hyapp.user.v1.UserHostAdminService.CreateBDLeader:output_type -> hyapp.user.v1.CreateBDLeaderResponse + 50, // 112: hyapp.user.v1.UserHostAdminService.CreateBD:output_type -> hyapp.user.v1.CreateBDResponse + 52, // 113: hyapp.user.v1.UserHostAdminService.SetBDStatus:output_type -> hyapp.user.v1.SetBDStatusResponse + 54, // 114: hyapp.user.v1.UserHostAdminService.CreateCoinSeller:output_type -> hyapp.user.v1.CreateCoinSellerResponse + 56, // 115: hyapp.user.v1.UserHostAdminService.SetCoinSellerStatus:output_type -> hyapp.user.v1.SetCoinSellerStatusResponse + 58, // 116: hyapp.user.v1.UserHostAdminService.CreateAgency:output_type -> hyapp.user.v1.CreateAgencyResponse + 60, // 117: hyapp.user.v1.UserHostAdminService.CloseAgency:output_type -> hyapp.user.v1.CloseAgencyResponse + 62, // 118: hyapp.user.v1.UserHostAdminService.DeleteAgency:output_type -> hyapp.user.v1.DeleteAgencyResponse + 64, // 119: hyapp.user.v1.UserHostAdminService.SetAgencyJoinEnabled:output_type -> hyapp.user.v1.SetAgencyJoinEnabledResponse + 92, // [92:120] is the sub-list for method output_type + 64, // [64:92] is the sub-list for method input_type + 64, // [64:64] is the sub-list for extension type_name + 64, // [64:64] is the sub-list for extension extendee + 0, // [0:64] is the sub-list for field type_name } func init() { file_proto_user_v1_host_proto_init() } @@ -4984,7 +5113,7 @@ func file_proto_user_v1_host_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_host_proto_rawDesc), len(file_proto_user_v1_host_proto_rawDesc)), NumEnums: 0, - NumMessages: 63, + NumMessages: 65, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/user/v1/host.proto b/api/proto/user/v1/host.proto index 44ce416e..586ef814 100644 --- a/api/proto/user/v1/host.proto +++ b/api/proto/user/v1/host.proto @@ -30,6 +30,7 @@ message Agency { string name = 5; string status = 6; bool join_enabled = 7; + // Deprecated: Agency 不再限制主播数量,该字段仅为历史兼容保留。 int32 max_hosts = 8; int64 created_by_user_id = 9; int64 created_at_ms = 10; @@ -362,7 +363,6 @@ message CreateBDLeaderRequest { int64 admin_user_id = 3; int64 target_user_id = 4; string reason = 5; - int64 region_id = 6; } message CreateBDLeaderResponse { @@ -428,6 +428,7 @@ message CreateAgencyRequest { int64 parent_bd_user_id = 5; string name = 6; bool join_enabled = 7; + // Deprecated: Agency 不再限制主播数量,服务端会忽略该字段。 int32 max_hosts = 8; string reason = 9; } @@ -450,6 +451,18 @@ message CloseAgencyResponse { Agency agency = 1; } +message DeleteAgencyRequest { + RequestMeta meta = 1; + string command_id = 2; + int64 admin_user_id = 3; + int64 agency_id = 4; + string reason = 5; +} + +message DeleteAgencyResponse { + Agency agency = 1; +} + message SetAgencyJoinEnabledRequest { RequestMeta meta = 1; string command_id = 2; @@ -495,5 +508,6 @@ service UserHostAdminService { rpc SetCoinSellerStatus(SetCoinSellerStatusRequest) returns (SetCoinSellerStatusResponse); rpc CreateAgency(CreateAgencyRequest) returns (CreateAgencyResponse); rpc CloseAgency(CloseAgencyRequest) returns (CloseAgencyResponse); + rpc DeleteAgency(DeleteAgencyRequest) returns (DeleteAgencyResponse); rpc SetAgencyJoinEnabled(SetAgencyJoinEnabledRequest) returns (SetAgencyJoinEnabledResponse); } diff --git a/api/proto/user/v1/host_grpc.pb.go b/api/proto/user/v1/host_grpc.pb.go index 45ac7fcb..0e387868 100644 --- a/api/proto/user/v1/host_grpc.pb.go +++ b/api/proto/user/v1/host_grpc.pb.go @@ -816,6 +816,7 @@ const ( UserHostAdminService_SetCoinSellerStatus_FullMethodName = "/hyapp.user.v1.UserHostAdminService/SetCoinSellerStatus" UserHostAdminService_CreateAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/CreateAgency" UserHostAdminService_CloseAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/CloseAgency" + UserHostAdminService_DeleteAgency_FullMethodName = "/hyapp.user.v1.UserHostAdminService/DeleteAgency" UserHostAdminService_SetAgencyJoinEnabled_FullMethodName = "/hyapp.user.v1.UserHostAdminService/SetAgencyJoinEnabled" ) @@ -832,6 +833,7 @@ type UserHostAdminServiceClient interface { SetCoinSellerStatus(ctx context.Context, in *SetCoinSellerStatusRequest, opts ...grpc.CallOption) (*SetCoinSellerStatusResponse, error) CreateAgency(ctx context.Context, in *CreateAgencyRequest, opts ...grpc.CallOption) (*CreateAgencyResponse, error) CloseAgency(ctx context.Context, in *CloseAgencyRequest, opts ...grpc.CallOption) (*CloseAgencyResponse, error) + DeleteAgency(ctx context.Context, in *DeleteAgencyRequest, opts ...grpc.CallOption) (*DeleteAgencyResponse, error) SetAgencyJoinEnabled(ctx context.Context, in *SetAgencyJoinEnabledRequest, opts ...grpc.CallOption) (*SetAgencyJoinEnabledResponse, error) } @@ -913,6 +915,16 @@ func (c *userHostAdminServiceClient) CloseAgency(ctx context.Context, in *CloseA return out, nil } +func (c *userHostAdminServiceClient) DeleteAgency(ctx context.Context, in *DeleteAgencyRequest, opts ...grpc.CallOption) (*DeleteAgencyResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteAgencyResponse) + err := c.cc.Invoke(ctx, UserHostAdminService_DeleteAgency_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userHostAdminServiceClient) SetAgencyJoinEnabled(ctx context.Context, in *SetAgencyJoinEnabledRequest, opts ...grpc.CallOption) (*SetAgencyJoinEnabledResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetAgencyJoinEnabledResponse) @@ -936,6 +948,7 @@ type UserHostAdminServiceServer interface { SetCoinSellerStatus(context.Context, *SetCoinSellerStatusRequest) (*SetCoinSellerStatusResponse, error) CreateAgency(context.Context, *CreateAgencyRequest) (*CreateAgencyResponse, error) CloseAgency(context.Context, *CloseAgencyRequest) (*CloseAgencyResponse, error) + DeleteAgency(context.Context, *DeleteAgencyRequest) (*DeleteAgencyResponse, error) SetAgencyJoinEnabled(context.Context, *SetAgencyJoinEnabledRequest) (*SetAgencyJoinEnabledResponse, error) mustEmbedUnimplementedUserHostAdminServiceServer() } @@ -968,6 +981,9 @@ func (UnimplementedUserHostAdminServiceServer) CreateAgency(context.Context, *Cr func (UnimplementedUserHostAdminServiceServer) CloseAgency(context.Context, *CloseAgencyRequest) (*CloseAgencyResponse, error) { return nil, status.Error(codes.Unimplemented, "method CloseAgency not implemented") } +func (UnimplementedUserHostAdminServiceServer) DeleteAgency(context.Context, *DeleteAgencyRequest) (*DeleteAgencyResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteAgency not implemented") +} func (UnimplementedUserHostAdminServiceServer) SetAgencyJoinEnabled(context.Context, *SetAgencyJoinEnabledRequest) (*SetAgencyJoinEnabledResponse, error) { return nil, status.Error(codes.Unimplemented, "method SetAgencyJoinEnabled not implemented") } @@ -1118,6 +1134,24 @@ func _UserHostAdminService_CloseAgency_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } +func _UserHostAdminService_DeleteAgency_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAgencyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserHostAdminServiceServer).DeleteAgency(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserHostAdminService_DeleteAgency_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserHostAdminServiceServer).DeleteAgency(ctx, req.(*DeleteAgencyRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserHostAdminService_SetAgencyJoinEnabled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetAgencyJoinEnabledRequest) if err := dec(in); err != nil { @@ -1171,6 +1205,10 @@ var UserHostAdminService_ServiceDesc = grpc.ServiceDesc{ MethodName: "CloseAgency", Handler: _UserHostAdminService_CloseAgency_Handler, }, + { + MethodName: "DeleteAgency", + Handler: _UserHostAdminService_DeleteAgency_Handler, + }, { MethodName: "SetAgencyJoinEnabled", Handler: _UserHostAdminService_SetAgencyJoinEnabled_Handler, diff --git a/api/proto/user/v1/user.pb.go b/api/proto/user/v1/user.pb.go index 36a0c2d5..a7f16256 100644 --- a/api/proto/user/v1/user.pb.go +++ b/api/proto/user/v1/user.pb.go @@ -3907,7 +3907,7 @@ func (x *UpdateUserProfileResponse) GetUser() *User { return nil } -// ChangeUserCountryRequest 单独修改用户国家;该字段有冷却期和变更日志。 +// ChangeUserCountryRequest 是 App 用户自助修改国家入口;受限业务身份不允许自助修改。 type ChangeUserCountryRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` @@ -3968,6 +3968,83 @@ func (x *ChangeUserCountryRequest) GetCountry() string { return "" } +// AdminChangeUserCountryRequest 是后台显式覆盖用户国家入口;它绕过 App 自助身份限制。 +type AdminChangeUserCountryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Country string `protobuf:"bytes,3,opt,name=country,proto3" json:"country,omitempty"` + AdminUserId int64 `protobuf:"varint,4,opt,name=admin_user_id,json=adminUserId,proto3" json:"admin_user_id,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AdminChangeUserCountryRequest) Reset() { + *x = AdminChangeUserCountryRequest{} + mi := &file_proto_user_v1_user_proto_msgTypes[55] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AdminChangeUserCountryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AdminChangeUserCountryRequest) ProtoMessage() {} + +func (x *AdminChangeUserCountryRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_user_v1_user_proto_msgTypes[55] + 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 AdminChangeUserCountryRequest.ProtoReflect.Descriptor instead. +func (*AdminChangeUserCountryRequest) Descriptor() ([]byte, []int) { + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{55} +} + +func (x *AdminChangeUserCountryRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *AdminChangeUserCountryRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *AdminChangeUserCountryRequest) GetCountry() string { + if x != nil { + return x.Country + } + return "" +} + +func (x *AdminChangeUserCountryRequest) GetAdminUserId() int64 { + if x != nil { + return x.AdminUserId + } + return 0 +} + +func (x *AdminChangeUserCountryRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + // ChangeUserCountryResponse 返回更新后的用户资料和下一次可修改时间。 type ChangeUserCountryResponse struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -3982,7 +4059,7 @@ type ChangeUserCountryResponse struct { func (x *ChangeUserCountryResponse) Reset() { *x = ChangeUserCountryResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[55] + mi := &file_proto_user_v1_user_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3994,7 +4071,7 @@ func (x *ChangeUserCountryResponse) String() string { func (*ChangeUserCountryResponse) ProtoMessage() {} func (x *ChangeUserCountryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[55] + mi := &file_proto_user_v1_user_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4007,7 +4084,7 @@ func (x *ChangeUserCountryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeUserCountryResponse.ProtoReflect.Descriptor instead. func (*ChangeUserCountryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{55} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{56} } func (x *ChangeUserCountryResponse) GetUser() *User { @@ -4062,7 +4139,7 @@ type SetUserStatusRequest struct { func (x *SetUserStatusRequest) Reset() { *x = SetUserStatusRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[56] + mi := &file_proto_user_v1_user_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4074,7 +4151,7 @@ func (x *SetUserStatusRequest) String() string { func (*SetUserStatusRequest) ProtoMessage() {} func (x *SetUserStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[56] + mi := &file_proto_user_v1_user_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4087,7 +4164,7 @@ func (x *SetUserStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetUserStatusRequest.ProtoReflect.Descriptor instead. func (*SetUserStatusRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{56} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{57} } func (x *SetUserStatusRequest) GetMeta() *RequestMeta { @@ -4153,7 +4230,7 @@ type SetUserStatusResponse struct { func (x *SetUserStatusResponse) Reset() { *x = SetUserStatusResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[57] + mi := &file_proto_user_v1_user_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4165,7 +4242,7 @@ func (x *SetUserStatusResponse) String() string { func (*SetUserStatusResponse) ProtoMessage() {} func (x *SetUserStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[57] + mi := &file_proto_user_v1_user_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4178,7 +4255,7 @@ func (x *SetUserStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetUserStatusResponse.ProtoReflect.Descriptor instead. func (*SetUserStatusResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{57} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{58} } func (x *SetUserStatusResponse) GetUser() *User { @@ -4274,7 +4351,7 @@ type CompleteOnboardingRequest struct { func (x *CompleteOnboardingRequest) Reset() { *x = CompleteOnboardingRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[58] + mi := &file_proto_user_v1_user_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4286,7 +4363,7 @@ func (x *CompleteOnboardingRequest) String() string { func (*CompleteOnboardingRequest) ProtoMessage() {} func (x *CompleteOnboardingRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[58] + mi := &file_proto_user_v1_user_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4299,7 +4376,7 @@ func (x *CompleteOnboardingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteOnboardingRequest.ProtoReflect.Descriptor instead. func (*CompleteOnboardingRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{58} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{59} } func (x *CompleteOnboardingRequest) GetMeta() *RequestMeta { @@ -4366,7 +4443,7 @@ type CompleteOnboardingResponse struct { func (x *CompleteOnboardingResponse) Reset() { *x = CompleteOnboardingResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[59] + mi := &file_proto_user_v1_user_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4378,7 +4455,7 @@ func (x *CompleteOnboardingResponse) String() string { func (*CompleteOnboardingResponse) ProtoMessage() {} func (x *CompleteOnboardingResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[59] + mi := &file_proto_user_v1_user_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4391,7 +4468,7 @@ func (x *CompleteOnboardingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CompleteOnboardingResponse.ProtoReflect.Descriptor instead. func (*CompleteOnboardingResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{59} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{60} } func (x *CompleteOnboardingResponse) GetUser() *User { @@ -4455,7 +4532,7 @@ type BindPushTokenRequest struct { func (x *BindPushTokenRequest) Reset() { *x = BindPushTokenRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[60] + mi := &file_proto_user_v1_user_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4467,7 +4544,7 @@ func (x *BindPushTokenRequest) String() string { func (*BindPushTokenRequest) ProtoMessage() {} func (x *BindPushTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[60] + mi := &file_proto_user_v1_user_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4480,7 +4557,7 @@ func (x *BindPushTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BindPushTokenRequest.ProtoReflect.Descriptor instead. func (*BindPushTokenRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{60} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{61} } func (x *BindPushTokenRequest) GetMeta() *RequestMeta { @@ -4556,7 +4633,7 @@ type BindPushTokenResponse struct { func (x *BindPushTokenResponse) Reset() { *x = BindPushTokenResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[61] + mi := &file_proto_user_v1_user_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4568,7 +4645,7 @@ func (x *BindPushTokenResponse) String() string { func (*BindPushTokenResponse) ProtoMessage() {} func (x *BindPushTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[61] + mi := &file_proto_user_v1_user_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4581,7 +4658,7 @@ func (x *BindPushTokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BindPushTokenResponse.ProtoReflect.Descriptor instead. func (*BindPushTokenResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{61} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{62} } func (x *BindPushTokenResponse) GetBound() bool { @@ -4612,7 +4689,7 @@ type DeletePushTokenRequest struct { func (x *DeletePushTokenRequest) Reset() { *x = DeletePushTokenRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[62] + mi := &file_proto_user_v1_user_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4624,7 +4701,7 @@ func (x *DeletePushTokenRequest) String() string { func (*DeletePushTokenRequest) ProtoMessage() {} func (x *DeletePushTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[62] + mi := &file_proto_user_v1_user_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4637,7 +4714,7 @@ func (x *DeletePushTokenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeletePushTokenRequest.ProtoReflect.Descriptor instead. func (*DeletePushTokenRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{62} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{63} } func (x *DeletePushTokenRequest) GetMeta() *RequestMeta { @@ -4678,7 +4755,7 @@ type DeletePushTokenResponse struct { func (x *DeletePushTokenResponse) Reset() { *x = DeletePushTokenResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[63] + mi := &file_proto_user_v1_user_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4690,7 +4767,7 @@ func (x *DeletePushTokenResponse) String() string { func (*DeletePushTokenResponse) ProtoMessage() {} func (x *DeletePushTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[63] + mi := &file_proto_user_v1_user_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4703,7 +4780,7 @@ func (x *DeletePushTokenResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeletePushTokenResponse.ProtoReflect.Descriptor instead. func (*DeletePushTokenResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{63} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{64} } func (x *DeletePushTokenResponse) GetDeleted() bool { @@ -4742,7 +4819,7 @@ type Country struct { func (x *Country) Reset() { *x = Country{} - mi := &file_proto_user_v1_user_proto_msgTypes[64] + mi := &file_proto_user_v1_user_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4754,7 +4831,7 @@ func (x *Country) String() string { func (*Country) ProtoMessage() {} func (x *Country) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[64] + mi := &file_proto_user_v1_user_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4767,7 +4844,7 @@ func (x *Country) ProtoReflect() protoreflect.Message { // Deprecated: Use Country.ProtoReflect.Descriptor instead. func (*Country) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{64} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{65} } func (x *Country) GetCountryId() int64 { @@ -4879,7 +4956,7 @@ type Region struct { func (x *Region) Reset() { *x = Region{} - mi := &file_proto_user_v1_user_proto_msgTypes[65] + mi := &file_proto_user_v1_user_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4891,7 +4968,7 @@ func (x *Region) String() string { func (*Region) ProtoMessage() {} func (x *Region) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[65] + mi := &file_proto_user_v1_user_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4904,7 +4981,7 @@ func (x *Region) ProtoReflect() protoreflect.Message { // Deprecated: Use Region.ProtoReflect.Descriptor instead. func (*Region) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{65} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{66} } func (x *Region) GetRegionId() int64 { @@ -4980,7 +5057,7 @@ type ListCountriesRequest struct { func (x *ListCountriesRequest) Reset() { *x = ListCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[66] + mi := &file_proto_user_v1_user_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4992,7 +5069,7 @@ func (x *ListCountriesRequest) String() string { func (*ListCountriesRequest) ProtoMessage() {} func (x *ListCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[66] + mi := &file_proto_user_v1_user_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5005,7 +5082,7 @@ func (x *ListCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCountriesRequest.ProtoReflect.Descriptor instead. func (*ListCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{66} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{67} } func (x *ListCountriesRequest) GetMeta() *RequestMeta { @@ -5031,7 +5108,7 @@ type ListCountriesResponse struct { func (x *ListCountriesResponse) Reset() { *x = ListCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[67] + mi := &file_proto_user_v1_user_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5043,7 +5120,7 @@ func (x *ListCountriesResponse) String() string { func (*ListCountriesResponse) ProtoMessage() {} func (x *ListCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[67] + mi := &file_proto_user_v1_user_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5056,7 +5133,7 @@ func (x *ListCountriesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListCountriesResponse.ProtoReflect.Descriptor instead. func (*ListCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{67} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{68} } func (x *ListCountriesResponse) GetCountries() []*Country { @@ -5085,7 +5162,7 @@ type UpdateCountryRequest struct { func (x *UpdateCountryRequest) Reset() { *x = UpdateCountryRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[68] + mi := &file_proto_user_v1_user_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5097,7 +5174,7 @@ func (x *UpdateCountryRequest) String() string { func (*UpdateCountryRequest) ProtoMessage() {} func (x *UpdateCountryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[68] + mi := &file_proto_user_v1_user_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5110,7 +5187,7 @@ func (x *UpdateCountryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateCountryRequest.ProtoReflect.Descriptor instead. func (*UpdateCountryRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{68} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{69} } func (x *UpdateCountryRequest) GetMeta() *RequestMeta { @@ -5192,7 +5269,7 @@ type CountryResponse struct { func (x *CountryResponse) Reset() { *x = CountryResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[69] + mi := &file_proto_user_v1_user_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5204,7 +5281,7 @@ func (x *CountryResponse) String() string { func (*CountryResponse) ProtoMessage() {} func (x *CountryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[69] + mi := &file_proto_user_v1_user_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5217,7 +5294,7 @@ func (x *CountryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CountryResponse.ProtoReflect.Descriptor instead. func (*CountryResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{69} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{70} } func (x *CountryResponse) GetCountry() *Country { @@ -5236,7 +5313,7 @@ type ListRegistrationCountriesRequest struct { func (x *ListRegistrationCountriesRequest) Reset() { *x = ListRegistrationCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[70] + mi := &file_proto_user_v1_user_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5248,7 +5325,7 @@ func (x *ListRegistrationCountriesRequest) String() string { func (*ListRegistrationCountriesRequest) ProtoMessage() {} func (x *ListRegistrationCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[70] + mi := &file_proto_user_v1_user_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5261,7 +5338,7 @@ func (x *ListRegistrationCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegistrationCountriesRequest.ProtoReflect.Descriptor instead. func (*ListRegistrationCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{70} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{71} } func (x *ListRegistrationCountriesRequest) GetMeta() *RequestMeta { @@ -5280,7 +5357,7 @@ type ListRegistrationCountriesResponse struct { func (x *ListRegistrationCountriesResponse) Reset() { *x = ListRegistrationCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[71] + mi := &file_proto_user_v1_user_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5292,7 +5369,7 @@ func (x *ListRegistrationCountriesResponse) String() string { func (*ListRegistrationCountriesResponse) ProtoMessage() {} func (x *ListRegistrationCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[71] + mi := &file_proto_user_v1_user_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5305,7 +5382,7 @@ func (x *ListRegistrationCountriesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListRegistrationCountriesResponse.ProtoReflect.Descriptor instead. func (*ListRegistrationCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{71} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{72} } func (x *ListRegistrationCountriesResponse) GetCountries() []*Country { @@ -5326,7 +5403,7 @@ type LoginRiskBlockedCountry struct { func (x *LoginRiskBlockedCountry) Reset() { *x = LoginRiskBlockedCountry{} - mi := &file_proto_user_v1_user_proto_msgTypes[72] + mi := &file_proto_user_v1_user_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5338,7 +5415,7 @@ func (x *LoginRiskBlockedCountry) String() string { func (*LoginRiskBlockedCountry) ProtoMessage() {} func (x *LoginRiskBlockedCountry) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[72] + mi := &file_proto_user_v1_user_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5351,7 +5428,7 @@ func (x *LoginRiskBlockedCountry) ProtoReflect() protoreflect.Message { // Deprecated: Use LoginRiskBlockedCountry.ProtoReflect.Descriptor instead. func (*LoginRiskBlockedCountry) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{72} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{73} } func (x *LoginRiskBlockedCountry) GetCountryCode() string { @@ -5384,7 +5461,7 @@ type ListLoginRiskBlockedCountriesRequest struct { func (x *ListLoginRiskBlockedCountriesRequest) Reset() { *x = ListLoginRiskBlockedCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[73] + mi := &file_proto_user_v1_user_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5396,7 +5473,7 @@ func (x *ListLoginRiskBlockedCountriesRequest) String() string { func (*ListLoginRiskBlockedCountriesRequest) ProtoMessage() {} func (x *ListLoginRiskBlockedCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[73] + mi := &file_proto_user_v1_user_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5409,7 +5486,7 @@ func (x *ListLoginRiskBlockedCountriesRequest) ProtoReflect() protoreflect.Messa // Deprecated: Use ListLoginRiskBlockedCountriesRequest.ProtoReflect.Descriptor instead. func (*ListLoginRiskBlockedCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{73} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{74} } func (x *ListLoginRiskBlockedCountriesRequest) GetMeta() *RequestMeta { @@ -5429,7 +5506,7 @@ type ListLoginRiskBlockedCountriesResponse struct { func (x *ListLoginRiskBlockedCountriesResponse) Reset() { *x = ListLoginRiskBlockedCountriesResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[74] + mi := &file_proto_user_v1_user_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5441,7 +5518,7 @@ func (x *ListLoginRiskBlockedCountriesResponse) String() string { func (*ListLoginRiskBlockedCountriesResponse) ProtoMessage() {} func (x *ListLoginRiskBlockedCountriesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[74] + mi := &file_proto_user_v1_user_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5454,7 +5531,7 @@ func (x *ListLoginRiskBlockedCountriesResponse) ProtoReflect() protoreflect.Mess // Deprecated: Use ListLoginRiskBlockedCountriesResponse.ProtoReflect.Descriptor instead. func (*ListLoginRiskBlockedCountriesResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{74} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{75} } func (x *ListLoginRiskBlockedCountriesResponse) GetCountries() []*LoginRiskBlockedCountry { @@ -5481,7 +5558,7 @@ type ListRegionsRequest struct { func (x *ListRegionsRequest) Reset() { *x = ListRegionsRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[75] + mi := &file_proto_user_v1_user_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5493,7 +5570,7 @@ func (x *ListRegionsRequest) String() string { func (*ListRegionsRequest) ProtoMessage() {} func (x *ListRegionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[75] + mi := &file_proto_user_v1_user_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5506,7 +5583,7 @@ func (x *ListRegionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegionsRequest.ProtoReflect.Descriptor instead. func (*ListRegionsRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{75} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{76} } func (x *ListRegionsRequest) GetMeta() *RequestMeta { @@ -5532,7 +5609,7 @@ type ListRegionsResponse struct { func (x *ListRegionsResponse) Reset() { *x = ListRegionsResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[76] + mi := &file_proto_user_v1_user_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5544,7 +5621,7 @@ func (x *ListRegionsResponse) String() string { func (*ListRegionsResponse) ProtoMessage() {} func (x *ListRegionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[76] + mi := &file_proto_user_v1_user_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5557,7 +5634,7 @@ func (x *ListRegionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRegionsResponse.ProtoReflect.Descriptor instead. func (*ListRegionsResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{76} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{77} } func (x *ListRegionsResponse) GetRegions() []*Region { @@ -5577,7 +5654,7 @@ type GetRegionRequest struct { func (x *GetRegionRequest) Reset() { *x = GetRegionRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[77] + mi := &file_proto_user_v1_user_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5589,7 +5666,7 @@ func (x *GetRegionRequest) String() string { func (*GetRegionRequest) ProtoMessage() {} func (x *GetRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[77] + mi := &file_proto_user_v1_user_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5602,7 +5679,7 @@ func (x *GetRegionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRegionRequest.ProtoReflect.Descriptor instead. func (*GetRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{77} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{78} } func (x *GetRegionRequest) GetMeta() *RequestMeta { @@ -5634,7 +5711,7 @@ type UpdateRegionRequest struct { func (x *UpdateRegionRequest) Reset() { *x = UpdateRegionRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[78] + mi := &file_proto_user_v1_user_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5646,7 +5723,7 @@ func (x *UpdateRegionRequest) String() string { func (*UpdateRegionRequest) ProtoMessage() {} func (x *UpdateRegionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[78] + mi := &file_proto_user_v1_user_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5659,7 +5736,7 @@ func (x *UpdateRegionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRegionRequest.ProtoReflect.Descriptor instead. func (*UpdateRegionRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{78} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{79} } func (x *UpdateRegionRequest) GetMeta() *RequestMeta { @@ -5716,7 +5793,7 @@ type ReplaceRegionCountriesRequest struct { func (x *ReplaceRegionCountriesRequest) Reset() { *x = ReplaceRegionCountriesRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[79] + mi := &file_proto_user_v1_user_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5728,7 +5805,7 @@ func (x *ReplaceRegionCountriesRequest) String() string { func (*ReplaceRegionCountriesRequest) ProtoMessage() {} func (x *ReplaceRegionCountriesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[79] + mi := &file_proto_user_v1_user_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5741,7 +5818,7 @@ func (x *ReplaceRegionCountriesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ReplaceRegionCountriesRequest.ProtoReflect.Descriptor instead. func (*ReplaceRegionCountriesRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{79} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{80} } func (x *ReplaceRegionCountriesRequest) GetMeta() *RequestMeta { @@ -5781,7 +5858,7 @@ type RegionResponse struct { func (x *RegionResponse) Reset() { *x = RegionResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[80] + mi := &file_proto_user_v1_user_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5793,7 +5870,7 @@ func (x *RegionResponse) String() string { func (*RegionResponse) ProtoMessage() {} func (x *RegionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[80] + mi := &file_proto_user_v1_user_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5806,7 +5883,7 @@ func (x *RegionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RegionResponse.ProtoReflect.Descriptor instead. func (*RegionResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{80} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{81} } func (x *RegionResponse) GetRegion() *Region { @@ -5832,7 +5909,7 @@ type UserIdentity struct { func (x *UserIdentity) Reset() { *x = UserIdentity{} - mi := &file_proto_user_v1_user_proto_msgTypes[81] + mi := &file_proto_user_v1_user_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5844,7 +5921,7 @@ func (x *UserIdentity) String() string { func (*UserIdentity) ProtoMessage() {} func (x *UserIdentity) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[81] + mi := &file_proto_user_v1_user_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5857,7 +5934,7 @@ func (x *UserIdentity) ProtoReflect() protoreflect.Message { // Deprecated: Use UserIdentity.ProtoReflect.Descriptor instead. func (*UserIdentity) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{81} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{82} } func (x *UserIdentity) GetUserId() int64 { @@ -5920,7 +5997,7 @@ type GetUserIdentityRequest struct { func (x *GetUserIdentityRequest) Reset() { *x = GetUserIdentityRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[82] + mi := &file_proto_user_v1_user_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5932,7 +6009,7 @@ func (x *GetUserIdentityRequest) String() string { func (*GetUserIdentityRequest) ProtoMessage() {} func (x *GetUserIdentityRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[82] + mi := &file_proto_user_v1_user_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5945,7 +6022,7 @@ func (x *GetUserIdentityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserIdentityRequest.ProtoReflect.Descriptor instead. func (*GetUserIdentityRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{82} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{83} } func (x *GetUserIdentityRequest) GetMeta() *RequestMeta { @@ -5972,7 +6049,7 @@ type GetUserIdentityResponse struct { func (x *GetUserIdentityResponse) Reset() { *x = GetUserIdentityResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[83] + mi := &file_proto_user_v1_user_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5984,7 +6061,7 @@ func (x *GetUserIdentityResponse) String() string { func (*GetUserIdentityResponse) ProtoMessage() {} func (x *GetUserIdentityResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[83] + mi := &file_proto_user_v1_user_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5997,7 +6074,7 @@ func (x *GetUserIdentityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserIdentityResponse.ProtoReflect.Descriptor instead. func (*GetUserIdentityResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{83} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{84} } func (x *GetUserIdentityResponse) GetIdentity() *UserIdentity { @@ -6018,7 +6095,7 @@ type ResolveDisplayUserIDRequest struct { func (x *ResolveDisplayUserIDRequest) Reset() { *x = ResolveDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[84] + mi := &file_proto_user_v1_user_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6030,7 +6107,7 @@ func (x *ResolveDisplayUserIDRequest) String() string { func (*ResolveDisplayUserIDRequest) ProtoMessage() {} func (x *ResolveDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[84] + mi := &file_proto_user_v1_user_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6043,7 +6120,7 @@ func (x *ResolveDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ResolveDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{84} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{85} } func (x *ResolveDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -6070,7 +6147,7 @@ type ResolveDisplayUserIDResponse struct { func (x *ResolveDisplayUserIDResponse) Reset() { *x = ResolveDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[85] + mi := &file_proto_user_v1_user_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6082,7 +6159,7 @@ func (x *ResolveDisplayUserIDResponse) String() string { func (*ResolveDisplayUserIDResponse) ProtoMessage() {} func (x *ResolveDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[85] + mi := &file_proto_user_v1_user_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6095,7 +6172,7 @@ func (x *ResolveDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ResolveDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{85} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{86} } func (x *ResolveDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -6119,7 +6196,7 @@ type ChangeDisplayUserIDRequest struct { func (x *ChangeDisplayUserIDRequest) Reset() { *x = ChangeDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[86] + mi := &file_proto_user_v1_user_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6131,7 +6208,7 @@ func (x *ChangeDisplayUserIDRequest) String() string { func (*ChangeDisplayUserIDRequest) ProtoMessage() {} func (x *ChangeDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[86] + mi := &file_proto_user_v1_user_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6144,7 +6221,7 @@ func (x *ChangeDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ChangeDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{86} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{87} } func (x *ChangeDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -6192,7 +6269,7 @@ type ChangeDisplayUserIDResponse struct { func (x *ChangeDisplayUserIDResponse) Reset() { *x = ChangeDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[87] + mi := &file_proto_user_v1_user_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6204,7 +6281,7 @@ func (x *ChangeDisplayUserIDResponse) String() string { func (*ChangeDisplayUserIDResponse) ProtoMessage() {} func (x *ChangeDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[87] + mi := &file_proto_user_v1_user_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6217,7 +6294,7 @@ func (x *ChangeDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ChangeDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{87} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{88} } func (x *ChangeDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -6241,7 +6318,7 @@ type ApplyPrettyDisplayUserIDRequest struct { func (x *ApplyPrettyDisplayUserIDRequest) Reset() { *x = ApplyPrettyDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[88] + mi := &file_proto_user_v1_user_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6253,7 +6330,7 @@ func (x *ApplyPrettyDisplayUserIDRequest) String() string { func (*ApplyPrettyDisplayUserIDRequest) ProtoMessage() {} func (x *ApplyPrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[88] + mi := &file_proto_user_v1_user_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6266,7 +6343,7 @@ func (x *ApplyPrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyPrettyDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{88} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{89} } func (x *ApplyPrettyDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -6315,7 +6392,7 @@ type ApplyPrettyDisplayUserIDResponse struct { func (x *ApplyPrettyDisplayUserIDResponse) Reset() { *x = ApplyPrettyDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[89] + mi := &file_proto_user_v1_user_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6327,7 +6404,7 @@ func (x *ApplyPrettyDisplayUserIDResponse) String() string { func (*ApplyPrettyDisplayUserIDResponse) ProtoMessage() {} func (x *ApplyPrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[89] + mi := &file_proto_user_v1_user_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6340,7 +6417,7 @@ func (x *ApplyPrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyPrettyDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ApplyPrettyDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{89} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{90} } func (x *ApplyPrettyDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -6369,7 +6446,7 @@ type ExpirePrettyDisplayUserIDRequest struct { func (x *ExpirePrettyDisplayUserIDRequest) Reset() { *x = ExpirePrettyDisplayUserIDRequest{} - mi := &file_proto_user_v1_user_proto_msgTypes[90] + mi := &file_proto_user_v1_user_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6381,7 +6458,7 @@ func (x *ExpirePrettyDisplayUserIDRequest) String() string { func (*ExpirePrettyDisplayUserIDRequest) ProtoMessage() {} func (x *ExpirePrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[90] + mi := &file_proto_user_v1_user_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6394,7 +6471,7 @@ func (x *ExpirePrettyDisplayUserIDRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpirePrettyDisplayUserIDRequest.ProtoReflect.Descriptor instead. func (*ExpirePrettyDisplayUserIDRequest) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{90} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{91} } func (x *ExpirePrettyDisplayUserIDRequest) GetMeta() *RequestMeta { @@ -6428,7 +6505,7 @@ type ExpirePrettyDisplayUserIDResponse struct { func (x *ExpirePrettyDisplayUserIDResponse) Reset() { *x = ExpirePrettyDisplayUserIDResponse{} - mi := &file_proto_user_v1_user_proto_msgTypes[91] + mi := &file_proto_user_v1_user_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6440,7 +6517,7 @@ func (x *ExpirePrettyDisplayUserIDResponse) String() string { func (*ExpirePrettyDisplayUserIDResponse) ProtoMessage() {} func (x *ExpirePrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_user_v1_user_proto_msgTypes[91] + mi := &file_proto_user_v1_user_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6453,7 +6530,7 @@ func (x *ExpirePrettyDisplayUserIDResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ExpirePrettyDisplayUserIDResponse.ProtoReflect.Descriptor instead. func (*ExpirePrettyDisplayUserIDResponse) Descriptor() ([]byte, []int) { - return file_proto_user_v1_user_proto_rawDescGZIP(), []int{91} + return file_proto_user_v1_user_proto_rawDescGZIP(), []int{92} } func (x *ExpirePrettyDisplayUserIDResponse) GetIdentity() *UserIdentity { @@ -6791,7 +6868,13 @@ const file_proto_user_v1_user_proto_rawDesc = "" + "\x18ChangeUserCountryRequest\x12.\n" + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12\x17\n" + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x18\n" + - "\acountry\x18\x03 \x01(\tR\acountry\"\xed\x01\n" + + "\acountry\x18\x03 \x01(\tR\acountry\"\xcb\x01\n" + + "\x1dAdminChangeUserCountryRequest\x12.\n" + + "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.user.v1.RequestMetaR\x04meta\x12$\n" + + "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x18\n" + + "\acountry\x18\x03 \x01(\tR\acountry\x12\"\n" + + "\radmin_user_id\x18\x04 \x01(\x03R\vadminUserId\x12\x16\n" + + "\x06reason\x18\x05 \x01(\tR\x06reason\"\xed\x01\n" + "\x19ChangeUserCountryResponse\x12'\n" + "\x04user\x18\x01 \x01(\v2\x13.hyapp.user.v1.UserR\x04user\x128\n" + "\x19next_change_allowed_at_ms\x18\x02 \x01(\x03R\x15nextChangeAllowedAtMs\x12\"\n" + @@ -6998,7 +7081,7 @@ const file_proto_user_v1_user_proto_rawDesc = "" + "\x17USER_STATUS_UNSPECIFIED\x10\x00\x12\x16\n" + "\x12USER_STATUS_ACTIVE\x10\x01\x12\x18\n" + "\x14USER_STATUS_DISABLED\x10\x02\x12\x16\n" + - "\x12USER_STATUS_BANNED\x10\x032\xed\a\n" + + "\x12USER_STATUS_BANNED\x10\x032\xdf\b\n" + "\vUserService\x12H\n" + "\aGetUser\x12\x1d.hyapp.user.v1.GetUserRequest\x1a\x1e.hyapp.user.v1.GetUserResponse\x12i\n" + "\x12BusinessUserLookup\x12(.hyapp.user.v1.BusinessUserLookupRequest\x1a).hyapp.user.v1.BusinessUserLookupResponse\x12f\n" + @@ -7007,7 +7090,8 @@ const file_proto_user_v1_user_proto_rawDesc = "" + "\vListUserIDs\x12!.hyapp.user.v1.ListUserIDsRequest\x1a\".hyapp.user.v1.ListUserIDsResponse\x12x\n" + "\x17GetUserMicLifetimeStats\x12-.hyapp.user.v1.GetUserMicLifetimeStatsRequest\x1a..hyapp.user.v1.GetUserMicLifetimeStatsResponse\x12f\n" + "\x11UpdateUserProfile\x12'.hyapp.user.v1.UpdateUserProfileRequest\x1a(.hyapp.user.v1.UpdateUserProfileResponse\x12f\n" + - "\x11ChangeUserCountry\x12'.hyapp.user.v1.ChangeUserCountryRequest\x1a(.hyapp.user.v1.ChangeUserCountryResponse\x12Z\n" + + "\x11ChangeUserCountry\x12'.hyapp.user.v1.ChangeUserCountryRequest\x1a(.hyapp.user.v1.ChangeUserCountryResponse\x12p\n" + + "\x16AdminChangeUserCountry\x12,.hyapp.user.v1.AdminChangeUserCountryRequest\x1a(.hyapp.user.v1.ChangeUserCountryResponse\x12Z\n" + "\rSetUserStatus\x12#.hyapp.user.v1.SetUserStatusRequest\x1a$.hyapp.user.v1.SetUserStatusResponse\x12i\n" + "\x12CompleteOnboarding\x12(.hyapp.user.v1.CompleteOnboardingRequest\x1a).hyapp.user.v1.CompleteOnboardingResponse2\xc3\b\n" + "\x11UserSocialService\x12i\n" + @@ -7064,7 +7148,7 @@ func file_proto_user_v1_user_proto_rawDescGZIP() []byte { } var file_proto_user_v1_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 93) +var file_proto_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 94) var file_proto_user_v1_user_proto_goTypes = []any{ (UserStatus)(0), // 0: hyapp.user.v1.UserStatus (*RequestMeta)(nil), // 1: hyapp.user.v1.RequestMeta @@ -7122,44 +7206,45 @@ var file_proto_user_v1_user_proto_goTypes = []any{ (*UpdateUserProfileRequest)(nil), // 53: hyapp.user.v1.UpdateUserProfileRequest (*UpdateUserProfileResponse)(nil), // 54: hyapp.user.v1.UpdateUserProfileResponse (*ChangeUserCountryRequest)(nil), // 55: hyapp.user.v1.ChangeUserCountryRequest - (*ChangeUserCountryResponse)(nil), // 56: hyapp.user.v1.ChangeUserCountryResponse - (*SetUserStatusRequest)(nil), // 57: hyapp.user.v1.SetUserStatusRequest - (*SetUserStatusResponse)(nil), // 58: hyapp.user.v1.SetUserStatusResponse - (*CompleteOnboardingRequest)(nil), // 59: hyapp.user.v1.CompleteOnboardingRequest - (*CompleteOnboardingResponse)(nil), // 60: hyapp.user.v1.CompleteOnboardingResponse - (*BindPushTokenRequest)(nil), // 61: hyapp.user.v1.BindPushTokenRequest - (*BindPushTokenResponse)(nil), // 62: hyapp.user.v1.BindPushTokenResponse - (*DeletePushTokenRequest)(nil), // 63: hyapp.user.v1.DeletePushTokenRequest - (*DeletePushTokenResponse)(nil), // 64: hyapp.user.v1.DeletePushTokenResponse - (*Country)(nil), // 65: hyapp.user.v1.Country - (*Region)(nil), // 66: hyapp.user.v1.Region - (*ListCountriesRequest)(nil), // 67: hyapp.user.v1.ListCountriesRequest - (*ListCountriesResponse)(nil), // 68: hyapp.user.v1.ListCountriesResponse - (*UpdateCountryRequest)(nil), // 69: hyapp.user.v1.UpdateCountryRequest - (*CountryResponse)(nil), // 70: hyapp.user.v1.CountryResponse - (*ListRegistrationCountriesRequest)(nil), // 71: hyapp.user.v1.ListRegistrationCountriesRequest - (*ListRegistrationCountriesResponse)(nil), // 72: hyapp.user.v1.ListRegistrationCountriesResponse - (*LoginRiskBlockedCountry)(nil), // 73: hyapp.user.v1.LoginRiskBlockedCountry - (*ListLoginRiskBlockedCountriesRequest)(nil), // 74: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest - (*ListLoginRiskBlockedCountriesResponse)(nil), // 75: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse - (*ListRegionsRequest)(nil), // 76: hyapp.user.v1.ListRegionsRequest - (*ListRegionsResponse)(nil), // 77: hyapp.user.v1.ListRegionsResponse - (*GetRegionRequest)(nil), // 78: hyapp.user.v1.GetRegionRequest - (*UpdateRegionRequest)(nil), // 79: hyapp.user.v1.UpdateRegionRequest - (*ReplaceRegionCountriesRequest)(nil), // 80: hyapp.user.v1.ReplaceRegionCountriesRequest - (*RegionResponse)(nil), // 81: hyapp.user.v1.RegionResponse - (*UserIdentity)(nil), // 82: hyapp.user.v1.UserIdentity - (*GetUserIdentityRequest)(nil), // 83: hyapp.user.v1.GetUserIdentityRequest - (*GetUserIdentityResponse)(nil), // 84: hyapp.user.v1.GetUserIdentityResponse - (*ResolveDisplayUserIDRequest)(nil), // 85: hyapp.user.v1.ResolveDisplayUserIDRequest - (*ResolveDisplayUserIDResponse)(nil), // 86: hyapp.user.v1.ResolveDisplayUserIDResponse - (*ChangeDisplayUserIDRequest)(nil), // 87: hyapp.user.v1.ChangeDisplayUserIDRequest - (*ChangeDisplayUserIDResponse)(nil), // 88: hyapp.user.v1.ChangeDisplayUserIDResponse - (*ApplyPrettyDisplayUserIDRequest)(nil), // 89: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest - (*ApplyPrettyDisplayUserIDResponse)(nil), // 90: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse - (*ExpirePrettyDisplayUserIDRequest)(nil), // 91: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest - (*ExpirePrettyDisplayUserIDResponse)(nil), // 92: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse - nil, // 93: hyapp.user.v1.BatchGetUsersResponse.UsersEntry + (*AdminChangeUserCountryRequest)(nil), // 56: hyapp.user.v1.AdminChangeUserCountryRequest + (*ChangeUserCountryResponse)(nil), // 57: hyapp.user.v1.ChangeUserCountryResponse + (*SetUserStatusRequest)(nil), // 58: hyapp.user.v1.SetUserStatusRequest + (*SetUserStatusResponse)(nil), // 59: hyapp.user.v1.SetUserStatusResponse + (*CompleteOnboardingRequest)(nil), // 60: hyapp.user.v1.CompleteOnboardingRequest + (*CompleteOnboardingResponse)(nil), // 61: hyapp.user.v1.CompleteOnboardingResponse + (*BindPushTokenRequest)(nil), // 62: hyapp.user.v1.BindPushTokenRequest + (*BindPushTokenResponse)(nil), // 63: hyapp.user.v1.BindPushTokenResponse + (*DeletePushTokenRequest)(nil), // 64: hyapp.user.v1.DeletePushTokenRequest + (*DeletePushTokenResponse)(nil), // 65: hyapp.user.v1.DeletePushTokenResponse + (*Country)(nil), // 66: hyapp.user.v1.Country + (*Region)(nil), // 67: hyapp.user.v1.Region + (*ListCountriesRequest)(nil), // 68: hyapp.user.v1.ListCountriesRequest + (*ListCountriesResponse)(nil), // 69: hyapp.user.v1.ListCountriesResponse + (*UpdateCountryRequest)(nil), // 70: hyapp.user.v1.UpdateCountryRequest + (*CountryResponse)(nil), // 71: hyapp.user.v1.CountryResponse + (*ListRegistrationCountriesRequest)(nil), // 72: hyapp.user.v1.ListRegistrationCountriesRequest + (*ListRegistrationCountriesResponse)(nil), // 73: hyapp.user.v1.ListRegistrationCountriesResponse + (*LoginRiskBlockedCountry)(nil), // 74: hyapp.user.v1.LoginRiskBlockedCountry + (*ListLoginRiskBlockedCountriesRequest)(nil), // 75: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest + (*ListLoginRiskBlockedCountriesResponse)(nil), // 76: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse + (*ListRegionsRequest)(nil), // 77: hyapp.user.v1.ListRegionsRequest + (*ListRegionsResponse)(nil), // 78: hyapp.user.v1.ListRegionsResponse + (*GetRegionRequest)(nil), // 79: hyapp.user.v1.GetRegionRequest + (*UpdateRegionRequest)(nil), // 80: hyapp.user.v1.UpdateRegionRequest + (*ReplaceRegionCountriesRequest)(nil), // 81: hyapp.user.v1.ReplaceRegionCountriesRequest + (*RegionResponse)(nil), // 82: hyapp.user.v1.RegionResponse + (*UserIdentity)(nil), // 83: hyapp.user.v1.UserIdentity + (*GetUserIdentityRequest)(nil), // 84: hyapp.user.v1.GetUserIdentityRequest + (*GetUserIdentityResponse)(nil), // 85: hyapp.user.v1.GetUserIdentityResponse + (*ResolveDisplayUserIDRequest)(nil), // 86: hyapp.user.v1.ResolveDisplayUserIDRequest + (*ResolveDisplayUserIDResponse)(nil), // 87: hyapp.user.v1.ResolveDisplayUserIDResponse + (*ChangeDisplayUserIDRequest)(nil), // 88: hyapp.user.v1.ChangeDisplayUserIDRequest + (*ChangeDisplayUserIDResponse)(nil), // 89: hyapp.user.v1.ChangeDisplayUserIDResponse + (*ApplyPrettyDisplayUserIDRequest)(nil), // 90: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest + (*ApplyPrettyDisplayUserIDResponse)(nil), // 91: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse + (*ExpirePrettyDisplayUserIDRequest)(nil), // 92: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest + (*ExpirePrettyDisplayUserIDResponse)(nil), // 93: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse + nil, // 94: hyapp.user.v1.BatchGetUsersResponse.UsersEntry } var file_proto_user_v1_user_proto_depIdxs = []int32{ 1, // 0: hyapp.user.v1.ResolveAppRequest.meta:type_name -> hyapp.user.v1.RequestMeta @@ -7198,131 +7283,134 @@ var file_proto_user_v1_user_proto_depIdxs = []int32{ 1, // 33: hyapp.user.v1.SubmitReportRequest.meta:type_name -> hyapp.user.v1.RequestMeta 46, // 34: hyapp.user.v1.SubmitReportResponse.report:type_name -> hyapp.user.v1.UserReport 1, // 35: hyapp.user.v1.BatchGetUsersRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 93, // 36: hyapp.user.v1.BatchGetUsersResponse.users:type_name -> hyapp.user.v1.BatchGetUsersResponse.UsersEntry + 94, // 36: hyapp.user.v1.BatchGetUsersResponse.users:type_name -> hyapp.user.v1.BatchGetUsersResponse.UsersEntry 1, // 37: hyapp.user.v1.ListUserIDsRequest.meta:type_name -> hyapp.user.v1.RequestMeta 1, // 38: hyapp.user.v1.UpdateUserProfileRequest.meta:type_name -> hyapp.user.v1.RequestMeta 5, // 39: hyapp.user.v1.UpdateUserProfileResponse.user:type_name -> hyapp.user.v1.User 1, // 40: hyapp.user.v1.ChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 41: hyapp.user.v1.ChangeUserCountryResponse.user:type_name -> hyapp.user.v1.User - 1, // 42: hyapp.user.v1.SetUserStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 0, // 43: hyapp.user.v1.SetUserStatusRequest.status:type_name -> hyapp.user.v1.UserStatus - 5, // 44: hyapp.user.v1.SetUserStatusResponse.user:type_name -> hyapp.user.v1.User - 1, // 45: hyapp.user.v1.CompleteOnboardingRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 5, // 46: hyapp.user.v1.CompleteOnboardingResponse.user:type_name -> hyapp.user.v1.User - 13, // 47: hyapp.user.v1.CompleteOnboardingResponse.token:type_name -> hyapp.user.v1.AuthToken - 7, // 48: hyapp.user.v1.CompleteOnboardingResponse.invite:type_name -> hyapp.user.v1.InviteBinding - 1, // 49: hyapp.user.v1.BindPushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 50: hyapp.user.v1.DeletePushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 51: hyapp.user.v1.ListCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 65, // 52: hyapp.user.v1.ListCountriesResponse.countries:type_name -> hyapp.user.v1.Country - 1, // 53: hyapp.user.v1.UpdateCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 65, // 54: hyapp.user.v1.CountryResponse.country:type_name -> hyapp.user.v1.Country - 1, // 55: hyapp.user.v1.ListRegistrationCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 65, // 56: hyapp.user.v1.ListRegistrationCountriesResponse.countries:type_name -> hyapp.user.v1.Country - 1, // 57: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 73, // 58: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse.countries:type_name -> hyapp.user.v1.LoginRiskBlockedCountry - 1, // 59: hyapp.user.v1.ListRegionsRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 66, // 60: hyapp.user.v1.ListRegionsResponse.regions:type_name -> hyapp.user.v1.Region - 1, // 61: hyapp.user.v1.GetRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 62: hyapp.user.v1.UpdateRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 1, // 63: hyapp.user.v1.ReplaceRegionCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 66, // 64: hyapp.user.v1.RegionResponse.region:type_name -> hyapp.user.v1.Region - 1, // 65: hyapp.user.v1.GetUserIdentityRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 82, // 66: hyapp.user.v1.GetUserIdentityResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 67: hyapp.user.v1.ResolveDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 82, // 68: hyapp.user.v1.ResolveDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 69: hyapp.user.v1.ChangeDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 82, // 70: hyapp.user.v1.ChangeDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 71: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 82, // 72: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 1, // 73: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta - 82, // 74: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity - 5, // 75: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User - 14, // 76: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest - 16, // 77: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest - 20, // 78: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest - 49, // 79: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest - 51, // 80: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest - 9, // 81: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest - 53, // 82: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest - 55, // 83: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest - 57, // 84: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest - 59, // 85: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest - 22, // 86: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest - 25, // 87: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest - 27, // 88: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest - 29, // 89: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest - 32, // 90: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest - 34, // 91: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest - 36, // 92: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest - 38, // 93: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest - 41, // 94: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest - 44, // 95: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest - 47, // 96: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest - 11, // 97: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest - 11, // 98: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest - 11, // 99: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest - 61, // 100: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest - 63, // 101: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest - 3, // 102: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest - 67, // 103: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest - 69, // 104: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest - 71, // 105: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest - 74, // 106: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest - 76, // 107: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest - 78, // 108: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest - 79, // 109: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest - 80, // 110: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest - 83, // 111: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest - 85, // 112: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest - 87, // 113: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest - 89, // 114: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest - 91, // 115: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest - 15, // 116: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse - 18, // 117: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse - 21, // 118: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse - 50, // 119: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse - 52, // 120: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse - 10, // 121: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse - 54, // 122: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse - 56, // 123: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse - 58, // 124: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse - 60, // 125: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse - 23, // 126: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse - 26, // 127: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse - 28, // 128: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse - 30, // 129: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse - 33, // 130: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse - 35, // 131: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse - 37, // 132: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse - 39, // 133: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse - 42, // 134: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse - 45, // 135: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse - 48, // 136: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse - 12, // 137: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse - 12, // 138: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse - 12, // 139: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse - 62, // 140: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse - 64, // 141: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse - 4, // 142: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse - 68, // 143: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse - 70, // 144: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse - 72, // 145: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse - 75, // 146: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse - 77, // 147: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse - 81, // 148: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse - 81, // 149: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse - 81, // 150: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse - 84, // 151: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse - 86, // 152: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse - 88, // 153: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse - 90, // 154: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse - 92, // 155: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse - 116, // [116:156] is the sub-list for method output_type - 76, // [76:116] is the sub-list for method input_type - 76, // [76:76] is the sub-list for extension type_name - 76, // [76:76] is the sub-list for extension extendee - 0, // [0:76] is the sub-list for field type_name + 1, // 41: hyapp.user.v1.AdminChangeUserCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 42: hyapp.user.v1.ChangeUserCountryResponse.user:type_name -> hyapp.user.v1.User + 1, // 43: hyapp.user.v1.SetUserStatusRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 0, // 44: hyapp.user.v1.SetUserStatusRequest.status:type_name -> hyapp.user.v1.UserStatus + 5, // 45: hyapp.user.v1.SetUserStatusResponse.user:type_name -> hyapp.user.v1.User + 1, // 46: hyapp.user.v1.CompleteOnboardingRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 5, // 47: hyapp.user.v1.CompleteOnboardingResponse.user:type_name -> hyapp.user.v1.User + 13, // 48: hyapp.user.v1.CompleteOnboardingResponse.token:type_name -> hyapp.user.v1.AuthToken + 7, // 49: hyapp.user.v1.CompleteOnboardingResponse.invite:type_name -> hyapp.user.v1.InviteBinding + 1, // 50: hyapp.user.v1.BindPushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 51: hyapp.user.v1.DeletePushTokenRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 52: hyapp.user.v1.ListCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 66, // 53: hyapp.user.v1.ListCountriesResponse.countries:type_name -> hyapp.user.v1.Country + 1, // 54: hyapp.user.v1.UpdateCountryRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 66, // 55: hyapp.user.v1.CountryResponse.country:type_name -> hyapp.user.v1.Country + 1, // 56: hyapp.user.v1.ListRegistrationCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 66, // 57: hyapp.user.v1.ListRegistrationCountriesResponse.countries:type_name -> hyapp.user.v1.Country + 1, // 58: hyapp.user.v1.ListLoginRiskBlockedCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 74, // 59: hyapp.user.v1.ListLoginRiskBlockedCountriesResponse.countries:type_name -> hyapp.user.v1.LoginRiskBlockedCountry + 1, // 60: hyapp.user.v1.ListRegionsRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 67, // 61: hyapp.user.v1.ListRegionsResponse.regions:type_name -> hyapp.user.v1.Region + 1, // 62: hyapp.user.v1.GetRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 63: hyapp.user.v1.UpdateRegionRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 1, // 64: hyapp.user.v1.ReplaceRegionCountriesRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 67, // 65: hyapp.user.v1.RegionResponse.region:type_name -> hyapp.user.v1.Region + 1, // 66: hyapp.user.v1.GetUserIdentityRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 83, // 67: hyapp.user.v1.GetUserIdentityResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 68: hyapp.user.v1.ResolveDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 83, // 69: hyapp.user.v1.ResolveDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 70: hyapp.user.v1.ChangeDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 83, // 71: hyapp.user.v1.ChangeDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 72: hyapp.user.v1.ApplyPrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 83, // 73: hyapp.user.v1.ApplyPrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 1, // 74: hyapp.user.v1.ExpirePrettyDisplayUserIDRequest.meta:type_name -> hyapp.user.v1.RequestMeta + 83, // 75: hyapp.user.v1.ExpirePrettyDisplayUserIDResponse.identity:type_name -> hyapp.user.v1.UserIdentity + 5, // 76: hyapp.user.v1.BatchGetUsersResponse.UsersEntry.value:type_name -> hyapp.user.v1.User + 14, // 77: hyapp.user.v1.UserService.GetUser:input_type -> hyapp.user.v1.GetUserRequest + 16, // 78: hyapp.user.v1.UserService.BusinessUserLookup:input_type -> hyapp.user.v1.BusinessUserLookupRequest + 20, // 79: hyapp.user.v1.UserService.GetMyProfileStats:input_type -> hyapp.user.v1.GetMyProfileStatsRequest + 49, // 80: hyapp.user.v1.UserService.BatchGetUsers:input_type -> hyapp.user.v1.BatchGetUsersRequest + 51, // 81: hyapp.user.v1.UserService.ListUserIDs:input_type -> hyapp.user.v1.ListUserIDsRequest + 9, // 82: hyapp.user.v1.UserService.GetUserMicLifetimeStats:input_type -> hyapp.user.v1.GetUserMicLifetimeStatsRequest + 53, // 83: hyapp.user.v1.UserService.UpdateUserProfile:input_type -> hyapp.user.v1.UpdateUserProfileRequest + 55, // 84: hyapp.user.v1.UserService.ChangeUserCountry:input_type -> hyapp.user.v1.ChangeUserCountryRequest + 56, // 85: hyapp.user.v1.UserService.AdminChangeUserCountry:input_type -> hyapp.user.v1.AdminChangeUserCountryRequest + 58, // 86: hyapp.user.v1.UserService.SetUserStatus:input_type -> hyapp.user.v1.SetUserStatusRequest + 60, // 87: hyapp.user.v1.UserService.CompleteOnboarding:input_type -> hyapp.user.v1.CompleteOnboardingRequest + 22, // 88: hyapp.user.v1.UserSocialService.RecordProfileVisit:input_type -> hyapp.user.v1.RecordProfileVisitRequest + 25, // 89: hyapp.user.v1.UserSocialService.ListProfileVisitors:input_type -> hyapp.user.v1.ListProfileVisitorsRequest + 27, // 90: hyapp.user.v1.UserSocialService.FollowUser:input_type -> hyapp.user.v1.FollowUserRequest + 29, // 91: hyapp.user.v1.UserSocialService.UnfollowUser:input_type -> hyapp.user.v1.UnfollowUserRequest + 32, // 92: hyapp.user.v1.UserSocialService.ListFollowing:input_type -> hyapp.user.v1.ListFollowingRequest + 34, // 93: hyapp.user.v1.UserSocialService.ApplyFriend:input_type -> hyapp.user.v1.ApplyFriendRequest + 36, // 94: hyapp.user.v1.UserSocialService.AcceptFriendApplication:input_type -> hyapp.user.v1.AcceptFriendApplicationRequest + 38, // 95: hyapp.user.v1.UserSocialService.DeleteFriend:input_type -> hyapp.user.v1.DeleteFriendRequest + 41, // 96: hyapp.user.v1.UserSocialService.ListFriends:input_type -> hyapp.user.v1.ListFriendsRequest + 44, // 97: hyapp.user.v1.UserSocialService.ListFriendApplications:input_type -> hyapp.user.v1.ListFriendApplicationsRequest + 47, // 98: hyapp.user.v1.UserSocialService.SubmitReport:input_type -> hyapp.user.v1.SubmitReportRequest + 11, // 99: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:input_type -> hyapp.user.v1.CronBatchRequest + 11, // 100: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:input_type -> hyapp.user.v1.CronBatchRequest + 11, // 101: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:input_type -> hyapp.user.v1.CronBatchRequest + 62, // 102: hyapp.user.v1.UserDeviceService.BindPushToken:input_type -> hyapp.user.v1.BindPushTokenRequest + 64, // 103: hyapp.user.v1.UserDeviceService.DeletePushToken:input_type -> hyapp.user.v1.DeletePushTokenRequest + 3, // 104: hyapp.user.v1.AppRegistryService.ResolveApp:input_type -> hyapp.user.v1.ResolveAppRequest + 68, // 105: hyapp.user.v1.CountryAdminService.ListCountries:input_type -> hyapp.user.v1.ListCountriesRequest + 70, // 106: hyapp.user.v1.CountryAdminService.UpdateCountry:input_type -> hyapp.user.v1.UpdateCountryRequest + 72, // 107: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:input_type -> hyapp.user.v1.ListRegistrationCountriesRequest + 75, // 108: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:input_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesRequest + 77, // 109: hyapp.user.v1.RegionAdminService.ListRegions:input_type -> hyapp.user.v1.ListRegionsRequest + 79, // 110: hyapp.user.v1.RegionAdminService.GetRegion:input_type -> hyapp.user.v1.GetRegionRequest + 80, // 111: hyapp.user.v1.RegionAdminService.UpdateRegion:input_type -> hyapp.user.v1.UpdateRegionRequest + 81, // 112: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:input_type -> hyapp.user.v1.ReplaceRegionCountriesRequest + 84, // 113: hyapp.user.v1.UserIdentityService.GetUserIdentity:input_type -> hyapp.user.v1.GetUserIdentityRequest + 86, // 114: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:input_type -> hyapp.user.v1.ResolveDisplayUserIDRequest + 88, // 115: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:input_type -> hyapp.user.v1.ChangeDisplayUserIDRequest + 90, // 116: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:input_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDRequest + 92, // 117: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:input_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDRequest + 15, // 118: hyapp.user.v1.UserService.GetUser:output_type -> hyapp.user.v1.GetUserResponse + 18, // 119: hyapp.user.v1.UserService.BusinessUserLookup:output_type -> hyapp.user.v1.BusinessUserLookupResponse + 21, // 120: hyapp.user.v1.UserService.GetMyProfileStats:output_type -> hyapp.user.v1.GetMyProfileStatsResponse + 50, // 121: hyapp.user.v1.UserService.BatchGetUsers:output_type -> hyapp.user.v1.BatchGetUsersResponse + 52, // 122: hyapp.user.v1.UserService.ListUserIDs:output_type -> hyapp.user.v1.ListUserIDsResponse + 10, // 123: hyapp.user.v1.UserService.GetUserMicLifetimeStats:output_type -> hyapp.user.v1.GetUserMicLifetimeStatsResponse + 54, // 124: hyapp.user.v1.UserService.UpdateUserProfile:output_type -> hyapp.user.v1.UpdateUserProfileResponse + 57, // 125: hyapp.user.v1.UserService.ChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 57, // 126: hyapp.user.v1.UserService.AdminChangeUserCountry:output_type -> hyapp.user.v1.ChangeUserCountryResponse + 59, // 127: hyapp.user.v1.UserService.SetUserStatus:output_type -> hyapp.user.v1.SetUserStatusResponse + 61, // 128: hyapp.user.v1.UserService.CompleteOnboarding:output_type -> hyapp.user.v1.CompleteOnboardingResponse + 23, // 129: hyapp.user.v1.UserSocialService.RecordProfileVisit:output_type -> hyapp.user.v1.RecordProfileVisitResponse + 26, // 130: hyapp.user.v1.UserSocialService.ListProfileVisitors:output_type -> hyapp.user.v1.ListProfileVisitorsResponse + 28, // 131: hyapp.user.v1.UserSocialService.FollowUser:output_type -> hyapp.user.v1.FollowUserResponse + 30, // 132: hyapp.user.v1.UserSocialService.UnfollowUser:output_type -> hyapp.user.v1.UnfollowUserResponse + 33, // 133: hyapp.user.v1.UserSocialService.ListFollowing:output_type -> hyapp.user.v1.ListFollowingResponse + 35, // 134: hyapp.user.v1.UserSocialService.ApplyFriend:output_type -> hyapp.user.v1.ApplyFriendResponse + 37, // 135: hyapp.user.v1.UserSocialService.AcceptFriendApplication:output_type -> hyapp.user.v1.AcceptFriendApplicationResponse + 39, // 136: hyapp.user.v1.UserSocialService.DeleteFriend:output_type -> hyapp.user.v1.DeleteFriendResponse + 42, // 137: hyapp.user.v1.UserSocialService.ListFriends:output_type -> hyapp.user.v1.ListFriendsResponse + 45, // 138: hyapp.user.v1.UserSocialService.ListFriendApplications:output_type -> hyapp.user.v1.ListFriendApplicationsResponse + 48, // 139: hyapp.user.v1.UserSocialService.SubmitReport:output_type -> hyapp.user.v1.SubmitReportResponse + 12, // 140: hyapp.user.v1.UserCronService.ProcessLoginIPRiskBatch:output_type -> hyapp.user.v1.CronBatchResponse + 12, // 141: hyapp.user.v1.UserCronService.ProcessRegionRebuildBatch:output_type -> hyapp.user.v1.CronBatchResponse + 12, // 142: hyapp.user.v1.UserCronService.CompensateMicOpenSessions:output_type -> hyapp.user.v1.CronBatchResponse + 63, // 143: hyapp.user.v1.UserDeviceService.BindPushToken:output_type -> hyapp.user.v1.BindPushTokenResponse + 65, // 144: hyapp.user.v1.UserDeviceService.DeletePushToken:output_type -> hyapp.user.v1.DeletePushTokenResponse + 4, // 145: hyapp.user.v1.AppRegistryService.ResolveApp:output_type -> hyapp.user.v1.ResolveAppResponse + 69, // 146: hyapp.user.v1.CountryAdminService.ListCountries:output_type -> hyapp.user.v1.ListCountriesResponse + 71, // 147: hyapp.user.v1.CountryAdminService.UpdateCountry:output_type -> hyapp.user.v1.CountryResponse + 73, // 148: hyapp.user.v1.CountryQueryService.ListRegistrationCountries:output_type -> hyapp.user.v1.ListRegistrationCountriesResponse + 76, // 149: hyapp.user.v1.CountryQueryService.ListLoginRiskBlockedCountries:output_type -> hyapp.user.v1.ListLoginRiskBlockedCountriesResponse + 78, // 150: hyapp.user.v1.RegionAdminService.ListRegions:output_type -> hyapp.user.v1.ListRegionsResponse + 82, // 151: hyapp.user.v1.RegionAdminService.GetRegion:output_type -> hyapp.user.v1.RegionResponse + 82, // 152: hyapp.user.v1.RegionAdminService.UpdateRegion:output_type -> hyapp.user.v1.RegionResponse + 82, // 153: hyapp.user.v1.RegionAdminService.ReplaceRegionCountries:output_type -> hyapp.user.v1.RegionResponse + 85, // 154: hyapp.user.v1.UserIdentityService.GetUserIdentity:output_type -> hyapp.user.v1.GetUserIdentityResponse + 87, // 155: hyapp.user.v1.UserIdentityService.ResolveDisplayUserID:output_type -> hyapp.user.v1.ResolveDisplayUserIDResponse + 89, // 156: hyapp.user.v1.UserIdentityService.ChangeDisplayUserID:output_type -> hyapp.user.v1.ChangeDisplayUserIDResponse + 91, // 157: hyapp.user.v1.UserIdentityService.ApplyPrettyDisplayUserID:output_type -> hyapp.user.v1.ApplyPrettyDisplayUserIDResponse + 93, // 158: hyapp.user.v1.UserIdentityService.ExpirePrettyDisplayUserID:output_type -> hyapp.user.v1.ExpirePrettyDisplayUserIDResponse + 118, // [118:159] is the sub-list for method output_type + 77, // [77:118] is the sub-list for method input_type + 77, // [77:77] is the sub-list for extension type_name + 77, // [77:77] is the sub-list for extension extendee + 0, // [0:77] is the sub-list for field type_name } func init() { file_proto_user_v1_user_proto_init() } @@ -7331,14 +7419,14 @@ func file_proto_user_v1_user_proto_init() { return } file_proto_user_v1_user_proto_msgTypes[52].OneofWrappers = []any{} - file_proto_user_v1_user_proto_msgTypes[66].OneofWrappers = []any{} + file_proto_user_v1_user_proto_msgTypes[67].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_user_v1_user_proto_rawDesc), len(file_proto_user_v1_user_proto_rawDesc)), NumEnums: 1, - NumMessages: 93, + NumMessages: 94, NumExtensions: 0, NumServices: 9, }, diff --git a/api/proto/user/v1/user.proto b/api/proto/user/v1/user.proto index baa58b18..acffe48b 100644 --- a/api/proto/user/v1/user.proto +++ b/api/proto/user/v1/user.proto @@ -432,13 +432,22 @@ message UpdateUserProfileResponse { User user = 1; } -// ChangeUserCountryRequest 单独修改用户国家;该字段有冷却期和变更日志。 +// ChangeUserCountryRequest 是 App 用户自助修改国家入口;受限业务身份不允许自助修改。 message ChangeUserCountryRequest { RequestMeta meta = 1; int64 user_id = 2; string country = 3; } +// AdminChangeUserCountryRequest 是后台显式覆盖用户国家入口;它绕过 App 自助身份限制。 +message AdminChangeUserCountryRequest { + RequestMeta meta = 1; + int64 target_user_id = 2; + string country = 3; + int64 admin_user_id = 4; + string reason = 5; +} + // ChangeUserCountryResponse 返回更新后的用户资料和下一次可修改时间。 message ChangeUserCountryResponse { User user = 1; @@ -729,6 +738,7 @@ service UserService { rpc GetUserMicLifetimeStats(GetUserMicLifetimeStatsRequest) returns (GetUserMicLifetimeStatsResponse); rpc UpdateUserProfile(UpdateUserProfileRequest) returns (UpdateUserProfileResponse); rpc ChangeUserCountry(ChangeUserCountryRequest) returns (ChangeUserCountryResponse); + rpc AdminChangeUserCountry(AdminChangeUserCountryRequest) returns (ChangeUserCountryResponse); rpc SetUserStatus(SetUserStatusRequest) returns (SetUserStatusResponse); rpc CompleteOnboarding(CompleteOnboardingRequest) returns (CompleteOnboardingResponse); } diff --git a/api/proto/user/v1/user_grpc.pb.go b/api/proto/user/v1/user_grpc.pb.go index c4fc2f91..e7805d65 100644 --- a/api/proto/user/v1/user_grpc.pb.go +++ b/api/proto/user/v1/user_grpc.pb.go @@ -27,6 +27,7 @@ const ( UserService_GetUserMicLifetimeStats_FullMethodName = "/hyapp.user.v1.UserService/GetUserMicLifetimeStats" UserService_UpdateUserProfile_FullMethodName = "/hyapp.user.v1.UserService/UpdateUserProfile" UserService_ChangeUserCountry_FullMethodName = "/hyapp.user.v1.UserService/ChangeUserCountry" + UserService_AdminChangeUserCountry_FullMethodName = "/hyapp.user.v1.UserService/AdminChangeUserCountry" UserService_SetUserStatus_FullMethodName = "/hyapp.user.v1.UserService/SetUserStatus" UserService_CompleteOnboarding_FullMethodName = "/hyapp.user.v1.UserService/CompleteOnboarding" ) @@ -45,6 +46,7 @@ type UserServiceClient interface { GetUserMicLifetimeStats(ctx context.Context, in *GetUserMicLifetimeStatsRequest, opts ...grpc.CallOption) (*GetUserMicLifetimeStatsResponse, error) UpdateUserProfile(ctx context.Context, in *UpdateUserProfileRequest, opts ...grpc.CallOption) (*UpdateUserProfileResponse, error) ChangeUserCountry(ctx context.Context, in *ChangeUserCountryRequest, opts ...grpc.CallOption) (*ChangeUserCountryResponse, error) + AdminChangeUserCountry(ctx context.Context, in *AdminChangeUserCountryRequest, opts ...grpc.CallOption) (*ChangeUserCountryResponse, error) SetUserStatus(ctx context.Context, in *SetUserStatusRequest, opts ...grpc.CallOption) (*SetUserStatusResponse, error) CompleteOnboarding(ctx context.Context, in *CompleteOnboardingRequest, opts ...grpc.CallOption) (*CompleteOnboardingResponse, error) } @@ -137,6 +139,16 @@ func (c *userServiceClient) ChangeUserCountry(ctx context.Context, in *ChangeUse return out, nil } +func (c *userServiceClient) AdminChangeUserCountry(ctx context.Context, in *AdminChangeUserCountryRequest, opts ...grpc.CallOption) (*ChangeUserCountryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ChangeUserCountryResponse) + err := c.cc.Invoke(ctx, UserService_AdminChangeUserCountry_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *userServiceClient) SetUserStatus(ctx context.Context, in *SetUserStatusRequest, opts ...grpc.CallOption) (*SetUserStatusResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(SetUserStatusResponse) @@ -171,6 +183,7 @@ type UserServiceServer interface { GetUserMicLifetimeStats(context.Context, *GetUserMicLifetimeStatsRequest) (*GetUserMicLifetimeStatsResponse, error) UpdateUserProfile(context.Context, *UpdateUserProfileRequest) (*UpdateUserProfileResponse, error) ChangeUserCountry(context.Context, *ChangeUserCountryRequest) (*ChangeUserCountryResponse, error) + AdminChangeUserCountry(context.Context, *AdminChangeUserCountryRequest) (*ChangeUserCountryResponse, error) SetUserStatus(context.Context, *SetUserStatusRequest) (*SetUserStatusResponse, error) CompleteOnboarding(context.Context, *CompleteOnboardingRequest) (*CompleteOnboardingResponse, error) mustEmbedUnimplementedUserServiceServer() @@ -207,6 +220,9 @@ func (UnimplementedUserServiceServer) UpdateUserProfile(context.Context, *Update func (UnimplementedUserServiceServer) ChangeUserCountry(context.Context, *ChangeUserCountryRequest) (*ChangeUserCountryResponse, error) { return nil, status.Error(codes.Unimplemented, "method ChangeUserCountry not implemented") } +func (UnimplementedUserServiceServer) AdminChangeUserCountry(context.Context, *AdminChangeUserCountryRequest) (*ChangeUserCountryResponse, error) { + return nil, status.Error(codes.Unimplemented, "method AdminChangeUserCountry not implemented") +} func (UnimplementedUserServiceServer) SetUserStatus(context.Context, *SetUserStatusRequest) (*SetUserStatusResponse, error) { return nil, status.Error(codes.Unimplemented, "method SetUserStatus not implemented") } @@ -378,6 +394,24 @@ func _UserService_ChangeUserCountry_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _UserService_AdminChangeUserCountry_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AdminChangeUserCountryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServiceServer).AdminChangeUserCountry(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: UserService_AdminChangeUserCountry_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServiceServer).AdminChangeUserCountry(ctx, req.(*AdminChangeUserCountryRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _UserService_SetUserStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SetUserStatusRequest) if err := dec(in); err != nil { @@ -453,6 +487,10 @@ var UserService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ChangeUserCountry", Handler: _UserService_ChangeUserCountry_Handler, }, + { + MethodName: "AdminChangeUserCountry", + Handler: _UserService_AdminChangeUserCountry_Handler, + }, { MethodName: "SetUserStatus", Handler: _UserService_SetUserStatus_Handler, diff --git a/docs/房间区域置顶.md b/docs/房间区域置顶.md index d6fc1fed..5cefec5d 100644 --- a/docs/房间区域置顶.md +++ b/docs/房间区域置顶.md @@ -1,46 +1,329 @@ -# 房间区域置顶 +# 房间置顶与房间列表排序产品开发文档 -房间置顶是公共房间发现列表的运营排序能力。房间列表按 `visible_region_id` 隔离,所以置顶也按区域生效:后台选择一个房间后,后端使用该房间当前 `visible_region_id` 建立 `room_region_pins` 记录。 +## 目标 -## 边界 +后台在「房间管理」下增加二级菜单「房间置顶」,用于运营配置公共房间发现页的置顶顺序。 -- `room-service` 仍然是房间状态 owner;置顶不进入 Room Cell、snapshot 或 command log。 -- 置顶只影响 `GET /api/v1/rooms?tab=hot/new` 的排序,不影响进房权限。 -- 有效置顶条件为 `status=active` 且 `expires_at_ms > now_ms`。 -- 房间改区域后,旧区域置顶不会自动迁移到新区域;后台需要取消旧置顶并在新区域重新置顶。 +置顶只影响 App 房间发现列表排序,不改变房间状态、不改变房间区域、不影响进房权限。 -## 排序 +## 后台页面 -同一区域公共列表排序: +菜单:房间管理 / 房间置顶 -1. 有效置顶房间排在普通房间之前。 -2. 置顶房间按 `weight DESC, expires_at_ms DESC, room_id ASC`。 -3. 非置顶房间保留原排序:`hot` 按 `sort_score DESC`,`new` 按 `created_at_ms DESC`。 +列表展示: -列表 cursor 包含置顶分区、权重、过期时间和原列表排序键,跨页时不会重复返回置顶房间。 +| 字段 | 说明 | +| --- | --- | +| 房间信息 | 房间头像、房间名、房间长 ID、房间短 ID | +| 房主信息 | 房主头像、昵称、用户长 ID、用户短 ID | +| 区域 | 房间当前区域 | +| 置顶时间 | `pinnedAtMs` 到 `expiresAtMs` | +| 排序 | `weight`,数值越大越靠前 | +| 置顶类型 | `global` 全区置顶;`region` 区域置顶 | +| 状态 | `active` 生效中;`expired` 已过期;`cancelled` 已取消 | + +新增置顶流程: + +1. 输入用户短 ID 或房间 ID 搜索房间。 +2. 选择置顶类型:全区置顶或区域置顶。 +3. 选择置顶开始时间和结束时间。 +4. 填写排序值,数值越大越靠前。 +5. 点击置顶后,后台创建置顶记录。 + +区域规则: + +- 全区置顶对所有用户国家/区域生效。 +- 区域置顶只对房间当前区域生效,不需要后台单独选择区域。 +- 房间后续改区域时,置顶记录不会自动改区域;后台可以取消旧置顶后重新置顶。 + +过期规则: + +- 当前时间不在 `[pinnedAtMs, expiresAtMs)` 内时,App 列表不再把该房间当置顶房间。 +- 过期后房间自动恢复普通房间排序,不需要修改房间状态。 +- 后台列表读取时会把已过期的 active 记录展示为 `expired`。 + +## App 房间列表排序 + +地址:`GET /api/v1/rooms` + +参数: + +| 参数 | 说明 | +| --- | --- | +| `tab` | `hot` 或 `new` | +| `limit` | 每页数量 | +| `cursor` | 下一页游标 | +| `q` | 搜索关键词,可不传 | + +区域来源: + +- gateway 使用登录用户 ID 调 user-service 获取 `users.region_id`。 +- 客户端传的区域参数不会生效。 +- room-service 按该用户区域做排序分组。 + +`hot` 排序: + +1. 全区置顶房间,多个房间按 `weight DESC`。 +2. 当前用户区域的置顶房间,多个房间按 `weight DESC`。 +3. 当前用户区域有人普通房,按 `hot_score DESC`。 +4. 其他区域有人普通房,按 `hot_score DESC`。 +5. 当前用户区域空房,按 `hot_score DESC`。 +6. 其他区域空房,按 `hot_score DESC`。 + +`hot_score` 规则: + +```text +heat_score = log2(heat + 1) +online_score = log2(min(online_count, 50) + 1) +mic_score = min(occupied_seat_count, 10) + +hot_score = heat_score * 650000 + + online_score * 300000 + + mic_score * 50000 +``` + +说明: + +- `heat` 是房间贡献值。 +- `online_count = 0` 的普通房进入空房分组;只要存在有人普通房,空房不会排在有人普通房前面。 +- 在线人数最多按 50 人计分,防止单个房间靠人数无限放大。 +- 上麦人数最多按 10 人计分,只作为活跃气氛补充。 + +`new` 排序: + +1. 全区置顶房间,多个房间按 `weight DESC`。 +2. 当前用户区域的置顶房间,多个房间按 `weight DESC`。 +3. 当前用户区域的普通房间,按创建时间 `created_at_ms DESC`。 +4. 其他区域的普通房间,按创建时间 `created_at_ms DESC`。 + +同一个排序分组内,如果排序值相同,后端使用过期时间和房间 ID 保证分页稳定。 + +返回值: + +```json +{ + "code": 0, + "message": "ok", + "request_id": "request-id", + "data": { + "rooms": [ + { + "room_id": "room-global-pin", + "room_short_id": "163212", + "owner_user_id": "165059", + "title": "room name", + "cover_url": "https://example.com/room.png", + "visible_region_id": 2, + "heat": 1000, + "online_count": 0, + "locked": false + } + ], + "next_cursor": "" + } +} +``` + +相关 IM: + +- 无新增 IM。 +- 置顶只影响 HTTP 房间列表读模型,不发送房间群消息或用户私信。 + +## 房间列表在线人数更新逻辑 + +房间列表返回的 `online_count` 来自 room-service 的业务 presence,不直接读取腾讯 IM 在线人数,也不直接读取 RTC 在线人数。 + +更新入口: + +| 入口 | 说明 | 列表人数变化 | +| --- | --- | --- | +| `POST /api/v1/rooms/join` | 用户进房,room-service 把用户写入 Room Cell 的 `OnlineUsers` | 增加或保持不变 | +| `POST /api/v1/rooms/heartbeat` | 用户在房间内刷新 `LastSeenAtMS` | 人数不变,只延长在线有效期 | +| `POST /api/v1/rooms/leave` | 用户主动离房,room-service 从 `OnlineUsers` 删除用户 | 减少 | +| 踢人、关房、系统驱逐 | 房间命令链路清理 presence | 减少或清零 | +| stale worker | 用户断线、杀进程、没有主动离房时,由后台扫描清理超时 presence | 延迟减少 | + +投影规则: + +- 每次 Room Cell 命令成功提交后,room-service 用最新快照刷新 `room_list_entries`。 +- `room_list_entries.online_count = len(snapshot.online_users)`。 +- `room_list_entries.occupied_seat_count` 来自当前被占用麦位数。 +- `hot_score` 使用 `online_count` 和 `occupied_seat_count`,所以在线人数变化会影响 hot 普通房排序。 +- 列表投影是最终一致读模型;投影失败只记录日志,不回滚已经成功的房间命令。 + +延迟: + +| 场景 | 预计延迟 | +| --- | --- | +| 正常进房 | 同一次 `JoinRoom` 命令内刷新,通常是毫秒级到几十毫秒 | +| 主动离房 | 同一次 `LeaveRoom` 命令内刷新,通常是毫秒级到几十毫秒 | +| 踢人、关房、系统驱逐 | 同一次房间命令内刷新,通常是毫秒级到几十毫秒 | +| 心跳 | 只刷新有效期,不改变列表人数 | +| App 断线或杀进程且没有主动离房 | 当前配置 `presence_stale_after = 2m`,`presence_stale_scan_interval = 30s`,通常约 2 分钟到 2 分 30 秒后列表人数减少 | + +相关 IM: + +- 无新增 IM。 +- 在线人数是 room-service 业务 presence,不等于腾讯 IM 长连接在线人数。 +- 腾讯 IM 退群、RTC 退房不会直接删除 room-service presence;业务离房只能由 `LeaveRoom`、踢人、关房、系统驱逐或 stale worker 完成。 ## 后台接口 后台接口使用后台登录 token 和 `/api/v1` 前缀。 -| 方法 | 路径 | 权限 | 说明 | -| --- | --- | --- | --- | -| `GET` | `/api/v1/admin/rooms/pins` | `room-pin:view` | 查询房间置顶列表,默认只返回有效置顶 | -| `POST` | `/api/v1/admin/rooms/pins` | `room-pin:create` | 新增或恢复房间置顶 | -| `DELETE` | `/api/v1/admin/rooms/pins/{pin_id}` | `room-pin:cancel` | 取消房间置顶 | +### 查询置顶列表 -创建请求: +地址:`GET /api/v1/admin/rooms/pins` + +参数: + +| 参数 | 说明 | +| --- | --- | +| `page` | 页码,默认 1 | +| `page_size` | 每页数量,默认 20,最大 100 | +| `keyword` | 房间 ID、房间短 ID、房间名关键词 | +| `status` | `active`、`expired`、`cancelled`、`all`,默认 `active` | +| `pinType` | `global` 或 `region`,不传表示全部类型 | +| `regionId` | 区域筛选,不传表示全部区域 | + +返回值: ```json { - "roomId": "room_123", - "weight": 100, - "durationDays": 30 + "code": 0, + "message": "ok", + "data": { + "items": [ + { + "id": 1, + "pinType": "global", + "status": "active", + "weight": 100, + "pinnedAtMs": 1780665600000, + "expiresAtMs": 1783257600000, + "remainingMs": 2592000000, + "room": { + "roomId": "room-global-pin", + "roomShortId": "163212", + "title": "room name", + "visibleRegionId": 2, + "regionName": "南亚区" + }, + "user": { + "userId": "165059", + "displayUserId": "165059", + "username": "host name" + } + } + ], + "page": 1, + "pageSize": 20, + "total": 1 + } } ``` -- `roomId` 可以是长房间 ID 或短房间 ID,最终落库使用长房间 ID。 -- `durationDays` 不传时默认 30 天。 -- 只能置顶当前 `active` 房间。 +### 搜索房间 -列表返回的 `room` 包含房间长短 ID、昵称、头像和区域;`user` 包含房主头像、长短 ID 和昵称;`remainingMs` 是当前 UTC 业务时间下的剩余毫秒数。 +地址:`GET /api/v1/admin/rooms` + +参数: + +| 参数 | 说明 | +| --- | --- | +| `keyword` | 用户短 ID、房间短 ID、房间长 ID、房间名 | +| `status` | 建议新增置顶时传 `active` | +| `page` | 页码 | +| `page_size` | 每页数量 | + +说明: + +- 输入用户短 ID 时,后台会先查用户,再按房主用户 ID 精确查房间。 +- 输入房间 ID 时,后台直接按 room-service 房间列表查询。 + +### 新增置顶 + +地址:`POST /api/v1/admin/rooms/pins` + +参数: + +| 参数 | 说明 | +| --- | --- | +| `roomId` | 房间长 ID 或房间短 ID | +| `pinType` | `global` 全区置顶;`region` 区域置顶;不传默认 `region` | +| `weight` | 排序值,不能小于 0 | +| `pinnedAtMs` | 置顶开始时间,Unix 毫秒 | +| `expiresAtMs` | 置顶结束时间,Unix 毫秒 | +| `durationDays` | 旧字段兼容;新后台优先传开始和结束时间 | + +请求示例: + +```json +{ + "roomId": "room-global-pin", + "pinType": "global", + "weight": 100, + "pinnedAtMs": 1780665600000, + "expiresAtMs": 1783257600000 +} +``` + +返回值:返回创建后的置顶记录,结构同列表单条记录。 + +### 取消置顶 + +地址:`DELETE /api/v1/admin/rooms/pins/{pin_id}` + +参数: + +| 参数 | 说明 | +| --- | --- | +| `pin_id` | 置顶记录 ID | + +返回值:返回取消后的置顶记录,状态为 `cancelled`。 + +相关 IM: + +- 无新增 IM。 +- 新增、取消、过期置顶都只影响发现页排序。 + +## 数据规则 + +- `room_region_pins.pin_type = global` 表示全区置顶,落库 `visible_region_id = 0`。 +- `room_region_pins.pin_type = region` 表示区域置顶,落库 `visible_region_id = 房间当前 visible_region_id`。 +- 有效置顶条件:`status = active` 且 `pinned_at_ms <= now_ms` 且 `expires_at_ms > now_ms`。 +- 同一个房间可以同时有全区置顶和区域置顶;App 列表优先按全区置顶分组展示。 +- `hot` 普通房先按本区域/其他区域和有人/空房分组,再按 `hot_score` 排序。 +- `new` 普通房只按本区域/其他区域分组,再按创建时间排序。 +- 置顶不进入 Room Cell、snapshot 或 command log;它是发现页运营排序读模型。 +- 房间核心状态仍由 room-service 管理,后台不直接写房间库。 + +## 本地真实数据验证 + +验证环境: + +- 本地 Docker MySQL:`hyapp-mysql`,端口 `23306`,状态 healthy。 +- 用真实 MySQL 临时库执行 room-service 用例,不使用 memory repository。 + +验证命令: + +```bash +ROOM_SERVICE_MYSQL_TEST_DSN='root:root@tcp(127.0.0.1:23306)/?parseTime=true&loc=UTC&multiStatements=true' \ +go test ./services/room-service/internal/room/service \ + -run 'TestRoomListSortScore|TestPinnedRoomListOrdersGlobalRegionLocalThenOtherFor(Hot|New)|TestRegionalPinOrdersPublicRoomList' \ + -count=1 -v +``` + +验证结果: + +- `TestRegionalPinOrdersPublicRoomList` 通过,验证区域置顶优先于同区域普通 hot 房间。 +- `TestPinnedRoomListOrdersGlobalRegionLocalThenOtherForHot` 通过,验证 hot 顺序为全区置顶、当前区域置顶、当前区域有人普通房、其他区域有人普通房、当前区域空房、其他区域空房。 +- `TestPinnedRoomListOrdersGlobalRegionLocalThenOtherForNew` 通过,验证 new 顺序为全区置顶、当前区域置顶、当前区域普通房、其他区域普通房。 +- `TestRoomListSortScoreUsesCompressedWeightedInputs` 通过,验证 `hot_score` 使用 65%、30%、5% 的压缩权重。 +- `TestRoomListSortScoreCapsPresenceInputs` 通过,验证在线人数和上麦人数有计分上限。 +- 测试过程创建了真实房间数据:`room-global-pin`、`room-region-pin`、`room-local-online`、`room-other-online`、`room-local-empty`、`room-other-empty`、`room-global-new`、`room-region-new` 等。 + +补充说明: + +- 普通 `hyapp` MySQL 用户没有创建临时库权限,所以本地真实数据验证使用 root DSN 建临时库。 +- 该验证不连接线上库,不影响线上数据。 diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index b3844776..634a9051 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -70,6 +70,7 @@ import ( mysqlDriver "github.com/go-sql-driver/mysql" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -154,32 +155,32 @@ func main() { } } - userConn, err := grpc.Dial(cfg.UserService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + userConn, err := dialBackendGRPC(cfg.UserService.Addr) if err != nil { fatalRuntime("connect_user_service_failed", err) } defer userConn.Close() - walletConn, err := grpc.Dial(cfg.WalletService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + walletConn, err := dialBackendGRPC(cfg.WalletService.Addr) if err != nil { fatalRuntime("connect_wallet_service_failed", err) } defer walletConn.Close() - roomConn, err := grpc.Dial(cfg.RoomService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + roomConn, err := dialBackendGRPC(cfg.RoomService.Addr) if err != nil { fatalRuntime("connect_room_service_failed", err) } defer roomConn.Close() roomClient := roomclient.NewGRPC(roomConn) - activityConn, err := grpc.Dial(cfg.ActivityService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + activityConn, err := dialBackendGRPC(cfg.ActivityService.Addr) if err != nil { fatalRuntime("connect_activity_service_failed", err) } defer activityConn.Close() - gameConn, err := grpc.Dial(cfg.GameService.Addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + gameConn, err := dialBackendGRPC(cfg.GameService.Addr) if err != nil { fatalRuntime("connect_game_service_failed", err) } @@ -245,7 +246,7 @@ func main() { Report: reportmodule.New(userDB, roomClient), RegistrationReward: registrationrewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), RegionBlock: regionblockmodule.New(userDB, auditHandler), - Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, auditHandler), + Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, cfg.WalletService.RequestTimeout, auditHandler), RoomAdmin: roomadminmodule.New(userDB, roomClient, auditHandler), RoomRocket: roomrocketmodule.New(roomClient, auditHandler), Search: searchmodule.New(store), @@ -287,6 +288,19 @@ func fatalRuntime(msg string, err error) { os.Exit(1) } +func dialBackendGRPC(addr string) (*grpc.ClientConn, error) { + // admin-server 在广州跨区访问 Saudi 内网 CLB;gRPC 长连接如果长时间空闲, + // TCP 层可能留下半开连接。客户端 keepalive 主动探活并触发重连,避免请求卡到 HTTP 超时。 + return grpc.Dial(addr, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithKeepaliveParams(keepalive.ClientParameters{ + Time: 30 * time.Second, + Timeout: 10 * time.Second, + PermitWithoutStream: true, + }), + ) +} + func ensureDatabase(dsn string) error { parsed, err := mysqlDriver.ParseDSN(dsn) if err != nil { diff --git a/server/admin/configs/config.tencent.example.yaml b/server/admin/configs/config.tencent.example.yaml index 3276871b..aabc4613 100644 --- a/server/admin/configs/config.tencent.example.yaml +++ b/server/admin/configs/config.tencent.example.yaml @@ -39,7 +39,7 @@ user_service: request_timeout: "10s" wallet_service: addr: "10.2.1.15:13004" - request_timeout: "3s" + request_timeout: "10s" room_service: addr: "10.2.1.16:13001" request_timeout: "3s" diff --git a/server/admin/docs/权限管理.md b/server/admin/docs/权限管理.md index 3ca741f6..3cb305c4 100644 --- a/server/admin/docs/权限管理.md +++ b/server/admin/docs/权限管理.md @@ -245,8 +245,8 @@ | `room:update` | `button` | 后台修改房间展示资料、模式、状态、区域 | | `room:delete` | `button` | 后台删除房间 | | `room-pin:view` | `menu` | 房间置顶菜单、置顶列表 | -| `room-pin:create` | `button` | 新增或恢复区域房间置顶 | -| `room-pin:cancel` | `button` | 取消区域房间置顶 | +| `room-pin:create` | `button` | 新增或恢复房间置顶 | +| `room-pin:cancel` | `button` | 取消房间置顶 | | `room-config:view` | `menu` | 房间配置页面、读取座位数配置 | | `room-config:update` | `button` | 保存启用座位数和默认座位数 | | `room:create` | `button` | 后台创建房间 | diff --git a/server/admin/internal/integration/roomclient/client.go b/server/admin/internal/integration/roomclient/client.go index 9bd3574f..dae3fe6e 100644 --- a/server/admin/internal/integration/roomclient/client.go +++ b/server/admin/internal/integration/roomclient/client.go @@ -34,6 +34,7 @@ type ListRoomsRequest struct { Keyword string Status string RegionID int64 + OwnerUserID int64 SortBy string SortDirection string } @@ -169,6 +170,7 @@ type RoomPinRoom struct { type RoomPin struct { ID int64 VisibleRegionID int64 + PinType string RoomID string Weight int64 Status string @@ -188,6 +190,7 @@ type ListRoomPinsRequest struct { Keyword string Status string RegionID int64 + PinType string } type ListRoomPinsResult struct { @@ -197,8 +200,11 @@ type ListRoomPinsResult struct { type CreateRoomPinRequest struct { RoomID string + PinType string Weight int64 DurationDays int64 + PinnedAtMS int64 + ExpiresAtMS int64 AdminID uint64 } @@ -245,6 +251,7 @@ func (c *GRPCClient) ListRooms(ctx context.Context, req ListRoomsRequest) (*List Keyword: strings.TrimSpace(req.Keyword), Status: strings.TrimSpace(req.Status), VisibleRegionId: req.RegionID, + OwnerUserId: req.OwnerUserID, SortBy: strings.TrimSpace(req.SortBy), SortDirection: strings.TrimSpace(req.SortDirection), }) @@ -351,6 +358,7 @@ func (c *GRPCClient) ListRoomPins(ctx context.Context, req ListRoomPinsRequest) Keyword: strings.TrimSpace(req.Keyword), Status: strings.TrimSpace(req.Status), VisibleRegionId: req.RegionID, + PinType: strings.TrimSpace(req.PinType), }) if err != nil { return ListRoomPinsResult{}, err @@ -366,8 +374,11 @@ func (c *GRPCClient) CreateRoomPin(ctx context.Context, req CreateRoomPinRequest resp, err := c.client.AdminCreateRoomPin(ctx, &roomv1.AdminCreateRoomPinRequest{ Meta: requestMeta(ctx, strings.TrimSpace(req.RoomID), int64(req.AdminID), "admin-create-room-pin"), RoomId: strings.TrimSpace(req.RoomID), + PinType: strings.TrimSpace(req.PinType), Weight: req.Weight, DurationDays: req.DurationDays, + PinnedAtMs: req.PinnedAtMS, + ExpiresAtMs: req.ExpiresAtMS, AdminId: req.AdminID, }) if err != nil { @@ -525,6 +536,7 @@ func roomPinFromProto(input *roomv1.AdminRoomPin) RoomPin { return RoomPin{ ID: input.GetId(), VisibleRegionID: input.GetVisibleRegionId(), + PinType: input.GetPinType(), RoomID: input.GetRoomId(), Weight: input.GetWeight(), Status: input.GetStatus(), diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 49f0ca71..958e16f1 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -12,6 +12,7 @@ import ( type Client interface { GetUser(ctx context.Context, req GetUserRequest) (*User, error) + AdminChangeUserCountry(ctx context.Context, req AdminChangeUserCountryRequest) (*ChangeUserCountryResult, error) SetUserStatus(ctx context.Context, req SetUserStatusRequest) (*SetUserStatusResult, error) ResolveDisplayUserID(ctx context.Context, req ResolveDisplayUserIDRequest) (*UserIdentity, error) ListCountries(ctx context.Context, req ListCountriesRequest) ([]*Country, error) @@ -28,6 +29,7 @@ type Client interface { GetCoinSellerProfile(ctx context.Context, req GetCoinSellerProfileRequest) (*CoinSellerProfile, error) CreateAgency(ctx context.Context, req CreateAgencyRequest) (*CreateAgencyResult, error) CloseAgency(ctx context.Context, req CloseAgencyRequest) (*Agency, error) + DeleteAgency(ctx context.Context, req DeleteAgencyRequest) (*Agency, error) SetAgencyJoinEnabled(ctx context.Context, req SetAgencyJoinEnabledRequest) (*Agency, error) } @@ -47,6 +49,22 @@ type SetUserStatusRequest struct { Reason string } +type AdminChangeUserCountryRequest struct { + RequestID string + Caller string + TargetUserID int64 + Country string + AdminUserID int64 + Reason string +} + +type ChangeUserCountryResult struct { + User *User `json:"user"` + OldRegionID int64 `json:"oldRegionId"` + NewRegionID int64 `json:"newRegionId"` + RegionChanged bool `json:"regionChanged"` +} + type SetUserStatusResult struct { User *User `json:"user"` RevokedSessionCount int64 `json:"revokedSessionCount"` @@ -142,6 +160,25 @@ func (c *GRPCClient) GetUser(ctx context.Context, req GetUserRequest) (*User, er return fromProtoUser(resp.GetUser()), nil } +func (c *GRPCClient) AdminChangeUserCountry(ctx context.Context, req AdminChangeUserCountryRequest) (*ChangeUserCountryResult, error) { + resp, err := c.client.AdminChangeUserCountry(ctx, &userv1.AdminChangeUserCountryRequest{ + Meta: requestMeta(ctx, req.RequestID, req.Caller), + TargetUserId: req.TargetUserID, + Country: req.Country, + AdminUserId: req.AdminUserID, + Reason: req.Reason, + }) + if err != nil { + return nil, err + } + return &ChangeUserCountryResult{ + User: fromProtoUser(resp.GetUser()), + OldRegionID: resp.GetOldRegionId(), + NewRegionID: resp.GetNewRegionId(), + RegionChanged: resp.GetRegionChanged(), + }, nil +} + func (c *GRPCClient) SetUserStatus(ctx context.Context, req SetUserStatusRequest) (*SetUserStatusResult, error) { resp, err := c.client.SetUserStatus(ctx, &userv1.SetUserStatusRequest{ Meta: requestMeta(ctx, req.RequestID, req.Caller), @@ -260,7 +297,6 @@ type CreateBDLeaderRequest struct { Caller string CommandID string AdminUserID int64 - RegionID int64 TargetUserID int64 Reason string } @@ -319,7 +355,6 @@ type CreateAgencyRequest struct { ParentBDUserID int64 Name string JoinEnabled bool - MaxHosts int32 Reason string } @@ -332,6 +367,15 @@ type CloseAgencyRequest struct { Reason string } +type DeleteAgencyRequest struct { + RequestID string + Caller string + CommandID string + AdminUserID int64 + AgencyID int64 + Reason string +} + type SetAgencyJoinEnabledRequest struct { RequestID string Caller string @@ -443,7 +487,6 @@ func (c *GRPCClient) CreateBDLeader(ctx context.Context, req CreateBDLeaderReque Meta: requestMeta(ctx, req.RequestID, req.Caller), CommandId: req.CommandID, AdminUserId: req.AdminUserID, - RegionId: req.RegionID, TargetUserId: req.TargetUserID, Reason: req.Reason, }) @@ -532,7 +575,6 @@ func (c *GRPCClient) CreateAgency(ctx context.Context, req CreateAgencyRequest) ParentBdUserId: req.ParentBDUserID, Name: req.Name, JoinEnabled: req.JoinEnabled, - MaxHosts: req.MaxHosts, Reason: req.Reason, }) if err != nil { @@ -559,6 +601,20 @@ func (c *GRPCClient) CloseAgency(ctx context.Context, req CloseAgencyRequest) (* return fromProtoAgency(resp.GetAgency()), nil } +func (c *GRPCClient) DeleteAgency(ctx context.Context, req DeleteAgencyRequest) (*Agency, error) { + resp, err := c.hostAdminClient.DeleteAgency(ctx, &userv1.DeleteAgencyRequest{ + Meta: requestMeta(ctx, req.RequestID, req.Caller), + CommandId: req.CommandID, + AdminUserId: req.AdminUserID, + AgencyId: req.AgencyID, + Reason: req.Reason, + }) + if err != nil { + return nil, err + } + return fromProtoAgency(resp.GetAgency()), nil +} + func (c *GRPCClient) SetAgencyJoinEnabled(ctx context.Context, req SetAgencyJoinEnabledRequest) (*Agency, error) { resp, err := c.hostAdminClient.SetAgencyJoinEnabled(ctx, &userv1.SetAgencyJoinEnabledRequest{ Meta: requestMeta(ctx, req.RequestID, req.Caller), diff --git a/server/admin/internal/modules/appuser/handler.go b/server/admin/internal/modules/appuser/handler.go index 3b67b485..9aaa38a7 100644 --- a/server/admin/internal/modules/appuser/handler.go +++ b/server/admin/internal/modules/appuser/handler.go @@ -99,7 +99,7 @@ func (h *Handler) UpdateUser(c *gin.Context) { response.BadRequest(c, "用户参数不正确") return } - user, err := h.service.UpdateUser(c.Request.Context(), userID, middleware.CurrentRequestID(c), req) + user, err := h.service.UpdateUser(c.Request.Context(), userID, int64(middleware.CurrentUserID(c)), middleware.CurrentRequestID(c), req) if err != nil { writeMutationError(c, err, "更新 App 用户失败") return diff --git a/server/admin/internal/modules/appuser/service.go b/server/admin/internal/modules/appuser/service.go index 9cced22b..42e2def1 100644 --- a/server/admin/internal/modules/appuser/service.go +++ b/server/admin/internal/modules/appuser/service.go @@ -322,11 +322,11 @@ func (s *Service) GetUser(ctx context.Context, userID int64) (AppUser, error) { return items[0], nil } -func (s *Service) UpdateUser(ctx context.Context, userID int64, requestID string, req updateUserRequest) (AppUser, error) { +func (s *Service) UpdateUser(ctx context.Context, userID int64, adminUserID int64, requestID string, req updateUserRequest) (AppUser, error) { if s.userDB == nil { return AppUser{}, fmt.Errorf("user mysql is not configured") } - sets := make([]string, 0, 6) + sets := make([]string, 0, 4) args := make([]any, 0, 8) if req.Username != nil { value := strings.TrimSpace(*req.Username) @@ -352,47 +352,48 @@ func (s *Service) UpdateUser(ctx context.Context, userID int64, requestID string sets = append(sets, "gender = ?") args = append(args, nullableString(value)) } - oldRegionID := int64(0) - if req.Country != nil { - before, err := s.GetUser(ctx, userID) + + if len(sets) > 0 { + sets = append(sets, "updated_at_ms = ?") + appCode := appctx.FromContext(ctx) + args = append(args, nowMillis()) + args = append(args, appCode, userID) + result, err := s.userDB.ExecContext(ctx, "UPDATE users SET "+strings.Join(sets, ", ")+" WHERE app_code = ? AND user_id = ?", args...) if err != nil { return AppUser{}, err } - oldRegionID = before.RegionID - country, regionID, err := s.resolveCountryRegion(ctx, *req.Country) + affected, err := result.RowsAffected() if err != nil { return AppUser{}, err } - sets = append(sets, "country = ?", "region_id = ?") - args = append(args, nullableString(country), nullableInt64(regionID)) - } - if len(sets) == 0 { - return s.GetUser(ctx, userID) + if affected == 0 { + return AppUser{}, ErrNotFound + } } - sets = append(sets, "updated_at_ms = ?") - appCode := appctx.FromContext(ctx) - args = append(args, nowMillis()) - args = append(args, appCode, userID) - result, err := s.userDB.ExecContext(ctx, "UPDATE users SET "+strings.Join(sets, ", ")+" WHERE app_code = ? AND user_id = ?", args...) - if err != nil { - return AppUser{}, err - } - affected, err := result.RowsAffected() - if err != nil { - return AppUser{}, err - } - if affected == 0 { - return AppUser{}, ErrNotFound - } - updated, err := s.GetUser(ctx, userID) - if err != nil { - return AppUser{}, err - } if req.Country != nil { - s.removeOldRegionBroadcastMemberBestEffort(ctx, userID, oldRegionID, updated.RegionID, strings.TrimSpace(requestID), "admin_user_country_changed") + if s.userClient == nil { + return AppUser{}, fmt.Errorf("user client is not configured") + } + change, err := s.userClient.AdminChangeUserCountry(ctx, userclient.AdminChangeUserCountryRequest{ + RequestID: strings.TrimSpace(requestID), + Caller: "hyapp-admin-server", + TargetUserID: userID, + Country: *req.Country, + AdminUserID: adminUserID, + Reason: "admin_user_country_changed", + }) + if err != nil { + return AppUser{}, err + } + if change != nil && change.RegionChanged { + s.removeOldRegionBroadcastMemberBestEffort(ctx, userID, change.OldRegionID, change.NewRegionID, strings.TrimSpace(requestID), "admin_user_country_changed") + } } - return updated, nil + if len(sets) == 0 && req.Country == nil { + return s.GetUser(ctx, userID) + } + return s.GetUser(ctx, userID) } func (s *Service) removeOldRegionBroadcastMemberBestEffort(ctx context.Context, userID int64, oldRegionID int64, newRegionID int64, requestID string, reason string) { @@ -491,45 +492,6 @@ func (s *Service) SetPassword(ctx context.Context, userID int64, password string return err } -func (s *Service) resolveCountryRegion(ctx context.Context, input string) (string, int64, error) { - country := normalizeCountryCode(input) - if country == "" { - return "", 0, fmt.Errorf("%w: 请选择国家", ErrInvalidArgument) - } - if !validCountryCode(country) { - return "", 0, fmt.Errorf("%w: 国家码必须是 2 到 3 位大写字母", ErrInvalidArgument) - } - - appCode := appctx.FromContext(ctx) - var canonical string - var regionID int64 - err := s.userDB.QueryRowContext(ctx, ` - SELECT c.country_code, - COALESCE(( - SELECT rg.region_id - FROM region_countries rc - INNER JOIN regions rg ON rg.region_id = rc.region_id - WHERE rc.app_code = c.app_code - AND rg.app_code = c.app_code - AND rc.country_code = c.country_code - AND rc.status = 'active' - AND rg.status = 'active' - AND rg.region_code NOT IN ('Australia and New Zealand', 'Caribbean', 'Melanesia', 'Micronesia', 'Polynesia', 'Southern Africa', 'UNSPECIFIED') - ORDER BY rg.sort_order ASC, rg.region_id ASC - LIMIT 1 - ), 0) - FROM countries c - WHERE c.app_code = ? AND c.country_code = ? AND c.enabled = TRUE - `, appCode, country).Scan(&canonical, ®ionID) - if errors.Is(err, sql.ErrNoRows) { - return "", 0, fmt.Errorf("%w: 国家不存在或已停用", ErrInvalidArgument) - } - if err != nil { - return "", 0, err - } - return canonical, regionID, nil -} - func (s *Service) fillBalances(ctx context.Context, items []AppUser, userIDs []int64) error { if s.walletDB == nil || len(userIDs) == 0 { return nil @@ -680,26 +642,10 @@ func nullableString(value string) sql.Null[string] { return sql.Null[string]{V: value, Valid: value != ""} } -func nullableInt64(value int64) sql.Null[int64] { - return sql.Null[int64]{V: value, Valid: value > 0} -} - func normalizeCountryCode(value string) string { return strings.ToUpper(strings.TrimSpace(value)) } -func validCountryCode(value string) bool { - if len(value) < 2 || len(value) > 3 { - return false - } - for _, char := range value { - if char < 'A' || char > 'Z' { - return false - } - } - return true -} - func nowMillis() int64 { return time.Now().UnixMilli() } diff --git a/server/admin/internal/modules/hostorg/handler.go b/server/admin/internal/modules/hostorg/handler.go index 851e6a92..e0026ae4 100644 --- a/server/admin/internal/modules/hostorg/handler.go +++ b/server/admin/internal/modules/hostorg/handler.go @@ -101,7 +101,7 @@ func (h *Handler) CreateBDLeader(c *gin.Context) { return } writeHostOrgAuditLog(c, h.audit, "create-bd-leader", "bd_profiles", profile.UserID, - fmt.Sprintf("command_id=%s user_id=%d region_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, req.RegionID, strings.TrimSpace(req.PositionAlias), strings.TrimSpace(req.Reason))) + fmt.Sprintf("command_id=%s user_id=%d region_id=%d position_alias=%q reason=%q", strings.TrimSpace(req.CommandID), profile.UserID, profile.RegionID, strings.TrimSpace(req.PositionAlias), strings.TrimSpace(req.Reason))) response.Created(c, profile) } @@ -303,6 +303,26 @@ func (h *Handler) CloseAgency(c *gin.Context) { response.OK(c, agency) } +func (h *Handler) DeleteAgency(c *gin.Context) { + agencyID, ok := parseInt64ID(c, "agency_id") + if !ok { + return + } + var req agencyDeleteRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "删除 Agency 参数不正确") + return + } + agency, err := h.service.DeleteAgency(c.Request.Context(), adminActorID(c), agencyID, middleware.CurrentRequestID(c), req) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + writeHostOrgAuditLog(c, h.audit, "delete-agency", "agencies", agency.AgencyID, + fmt.Sprintf("command_id=%s agency_id=%d status=%s reason=%q", strings.TrimSpace(req.CommandID), agency.AgencyID, agency.Status, strings.TrimSpace(req.Reason))) + response.OK(c, agency) +} + func (h *Handler) SetAgencyJoinEnabled(c *gin.Context) { agencyID, ok := parseInt64ID(c, "agency_id") if !ok { diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index 59f06056..b3362702 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -408,6 +408,9 @@ func (r *Reader) ListAgencies(ctx context.Context, query listQuery) ([]*userclie if query.Status != "" { whereSQL += " AND a.status = ?" args = append(args, query.Status) + } else { + whereSQL += " AND a.status <> ?" + args = append(args, "deleted") } if query.RegionID > 0 { whereSQL += " AND a.region_id = ?" diff --git a/server/admin/internal/modules/hostorg/request.go b/server/admin/internal/modules/hostorg/request.go index ed964a3f..186bdc23 100644 --- a/server/admin/internal/modules/hostorg/request.go +++ b/server/admin/internal/modules/hostorg/request.go @@ -16,7 +16,6 @@ type listQuery struct { type createBDLeaderRequest struct { CommandID string `json:"commandId" binding:"required"` TargetUserID int64 `json:"targetUserId" binding:"required"` - RegionID int64 `json:"regionId" binding:"required"` PositionAlias string `json:"positionAlias"` Reason string `json:"reason"` } @@ -85,7 +84,6 @@ type createAgencyRequest struct { ParentBDUserID int64 `json:"parentBdUserId"` Name string `json:"name" binding:"required"` JoinEnabled *bool `json:"joinEnabled" binding:"required"` - MaxHosts int32 `json:"maxHosts"` Reason string `json:"reason"` } @@ -99,3 +97,8 @@ type agencyCloseRequest struct { CommandID string `json:"commandId" binding:"required"` Reason string `json:"reason"` } + +type agencyDeleteRequest struct { + CommandID string `json:"commandId" binding:"required"` + Reason string `json:"reason"` +} diff --git a/server/admin/internal/modules/hostorg/routes.go b/server/admin/internal/modules/hostorg/routes.go index 1c0fb302..c7df19d6 100644 --- a/server/admin/internal/modules/hostorg/routes.go +++ b/server/admin/internal/modules/hostorg/routes.go @@ -18,6 +18,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/admin/agencies", middleware.RequirePermission("agency:view"), h.ListAgencies) protected.POST("/admin/agencies", middleware.RequirePermission("agency:create"), h.CreateAgency) protected.POST("/admin/agencies/:agency_id/close", middleware.RequirePermission("agency:status"), h.CloseAgency) + protected.POST("/admin/agencies/:agency_id/delete", middleware.RequirePermission("agency:delete"), h.DeleteAgency) protected.POST("/admin/agencies/:agency_id/join-enabled", middleware.RequirePermission("agency:status"), h.SetAgencyJoinEnabled) protected.GET("/admin/hosts", middleware.RequirePermission("host:view"), h.ListHosts) protected.GET("/admin/coin-sellers", middleware.RequirePermission("coin-seller:view"), h.ListCoinSellers) diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index 8ddebd59..fed44301 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -123,13 +123,12 @@ func (s *Service) CreateBDLeader(ctx context.Context, actorID int64, requestID s if err != nil { return nil, err } - // BD Leader 创建时后台选择的区域是显式运营归属,由 user-service 在同一事务里更新 users.region_id 和 bd_profiles.region_id。 + // BD Leader 区域由目标用户当前 users.region_id 派生;后台不再传区域,避免创建角色时顺手迁移用户国家/区域。 profile, err := s.userClient.CreateBDLeader(ctx, userclient.CreateBDLeaderRequest{ RequestID: requestID, Caller: "hyapp-admin-server", CommandID: strings.TrimSpace(req.CommandID), AdminUserID: actorID, - RegionID: req.RegionID, TargetUserID: targetUserID, Reason: strings.TrimSpace(req.Reason), }) @@ -346,7 +345,6 @@ func (s *Service) CreateAgency(ctx context.Context, actorID int64, requestID str ParentBDUserID: parentBDUserID, Name: strings.TrimSpace(req.Name), JoinEnabled: joinEnabled, - MaxHosts: req.MaxHosts, Reason: strings.TrimSpace(req.Reason), }) } @@ -362,6 +360,17 @@ func (s *Service) CloseAgency(ctx context.Context, actorID int64, agencyID int64 }) } +func (s *Service) DeleteAgency(ctx context.Context, actorID int64, agencyID int64, requestID string, req agencyDeleteRequest) (*userclient.Agency, error) { + return s.userClient.DeleteAgency(ctx, userclient.DeleteAgencyRequest{ + RequestID: requestID, + Caller: "hyapp-admin-server", + CommandID: strings.TrimSpace(req.CommandID), + AdminUserID: actorID, + AgencyID: agencyID, + Reason: strings.TrimSpace(req.Reason), + }) +} + func (s *Service) resolveDisplayUserID(ctx context.Context, requestID string, displayUserID int64) (int64, error) { if displayUserID <= 0 { return 0, fmt.Errorf("display_user_id is required") diff --git a/server/admin/internal/modules/resource/handler.go b/server/admin/internal/modules/resource/handler.go index dc2a9cf1..323bc86e 100644 --- a/server/admin/internal/modules/resource/handler.go +++ b/server/admin/internal/modules/resource/handler.go @@ -1,11 +1,13 @@ package resource import ( + "context" "database/sql" "fmt" "sort" "strconv" "strings" + "time" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/integration/walletclient" @@ -19,19 +21,30 @@ import ( ) type Handler struct { - wallet walletclient.Client - store *repository.Store - userDB *sql.DB - audit shared.OperationLogger + wallet walletclient.Client + store *repository.Store + userDB *sql.DB + requestTimeout time.Duration + audit shared.OperationLogger } -func New(wallet walletclient.Client, store *repository.Store, userDB *sql.DB, audit shared.OperationLogger) *Handler { - return &Handler{wallet: wallet, store: store, userDB: userDB, audit: audit} +func New(wallet walletclient.Client, store *repository.Store, userDB *sql.DB, requestTimeout time.Duration, audit shared.OperationLogger) *Handler { + if requestTimeout <= 0 { + requestTimeout = 3 * time.Second + } + return &Handler{wallet: wallet, store: store, userDB: userDB, requestTimeout: requestTimeout, audit: audit} +} + +func (h *Handler) walletRequestContext(c *gin.Context) (context.Context, context.CancelFunc) { + // 资源后台在广州 admin-server 跨区访问 Saudi wallet-service;每次 RPC 必须继承 HTTP 取消信号并设置硬上限,避免坏连接拖到前置 504。 + return context.WithTimeout(c.Request.Context(), h.requestTimeout) } func (h *Handler) ListResources(c *gin.Context) { options := shared.ListOptions(c) - resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{ + ctx, cancel := h.walletRequestContext(c) + defer cancel() + resp, err := h.wallet.ListResources(ctx, &walletv1.ListResourcesRequest{ RequestId: middleware.CurrentRequestID(c), AppCode: appctx.FromContext(c.Request.Context()), ResourceType: strings.TrimSpace(c.Query("resource_type")), @@ -94,7 +107,9 @@ func (h *Handler) CreateResource(c *gin.Context) { func (h *Handler) ListEmojiPacks(c *gin.Context) { options := shared.ListOptions(c) - resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{ + ctx, cancel := h.walletRequestContext(c) + defer cancel() + resp, err := h.wallet.ListResources(ctx, &walletv1.ListResourcesRequest{ RequestId: middleware.CurrentRequestID(c), AppCode: appctx.FromContext(c.Request.Context()), ResourceType: resourceTypeEmojiPack, @@ -117,8 +132,10 @@ func (h *Handler) ListEmojiPacks(c *gin.Context) { func (h *Handler) ListEmojiPackCategories(c *gin.Context) { const pageSize int32 = 100 categories := map[string]struct{}{} + ctx, cancel := h.walletRequestContext(c) + defer cancel() for page := int32(1); ; page++ { - resp, err := h.wallet.ListResources(c.Request.Context(), &walletv1.ListResourcesRequest{ + resp, err := h.wallet.ListResources(ctx, &walletv1.ListResourcesRequest{ RequestId: middleware.CurrentRequestID(c), AppCode: appctx.FromContext(c.Request.Context()), ResourceType: resourceTypeEmojiPack, @@ -207,7 +224,9 @@ func (h *Handler) DisableResource(c *gin.Context) { func (h *Handler) ListResourceGroups(c *gin.Context) { options := shared.ListOptions(c) - resp, err := h.wallet.ListResourceGroups(c.Request.Context(), &walletv1.ListResourceGroupsRequest{ + ctx, cancel := h.walletRequestContext(c) + defer cancel() + resp, err := h.wallet.ListResourceGroups(ctx, &walletv1.ListResourceGroupsRequest{ RequestId: middleware.CurrentRequestID(c), AppCode: appctx.FromContext(c.Request.Context()), Status: options.Status, @@ -294,15 +313,15 @@ func (h *Handler) ListGifts(c *gin.Context) { return } resp, err := h.wallet.ListGiftConfigs(c.Request.Context(), &walletv1.ListGiftConfigsRequest{ - RequestId: middleware.CurrentRequestID(c), - AppCode: appctx.FromContext(c.Request.Context()), - Status: options.Status, - Keyword: options.Keyword, - Page: int32(options.Page), - PageSize: int32(options.PageSize), - RegionId: regionID, - FilterRegion: filterRegion, - GiftTypeCode: giftTypeCodeQuery(c), + RequestId: middleware.CurrentRequestID(c), + AppCode: appctx.FromContext(c.Request.Context()), + Status: options.Status, + Keyword: options.Keyword, + Page: int32(options.Page), + PageSize: int32(options.PageSize), + RegionId: regionID, + FilterRegion: filterRegion, + GiftTypeCode: giftTypeCodeQuery(c), }) if err != nil { response.ServerError(c, "获取礼物列表失败") diff --git a/server/admin/internal/modules/roomadmin/handler.go b/server/admin/internal/modules/roomadmin/handler.go index 7de1ec06..24dd3ec0 100644 --- a/server/admin/internal/modules/roomadmin/handler.go +++ b/server/admin/internal/modules/roomadmin/handler.go @@ -60,7 +60,7 @@ func (h *Handler) CreateRoomPin(c *gin.Context) { writeMutationError(c, err, "新增房间置顶失败") return } - writeRoomAuditLog(c, h.audit, "create-room-pin", "room_region_pins", pin.Room.RoomID, "success", "create regional room pin") + writeRoomAuditLog(c, h.audit, "create-room-pin", "room_region_pins", pin.Room.RoomID, "success", "create room pin") response.Created(c, pin) } @@ -74,7 +74,7 @@ func (h *Handler) CancelRoomPin(c *gin.Context) { writeMutationError(c, err, "取消房间置顶失败") return } - writeRoomAuditLog(c, h.audit, "cancel-room-pin", "room_region_pins", strconv.FormatInt(pinID, 10), "success", "cancel regional room pin") + writeRoomAuditLog(c, h.audit, "cancel-room-pin", "room_region_pins", strconv.FormatInt(pinID, 10), "success", "cancel room pin") response.OK(c, pin) } @@ -162,6 +162,7 @@ func parseRoomPinListQuery(c *gin.Context) (roomPinListQuery, bool) { Keyword: options.Keyword, Page: options.Page, PageSize: options.PageSize, + PinType: firstQueryValue(c, "pinType", "pin_type"), RegionID: regionID, Status: options.Status, }), true diff --git a/server/admin/internal/modules/roomadmin/pin.go b/server/admin/internal/modules/roomadmin/pin.go index 36536469..c6701a08 100644 --- a/server/admin/internal/modules/roomadmin/pin.go +++ b/server/admin/internal/modules/roomadmin/pin.go @@ -15,6 +15,8 @@ const ( roomPinStatusCancelled = "cancelled" roomPinStatusExpired = "expired" roomPinStatusAll = "all" + roomPinTypeRegion = "region" + roomPinTypeGlobal = "global" defaultRoomPinDays = int64(30) maxRoomPinDays = int64(3650) roomPinDayMillis = int64(24 * 60 * 60 * 1000) @@ -37,6 +39,7 @@ type RoomPin struct { CreatedByAdminID uint `json:"createdByAdminId"` ExpiresAtMS int64 `json:"expiresAtMs"` ID int64 `json:"id"` + PinType string `json:"pinType"` PinnedAtMS int64 `json:"pinnedAtMs"` RemainingMS int64 `json:"remainingMs"` Room RoomPinRoom `json:"room"` @@ -57,6 +60,7 @@ func (s *Service) ListRoomPins(ctx context.Context, query roomPinListQuery) ([]R Keyword: query.Keyword, Status: query.Status, RegionID: query.RegionID, + PinType: query.PinType, }) if err != nil { return nil, 0, err @@ -78,8 +82,11 @@ func (s *Service) CreateRoomPin(ctx context.Context, req createRoomPinRequest, a } pin, err := s.roomClient.CreateRoomPin(ctx, roomclient.CreateRoomPinRequest{ RoomID: input.RoomID, + PinType: input.PinType, Weight: input.Weight, DurationDays: input.DurationDays, + PinnedAtMS: input.PinnedAtMS, + ExpiresAtMS: input.ExpiresAtMS, AdminID: uint64(actorID), }) if err != nil { @@ -124,12 +131,24 @@ func normalizeRoomPinListQuery(query roomPinListQuery) roomPinListQuery { } query.Keyword = strings.TrimSpace(query.Keyword) query.Status = normalizeRoomPinStatus(query.Status) + query.PinType = normalizeRoomPinType(query.PinType) if query.RegionID < 0 { query.RegionID = 0 } return query } +func normalizeRoomPinType(pinType string) string { + switch strings.ToLower(strings.TrimSpace(pinType)) { + case roomPinTypeGlobal: + return roomPinTypeGlobal + case roomPinTypeRegion: + return roomPinTypeRegion + default: + return "" + } +} + func normalizeRoomPinStatus(status string) string { switch strings.ToLower(strings.TrimSpace(status)) { case "", roomPinStatusActive: @@ -153,12 +172,27 @@ func normalizeCreateRoomPinRequest(req createRoomPinRequest) (createRoomPinReque if req.Weight < 0 { return req, fmt.Errorf("%w: 权重不能小于 0", ErrInvalidArgument) } - if req.DurationDays == 0 { + req.PinType = normalizeRoomPinType(req.PinType) + if req.PinType == "" { + req.PinType = roomPinTypeRegion + } + if req.PinnedAtMS <= 0 { + req.PinnedAtMS = time.Now().UTC().UnixMilli() + } + if req.ExpiresAtMS <= 0 && req.DurationDays == 0 { req.DurationDays = defaultRoomPinDays } - if req.DurationDays < 0 || req.DurationDays > maxRoomPinDays { + if req.ExpiresAtMS <= 0 { + req.ExpiresAtMS = req.PinnedAtMS + req.DurationDays*roomPinDayMillis + } + if req.ExpiresAtMS <= req.PinnedAtMS { + return req, fmt.Errorf("%w: 置顶时间区间不正确", ErrInvalidArgument) + } + durationDays := (req.ExpiresAtMS - req.PinnedAtMS + roomPinDayMillis - 1) / roomPinDayMillis + if durationDays < 1 || durationDays > maxRoomPinDays { return req, fmt.Errorf("%w: 置顶时间必须在 1 到 3650 天之间", ErrInvalidArgument) } + req.DurationDays = durationDays return req, nil } @@ -182,6 +216,7 @@ func roomPinFromClient(input roomclient.RoomPin) RoomPin { } return RoomPin{ ID: input.ID, + PinType: firstNonEmpty(input.PinType, roomPinTypeRegion), Weight: input.Weight, Status: input.Status, PinnedAtMS: input.PinnedAtMS, @@ -241,6 +276,15 @@ func scanRoomPin(row roomPinScanner) (RoomPin, error) { return item, err } +func firstNonEmpty(values ...string) string { + for _, value := range values { + if strings.TrimSpace(value) != "" { + return strings.TrimSpace(value) + } + } + return "" +} + func (s *Service) fillRoomPinDetails(ctx context.Context, items []RoomPin) error { if s.userDB == nil || len(items) == 0 { return nil diff --git a/server/admin/internal/modules/roomadmin/pin_test.go b/server/admin/internal/modules/roomadmin/pin_test.go index 563c8860..07ed1d20 100644 --- a/server/admin/internal/modules/roomadmin/pin_test.go +++ b/server/admin/internal/modules/roomadmin/pin_test.go @@ -20,9 +20,28 @@ func TestNormalizeCreateRoomPinRequestDefaultsDuration(t *testing.T) { if err != nil { t.Fatalf("normalize create pin failed: %v", err) } - if req.RoomID != "room-1" || req.DurationDays != defaultRoomPinDays || req.Weight != 10 { + if req.RoomID != "room-1" || req.DurationDays != defaultRoomPinDays || req.PinType != roomPinTypeRegion || req.Weight != 10 { t.Fatalf("create pin normalization mismatch: %+v", req) } + if req.PinnedAtMS <= 0 || req.ExpiresAtMS <= req.PinnedAtMS { + t.Fatalf("create pin interval should be normalized: %+v", req) + } +} + +func TestNormalizeCreateRoomPinRequestAcceptsExplicitIntervalAndType(t *testing.T) { + req, err := normalizeCreateRoomPinRequest(createRoomPinRequest{ + RoomID: "room-1", + PinType: roomPinTypeGlobal, + Weight: 10, + PinnedAtMS: 1000, + ExpiresAtMS: 2000, + }) + if err != nil { + t.Fatalf("normalize explicit create pin failed: %v", err) + } + if req.PinType != roomPinTypeGlobal || req.DurationDays != 1 || req.PinnedAtMS != 1000 || req.ExpiresAtMS != 2000 { + t.Fatalf("explicit interval normalization mismatch: %+v", req) + } } func TestNormalizeCreateRoomPinRequestRejectsInvalidInput(t *testing.T) { @@ -33,6 +52,7 @@ func TestNormalizeCreateRoomPinRequestRejectsInvalidInput(t *testing.T) { {name: "empty_room", req: createRoomPinRequest{Weight: 1, DurationDays: 30}}, {name: "negative_weight", req: createRoomPinRequest{RoomID: "room-1", Weight: -1, DurationDays: 30}}, {name: "duration_too_large", req: createRoomPinRequest{RoomID: "room-1", Weight: 1, DurationDays: maxRoomPinDays + 1}}, + {name: "bad_interval", req: createRoomPinRequest{RoomID: "room-1", Weight: 1, PinnedAtMS: 2000, ExpiresAtMS: 1000}}, } for _, test := range tests { diff --git a/server/admin/internal/modules/roomadmin/request.go b/server/admin/internal/modules/roomadmin/request.go index e462cfa8..908f1a45 100644 --- a/server/admin/internal/modules/roomadmin/request.go +++ b/server/admin/internal/modules/roomadmin/request.go @@ -14,12 +14,16 @@ type roomPinListQuery struct { Keyword string Page int PageSize int + PinType string RegionID int64 Status string } type createRoomPinRequest struct { DurationDays int64 `json:"durationDays"` + ExpiresAtMS int64 `json:"expiresAtMs"` + PinType string `json:"pinType"` + PinnedAtMS int64 `json:"pinnedAtMs"` RoomID string `json:"roomId"` Weight int64 `json:"weight"` } diff --git a/server/admin/internal/modules/roomadmin/service.go b/server/admin/internal/modules/roomadmin/service.go index d5fe387f..01dc950c 100644 --- a/server/admin/internal/modules/roomadmin/service.go +++ b/server/admin/internal/modules/roomadmin/service.go @@ -78,6 +78,30 @@ func (s *Service) ListRooms(ctx context.Context, query listQuery) ([]Room, int64 if err != nil { return nil, 0, err } + if result.Total == 0 && strings.TrimSpace(query.Keyword) != "" && s.userDB != nil { + ownerUserID, ok, err := s.queryOwnerUserIDByDisplayID(ctx, query.Keyword) + if err != nil { + return nil, 0, err + } + if ok { + // 新增置顶弹窗按用户短 ID 找房间;精确解析到 user_id 后交给 room-service owner 过滤,避免字符串 LIKE 误命中。 + fallback, err := s.roomClient.ListRooms(ctx, roomclient.ListRoomsRequest{ + Page: query.Page, + PageSize: query.PageSize, + Status: query.Status, + RegionID: query.RegionID, + OwnerUserID: ownerUserID, + SortBy: query.SortBy, + SortDirection: query.SortDirection, + }) + if err != nil { + return nil, 0, err + } + if fallback.Total > 0 { + result = fallback + } + } + } items := roomsFromClient(result.Rooms) if err := s.fillRoomDetails(ctx, items); err != nil { return nil, 0, err @@ -85,6 +109,27 @@ func (s *Service) ListRooms(ctx context.Context, query listQuery) ([]Room, int64 return items, result.Total, nil } +func (s *Service) queryOwnerUserIDByDisplayID(ctx context.Context, displayUserID string) (int64, bool, error) { + displayUserID = strings.TrimSpace(displayUserID) + if displayUserID == "" || s.userDB == nil { + return 0, false, nil + } + var userID int64 + err := s.userDB.QueryRowContext(ctx, ` + SELECT user_id + FROM users + WHERE app_code = ? AND current_display_user_id = ? + LIMIT 1 + `, appctx.FromContext(ctx), displayUserID).Scan(&userID) + if errors.Is(err, sql.ErrNoRows) { + return 0, false, nil + } + if err != nil { + return 0, false, err + } + return userID, true, nil +} + func (s *Service) GetRoom(ctx context.Context, roomID string) (Room, error) { item, err := s.roomClient.GetRoom(ctx, roomclient.GetRoomRequest{RoomID: roomID}) if err != nil { diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 9ebf7071..68fb881e 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -77,6 +77,7 @@ var defaultPermissions = []model.Permission{ {Name: "Agency 查看", Code: "agency:view", Kind: "menu"}, {Name: "Agency 创建", Code: "agency:create", Kind: "button"}, {Name: "Agency 状态", Code: "agency:status", Kind: "button"}, + {Name: "Agency 删除", Code: "agency:delete", Kind: "button"}, {Name: "BD 查看", Code: "bd:view", Kind: "menu"}, {Name: "BD 创建", Code: "bd:create", Kind: "button"}, {Name: "BD 更新", Code: "bd:update", Kind: "button"}, @@ -500,7 +501,7 @@ func defaultRolePermissionCodes(code string) []string { "country:view", "country:create", "country:update", "country:status", "region:view", "region:create", "region:update", "region:status", "host:view", "host-agency-policy:view", "host-agency-policy:create", "host-agency-policy:update", "host-agency-policy:delete", "host-agency-policy:publish", "team-salary-policy:view", "team-salary-policy:create", "team-salary-policy:update", "team-salary-policy:delete", "host-salary-settlement:view", "host-salary-settlement:settle", - "agency:view", "agency:create", "agency:status", + "agency:view", "agency:create", "agency:status", "agency:delete", "bd:view", "bd:create", "bd:update", "coin-seller:view", "coin-seller:create", "coin-seller:update", "coin-seller:stock-credit", "coin-seller:exchange-rate", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "coin-adjustment:create", "report:view", "gift-diamond:view", "gift-diamond:update", "payment-bill:view", "payment-product:view", "payment-product:create", "payment-product:update", "payment-product:delete", diff --git a/services/activity-service/configs/config.docker.yaml b/services/activity-service/configs/config.docker.yaml index 56cbcc91..a3a14c1a 100644 --- a/services/activity-service/configs/config.docker.yaml +++ b/services/activity-service/configs/config.docker.yaml @@ -66,6 +66,11 @@ rocketmq: first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 + user_outbox: + enabled: true + topic: "hyapp_user_outbox" + consumer_group: "hyapp-activity-user-region-broadcast" + consumer_max_reconsume_times: 16 consumer: room_outbox_poll_interval_ms: 1000 batch_size: 100 diff --git a/services/activity-service/configs/config.tencent.example.yaml b/services/activity-service/configs/config.tencent.example.yaml index 8b100f40..1bedba25 100644 --- a/services/activity-service/configs/config.tencent.example.yaml +++ b/services/activity-service/configs/config.tencent.example.yaml @@ -65,6 +65,11 @@ rocketmq: first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 + user_outbox: + enabled: true + topic: "hyapp_user_outbox" + consumer_group: "hyapp-activity-user-region-broadcast" + consumer_max_reconsume_times: 16 consumer: room_outbox_poll_interval_ms: 1000 batch_size: 100 diff --git a/services/activity-service/configs/config.yaml b/services/activity-service/configs/config.yaml index b72691ee..fa217608 100644 --- a/services/activity-service/configs/config.yaml +++ b/services/activity-service/configs/config.yaml @@ -65,6 +65,11 @@ rocketmq: first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 + user_outbox: + enabled: false + topic: "hyapp_user_outbox" + consumer_group: "hyapp-activity-user-region-broadcast" + consumer_max_reconsume_times: 16 consumer: room_outbox_poll_interval_ms: 1000 batch_size: 100 diff --git a/services/activity-service/internal/app/app.go b/services/activity-service/internal/app/app.go index 5e321d38..7db6a46b 100644 --- a/services/activity-service/internal/app/app.go +++ b/services/activity-service/internal/app/app.go @@ -22,6 +22,7 @@ import ( "hyapp/pkg/rocketmqx" "hyapp/pkg/roommq" "hyapp/pkg/tencentim" + "hyapp/pkg/usermq" "hyapp/pkg/walletmq" "hyapp/services/activity-service/internal/client" "hyapp/services/activity-service/internal/config" @@ -165,7 +166,7 @@ func New(cfg config.Config) (*App, error) { firstRechargeRewardSvc := firstrechargeservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) activityv1.RegisterFirstRechargeRewardServiceServer(server, grpcserver.NewFirstRechargeRewardServer(firstRechargeRewardSvc)) activityv1.RegisterAdminFirstRechargeRewardServiceServer(server, grpcserver.NewAdminFirstRechargeRewardServer(firstRechargeRewardSvc)) - mqConsumers := make([]*rocketmqx.Consumer, 0, 3) + mqConsumers := make([]*rocketmqx.Consumer, 0, 4) if cfg.RocketMQ.RoomOutbox.Enabled { consumer, err := rocketmqx.NewConsumer(roomOutboxConsumerConfig(cfg.RocketMQ)) if err != nil { @@ -195,6 +196,41 @@ func New(cfg config.Config) (*App, error) { } mqConsumers = append(mqConsumers, consumer) } + if cfg.RocketMQ.UserOutbox.Enabled && broadcastPublisher == nil { + shutdownConsumers(mqConsumers) + _ = walletConn.Close() + _ = userConn.Close() + _ = listener.Close() + _ = repository.Close() + return nil, errors.New("rocketmq user_outbox consumer requires tencent_im.enabled") + } + if cfg.RocketMQ.UserOutbox.Enabled { + consumer, err := rocketmqx.NewConsumer(userOutboxConsumerConfig(cfg.RocketMQ)) + if err != nil { + shutdownConsumers(mqConsumers) + _ = walletConn.Close() + _ = userConn.Close() + _ = listener.Close() + _ = repository.Close() + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.UserOutbox.Topic, usermq.TagUserOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + outboxMessage, err := usermq.DecodeUserOutboxMessage(message.Body) + if err != nil { + return err + } + return consumeUserRegionChangedForBroadcast(ctx, broadcastSvc, outboxMessage) + }); err != nil { + _ = consumer.Shutdown() + shutdownConsumers(mqConsumers) + _ = walletConn.Close() + _ = userConn.Close() + _ = listener.Close() + _ = repository.Close() + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } if cfg.FirstRechargeRewardWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.FirstRechargeConsumerGroup)) if err != nil { @@ -385,6 +421,10 @@ func roomOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfi return rocketMQConsumerConfig(cfg, cfg.RoomOutbox.ConsumerGroup, cfg.RoomOutbox.ConsumerMaxReconsumeTimes) } +func userOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { + return rocketMQConsumerConfig(cfg, cfg.UserOutbox.ConsumerGroup, cfg.UserOutbox.ConsumerMaxReconsumeTimes) +} + func walletOutboxConsumerConfig(cfg config.RocketMQConfig, group string) rocketmqx.ConsumerConfig { return rocketMQConsumerConfig(cfg, group, cfg.WalletOutbox.ConsumerMaxReconsumeTimes) } @@ -422,6 +462,28 @@ func shutdownConsumers(consumers []*rocketmqx.Consumer) { } } +type userRegionChangedPayload struct { + UserID int64 `json:"user_id"` + OldRegionID int64 `json:"old_region_id"` + NewRegionID int64 `json:"new_region_id"` +} + +func consumeUserRegionChangedForBroadcast(ctx context.Context, service *broadcastservice.Service, message usermq.UserOutboxMessage) error { + if message.EventType != "UserRegionChanged" { + return nil + } + var payload userRegionChangedPayload + if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil { + return err + } + if payload.UserID <= 0 || payload.OldRegionID <= 0 || payload.OldRegionID == payload.NewRegionID { + return nil + } + // 区域广播群成员关系是当前读模型;用户切区后只移除旧群,下一次 UserSig 会按新 users.region_id 返回新群。 + _, _, err := service.RemoveRegionBroadcastMember(appcode.WithContext(ctx, message.AppCode), payload.UserID, payload.OldRegionID) + return err +} + func firstRechargeEventFromWalletMessage(body []byte) (firstrechargedomain.RechargeEvent, bool, error) { message, err := walletmq.DecodeWalletOutboxMessage(body) if err != nil { diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index 737e9d88..8d537842 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -133,6 +133,7 @@ type RocketMQConfig struct { VIPChannel bool `yaml:"vip_channel"` RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"` WalletOutbox WalletOutboxMQConfig `yaml:"wallet_outbox"` + UserOutbox UserOutboxMQConfig `yaml:"user_outbox"` } // RoomOutboxMQConfig 控制 activity 对 room_outbox topic 的消费位点。 @@ -153,6 +154,14 @@ type WalletOutboxMQConfig struct { ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` } +// UserOutboxMQConfig 控制 activity 对 user_outbox topic 的独立消费组。 +type UserOutboxMQConfig struct { + Enabled bool `yaml:"enabled"` + Topic string `yaml:"topic"` + ConsumerGroup string `yaml:"consumer_group"` + ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` +} + // Default 返回本地默认配置。 func Default() Config { return Config{ @@ -232,6 +241,12 @@ func defaultRocketMQConfig() RocketMQConfig { RedPacketBroadcastConsumerGroup: "hyapp-activity-red-packet-wallet-outbox", ConsumerMaxReconsumeTimes: 16, }, + UserOutbox: UserOutboxMQConfig{ + Enabled: false, + Topic: "hyapp_user_outbox", + ConsumerGroup: "hyapp-activity-user-region-broadcast", + ConsumerMaxReconsumeTimes: 16, + }, } } @@ -367,7 +382,16 @@ func normalizeRocketMQConfig(cfg RocketMQConfig) (RocketMQConfig, error) { if cfg.WalletOutbox.ConsumerMaxReconsumeTimes <= 0 { cfg.WalletOutbox.ConsumerMaxReconsumeTimes = defaults.WalletOutbox.ConsumerMaxReconsumeTimes } - if cfg.RoomOutbox.Enabled || cfg.WalletOutbox.Enabled { + if cfg.UserOutbox.Topic = strings.TrimSpace(cfg.UserOutbox.Topic); cfg.UserOutbox.Topic == "" { + cfg.UserOutbox.Topic = defaults.UserOutbox.Topic + } + if cfg.UserOutbox.ConsumerGroup = strings.TrimSpace(cfg.UserOutbox.ConsumerGroup); cfg.UserOutbox.ConsumerGroup == "" { + cfg.UserOutbox.ConsumerGroup = defaults.UserOutbox.ConsumerGroup + } + if cfg.UserOutbox.ConsumerMaxReconsumeTimes <= 0 { + cfg.UserOutbox.ConsumerMaxReconsumeTimes = defaults.UserOutbox.ConsumerMaxReconsumeTimes + } + if cfg.RoomOutbox.Enabled || cfg.WalletOutbox.Enabled || cfg.UserOutbox.Enabled { cfg.Enabled = true } if cfg.Enabled { diff --git a/services/activity-service/internal/config/config_test.go b/services/activity-service/internal/config/config_test.go index 2ff151f0..ab30e4ce 100644 --- a/services/activity-service/internal/config/config_test.go +++ b/services/activity-service/internal/config/config_test.go @@ -7,7 +7,7 @@ func TestLoadLocalKeepsRocketMQDisabled(t *testing.T) { if err != nil { t.Fatalf("Load local config failed: %v", err) } - if cfg.RocketMQ.Enabled || cfg.RocketMQ.RoomOutbox.Enabled { + if cfg.RocketMQ.Enabled || cfg.RocketMQ.RoomOutbox.Enabled || cfg.RocketMQ.UserOutbox.Enabled { t.Fatalf("local config must not require RocketMQ: %+v", cfg.RocketMQ) } } @@ -20,6 +20,9 @@ func TestLoadTencentExampleEnablesRoomOutboxMQ(t *testing.T) { if !cfg.RocketMQ.Enabled || !cfg.RocketMQ.RoomOutbox.Enabled || cfg.RocketMQ.RoomOutbox.Topic == "" || cfg.RocketMQ.RoomOutbox.ConsumerGroup == "" { t.Fatalf("tencent example must configure room outbox MQ consumer: %+v", cfg.RocketMQ) } + if !cfg.RocketMQ.UserOutbox.Enabled || cfg.RocketMQ.UserOutbox.Topic != "hyapp_user_outbox" || cfg.RocketMQ.UserOutbox.ConsumerGroup == "" { + t.Fatalf("tencent example must configure user outbox MQ consumer: %+v", cfg.RocketMQ.UserOutbox) + } if cfg.RocketMQ.WalletOutbox.RealtimeTopic != "hyapp_wallet_realtime_outbox" { t.Fatalf("red packet worker should consume realtime wallet topic in tencent example: %+v", cfg.RocketMQ.WalletOutbox) } diff --git a/services/game-service/configs/config.tencent.example.yaml b/services/game-service/configs/config.tencent.example.yaml index e66fc900..3e00bcb8 100644 --- a/services/game-service/configs/config.tencent.example.yaml +++ b/services/game-service/configs/config.tencent.example.yaml @@ -6,7 +6,7 @@ health_http_addr: ":13108" mysql_dsn: "${GAME_MYSQL_DSN}" wallet_service_addr: "wallet-service:13004" user_service_addr: "user-service:13005" -activity_service_addr: "activity-service:13006" +activity_service_addr: "10.2.1.16:13006" launch_session_ttl: "15m" rocketmq: enabled: true diff --git a/services/game-service/internal/config/config_test.go b/services/game-service/internal/config/config_test.go new file mode 100644 index 00000000..acddd405 --- /dev/null +++ b/services/game-service/internal/config/config_test.go @@ -0,0 +1,27 @@ +package config + +import "testing" + +func TestLoadConfigsKeepActivityServiceAddr(t *testing.T) { + tests := []struct { + name string + path string + want string + }{ + {name: "local", path: "../../configs/config.yaml", want: "127.0.0.1:13006"}, + {name: "docker", path: "../../configs/config.docker.yaml", want: "activity-service:13006"}, + {name: "tencent", path: "../../configs/config.tencent.example.yaml", want: "10.2.1.16:13006"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cfg, err := Load(tt.path) + if err != nil { + t.Fatalf("Load %s config failed: %v", tt.name, err) + } + if cfg.ActivityServiceAddr != tt.want { + t.Fatalf("activity service addr mismatch: got %q want %q", cfg.ActivityServiceAddr, tt.want) + } + }) + } +} diff --git a/services/gateway-service/internal/transport/http/response_test.go b/services/gateway-service/internal/transport/http/response_test.go index 20ed2895..da03ed8d 100644 --- a/services/gateway-service/internal/transport/http/response_test.go +++ b/services/gateway-service/internal/transport/http/response_test.go @@ -3358,6 +3358,9 @@ func TestSearchHostAgenciesUsesAuthenticatedUserAndShortID(t *testing.T) { if first["agency_id"] != "7001" || first["owner_user_id"] != "901" || first["name"] != "Admin Seed Agency" || first["avatar"] != "https://cdn.example/agency.png" || first["host_count"] != float64(3) || data["page_size"] != float64(100) { t.Fatalf("host agency search response mismatch: %+v", response) } + if _, exists := first["max_hosts"]; exists { + t.Fatalf("host agency search response must not expose max_hosts: %+v", first) + } } func TestSearchHostAgenciesAllowsEmptyKeywordForCountryList(t *testing.T) { diff --git a/services/gateway-service/internal/transport/http/userapi/host_agency_handler.go b/services/gateway-service/internal/transport/http/userapi/host_agency_handler.go index 00a2f6a4..651fe947 100644 --- a/services/gateway-service/internal/transport/http/userapi/host_agency_handler.go +++ b/services/gateway-service/internal/transport/http/userapi/host_agency_handler.go @@ -21,7 +21,6 @@ type hostAgencyData struct { HostCount int32 `json:"host_count"` Status string `json:"status"` JoinEnabled bool `json:"join_enabled"` - MaxHosts int32 `json:"max_hosts"` CreatedByUserID string `json:"created_by_user_id,omitempty"` CreatedAtMS int64 `json:"created_at_ms"` UpdatedAtMS int64 `json:"updated_at_ms"` @@ -125,7 +124,6 @@ func hostAgencyFromProto(agency *userv1.Agency) hostAgencyData { HostCount: agency.GetHostCount(), Status: agency.GetStatus(), JoinEnabled: agency.GetJoinEnabled(), - MaxHosts: agency.GetMaxHosts(), CreatedByUserID: int64String(agency.GetCreatedByUserId()), CreatedAtMS: agency.GetCreatedAtMs(), UpdatedAtMS: agency.GetUpdatedAtMs(), diff --git a/services/room-service/configs/config.docker.yaml b/services/room-service/configs/config.docker.yaml index b7651a41..31832ec2 100644 --- a/services/room-service/configs/config.docker.yaml +++ b/services/room-service/configs/config.docker.yaml @@ -73,6 +73,11 @@ rocketmq: producer_group: "hyapp-room-rocket-launch-producer" consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 + user_outbox: + enabled: true + topic: "hyapp_user_outbox" + consumer_group: "hyapp-room-user-region-sync" + consumer_max_reconsume_times: 16 outbox_worker: # Docker 和 testbox 走 MQ;room-service 同进程启动 IM bridge consumer 补偿房间群消息。 enabled: true diff --git a/services/room-service/configs/config.tencent.example.yaml b/services/room-service/configs/config.tencent.example.yaml index 55b3cb9e..bb54d4b2 100644 --- a/services/room-service/configs/config.tencent.example.yaml +++ b/services/room-service/configs/config.tencent.example.yaml @@ -83,6 +83,11 @@ rocketmq: producer_group: "hyapp-room-rocket-launch-producer" consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 + user_outbox: + enabled: true + topic: "hyapp_user_outbox" + consumer_group: "hyapp-room-user-region-sync" + consumer_max_reconsume_times: 16 outbox_worker: # mq 模式下 outbox worker 只把事实投 MQ,并顺带安排火箭延迟发射唤醒。 enabled: true diff --git a/services/room-service/configs/config.yaml b/services/room-service/configs/config.yaml index a6b42dff..a1e2984b 100644 --- a/services/room-service/configs/config.yaml +++ b/services/room-service/configs/config.yaml @@ -76,6 +76,11 @@ rocketmq: producer_group: "hyapp-room-rocket-launch-producer" consumer_group: "hyapp-room-rocket-launch" consumer_max_reconsume_times: 16 + user_outbox: + enabled: false + topic: "hyapp_user_outbox" + consumer_group: "hyapp-room-user-region-sync" + consumer_max_reconsume_times: 16 outbox_worker: # room_outbox 是腾讯云 IM 和 activity-service 的异步投递通道;失败退避重试,超过上限转死信。 enabled: true diff --git a/services/room-service/deploy/mysql/initdb/001_room_service.sql b/services/room-service/deploy/mysql/initdb/001_room_service.sql index 39e13e12..ff142cc9 100644 --- a/services/room-service/deploy/mysql/initdb/001_room_service.sql +++ b/services/room-service/deploy/mysql/initdb/001_room_service.sql @@ -177,6 +177,7 @@ CREATE TABLE IF NOT EXISTS room_region_pins ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', visible_region_id BIGINT NOT NULL COMMENT '可见区域 ID', + pin_type VARCHAR(32) NOT NULL DEFAULT 'region' COMMENT '置顶类型:region 区域置顶,global 全区置顶', room_id VARCHAR(64) NOT NULL COMMENT '房间 ID', weight BIGINT NOT NULL DEFAULT 0 COMMENT '权重', status VARCHAR(32) NOT NULL COMMENT '业务状态', @@ -188,10 +189,10 @@ CREATE TABLE IF NOT EXISTS room_region_pins ( created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (id), - UNIQUE KEY uk_room_region_pins_room (app_code, visible_region_id, room_id), - KEY idx_room_region_pins_active (app_code, visible_region_id, status, expires_at_ms, weight DESC, room_id), + UNIQUE KEY uk_room_region_pins_scope (app_code, pin_type, visible_region_id, room_id), + KEY idx_room_region_pins_active_scope (app_code, pin_type, visible_region_id, status, pinned_at_ms, expires_at_ms, weight DESC, room_id), KEY idx_room_region_pins_room (app_code, room_id, status) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间区域置顶表'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间置顶表'; CREATE TABLE IF NOT EXISTS room_seat_configs ( app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离', diff --git a/services/room-service/internal/app/app.go b/services/room-service/internal/app/app.go index 0c38884b..dfb57423 100644 --- a/services/room-service/internal/app/app.go +++ b/services/room-service/internal/app/app.go @@ -23,6 +23,7 @@ import ( "hyapp/pkg/roommq" "hyapp/pkg/tencentim" "hyapp/pkg/tencentrtc" + "hyapp/pkg/usermq" "hyapp/services/room-service/internal/config" "hyapp/services/room-service/internal/healthcheck" "hyapp/services/room-service/internal/integration" @@ -153,7 +154,7 @@ func New(cfg config.Config) (*App, error) { } mqProducers := make([]*rocketmqx.Producer, 0, 2) - mqConsumers := make([]*rocketmqx.Consumer, 0, 2) + mqConsumers := make([]*rocketmqx.Consumer, 0, 3) var rocketLaunchScheduler integration.RoomRocketLaunchScheduler if cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDirect || cfg.OutboxWorker.PublishMode == config.OutboxPublishModeDual { if activityConn != nil { @@ -263,6 +264,30 @@ func New(cfg config.Config) (*App, error) { } mqConsumers = append(mqConsumers, imConsumer) } + if cfg.RocketMQ.UserOutbox.Enabled { + userConsumer, err := rocketmqx.NewConsumer(rocketMQConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.UserOutbox.ConsumerGroup, cfg.RocketMQ.UserOutbox.ConsumerMaxReconsumeTimes)) + if err != nil { + _ = repository.Close() + closeClientConn(activityConn) + _ = walletConn.Close() + _ = redisClient.Close() + return nil, err + } + if err := userConsumer.Subscribe(cfg.RocketMQ.UserOutbox.Topic, usermq.TagUserOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + outboxMessage, err := usermq.DecodeUserOutboxMessage(message.Body) + if err != nil { + return err + } + return svc.HandleUserOutboxMessage(ctx, outboxMessage) + }); err != nil { + _ = repository.Close() + closeClientConn(activityConn) + _ = walletConn.Close() + _ = redisClient.Close() + return nil, err + } + mqConsumers = append(mqConsumers, userConsumer) + } server := grpc.NewServer(grpc.UnaryInterceptor(logx.UnaryServerInterceptor("room-service"))) roomServer := grpcserver.NewServer(svc, grpcserver.WithOwnerForwarding(cfg.NodeID, directory, directory, cfg.OwnerForwardTimeout)) diff --git a/services/room-service/internal/config/config.go b/services/room-service/internal/config/config.go index b495b8b3..2ecce2ad 100644 --- a/services/room-service/internal/config/config.go +++ b/services/room-service/internal/config/config.go @@ -124,6 +124,7 @@ type RocketMQConfig struct { Retry int `yaml:"retry"` RoomOutbox RoomOutboxMQConfig `yaml:"room_outbox"` RocketLaunch RocketLaunchMQConfig `yaml:"rocket_launch"` + UserOutbox UserOutboxMQConfig `yaml:"user_outbox"` } // RoomOutboxMQConfig 控制 room_outbox fanout topic。 @@ -145,6 +146,14 @@ type RocketLaunchMQConfig struct { ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` } +// UserOutboxMQConfig 控制用户区域变更事实消费。 +type UserOutboxMQConfig struct { + Enabled bool `yaml:"enabled"` + Topic string `yaml:"topic"` + ConsumerGroup string `yaml:"consumer_group"` + ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` +} + // TencentIMConfig 描述 room-service 调用腾讯云 IM REST API 的配置。 type TencentIMConfig struct { // Enabled 控制是否启用腾讯云 IM REST 桥接;关闭时只保留 Room Cell 内部提交。 @@ -306,6 +315,12 @@ func defaultRocketMQConfig() RocketMQConfig { ConsumerGroup: "hyapp-room-rocket-launch", ConsumerMaxReconsumeTimes: 16, }, + UserOutbox: UserOutboxMQConfig{ + Enabled: false, + Topic: "hyapp_user_outbox", + ConsumerGroup: "hyapp-room-user-region-sync", + ConsumerMaxReconsumeTimes: 16, + }, } } @@ -485,7 +500,16 @@ func normalizeRocketMQConfig(cfg RocketMQConfig, publishMode string) (RocketMQCo if cfg.RocketLaunch.ConsumerMaxReconsumeTimes <= 0 { cfg.RocketLaunch.ConsumerMaxReconsumeTimes = defaults.RocketLaunch.ConsumerMaxReconsumeTimes } - if cfg.RoomOutbox.Enabled || cfg.RocketLaunch.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled { + if cfg.UserOutbox.Topic = strings.TrimSpace(cfg.UserOutbox.Topic); cfg.UserOutbox.Topic == "" { + cfg.UserOutbox.Topic = defaults.UserOutbox.Topic + } + if cfg.UserOutbox.ConsumerGroup = strings.TrimSpace(cfg.UserOutbox.ConsumerGroup); cfg.UserOutbox.ConsumerGroup == "" { + cfg.UserOutbox.ConsumerGroup = defaults.UserOutbox.ConsumerGroup + } + if cfg.UserOutbox.ConsumerMaxReconsumeTimes <= 0 { + cfg.UserOutbox.ConsumerMaxReconsumeTimes = defaults.UserOutbox.ConsumerMaxReconsumeTimes + } + if cfg.RoomOutbox.Enabled || cfg.RocketLaunch.Enabled || cfg.UserOutbox.Enabled || cfg.RoomOutbox.TencentIMConsumerEnabled { cfg.Enabled = true } if publishMode == OutboxPublishModeMQ || publishMode == OutboxPublishModeDual { diff --git a/services/room-service/internal/integration/tencent_im.go b/services/room-service/internal/integration/tencent_im.go index 746b0c6e..51b6a36f 100644 --- a/services/room-service/internal/integration/tencent_im.go +++ b/services/room-service/internal/integration/tencent_im.go @@ -268,6 +268,7 @@ func roomEventFromEnvelope(envelope *roomeventsv1.EventEnvelope) (tencentim.Room base.Attributes = map[string]string{ "gift_id": body.GetGiftId(), "gift_count": fmt.Sprintf("%d", body.GetGiftCount()), + "coin_spent": fmt.Sprintf("%d", body.GetCoinSpent()), "billing_receipt_id": body.GetBillingReceiptId(), } return base, true, nil diff --git a/services/room-service/internal/room/service/admin.go b/services/room-service/internal/room/service/admin.go index 598aac90..e68e1f03 100644 --- a/services/room-service/internal/room/service/admin.go +++ b/services/room-service/internal/room/service/admin.go @@ -26,6 +26,7 @@ func (s *Service) AdminListRooms(ctx context.Context, req *roomv1.AdminListRooms Keyword: strings.TrimSpace(req.GetKeyword()), Status: strings.TrimSpace(req.GetStatus()), RegionID: req.GetVisibleRegionId(), + OwnerUserID: req.GetOwnerUserId(), SortBy: strings.TrimSpace(req.GetSortBy()), SortDirection: strings.TrimSpace(req.GetSortDirection()), }) diff --git a/services/room-service/internal/room/service/admin_config_pin.go b/services/room-service/internal/room/service/admin_config_pin.go index 50bd49e4..44a40151 100644 --- a/services/room-service/internal/room/service/admin_config_pin.go +++ b/services/room-service/internal/room/service/admin_config_pin.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "strings" roomv1 "hyapp.local/api/proto/room/v1" @@ -11,6 +12,12 @@ import ( var adminSeatCandidates = []int32{10, 15, 20, 25, 30} +const ( + roomPinTypeRegion = "region" + roomPinTypeGlobal = "global" + roomPinDayMillis = int64(24 * 60 * 60 * 1000) +) + func (s *Service) AdminGetRoomSeatConfig(ctx context.Context, _ *roomv1.AdminGetRoomSeatConfigRequest) (*roomv1.AdminGetRoomSeatConfigResponse, error) { config, err := s.currentRoomSeatConfig(ctx) if err != nil { @@ -46,6 +53,7 @@ func (s *Service) AdminListRoomPins(ctx context.Context, req *roomv1.AdminListRo Keyword: strings.TrimSpace(req.GetKeyword()), Status: strings.TrimSpace(req.GetStatus()), RegionID: req.GetVisibleRegionId(), + PinType: normalizeRoomPinType(req.GetPinType()), NowMS: nowMS, }) if err != nil { @@ -53,6 +61,10 @@ func (s *Service) AdminListRoomPins(ctx context.Context, req *roomv1.AdminListRo } out := make([]*roomv1.AdminRoomPin, 0, len(pins)) for _, pin := range pins { + if pin.Status == "active" && pin.ExpiresAtMS <= nowMS { + // 过期不需要回写房间状态;对后台读模型呈现 expired,公共列表查询也会自动把它排除出置顶 join。 + pin.Status = "expired" + } out = append(out, roomPinToAdminProto(pin)) } return &roomv1.AdminListRoomPinsResponse{Pins: out, Total: total, ServerTimeMs: nowMS}, nil @@ -62,14 +74,21 @@ func (s *Service) AdminCreateRoomPin(ctx context.Context, req *roomv1.AdminCreat if req == nil || strings.TrimSpace(req.GetRoomId()) == "" { return nil, xerr.New(xerr.InvalidArgument, "room id is required") } - if req.GetWeight() < 0 || req.GetDurationDays() <= 0 { - return nil, xerr.New(xerr.InvalidArgument, "room pin weight or duration is invalid") + if req.GetWeight() < 0 { + return nil, xerr.New(xerr.InvalidArgument, "room pin weight is invalid") } nowMS := s.clock.Now().UTC().UnixMilli() + pinnedAtMS, expiresAtMS, err := normalizeAdminRoomPinInterval(req.GetPinnedAtMs(), req.GetExpiresAtMs(), req.GetDurationDays(), nowMS) + if err != nil { + return nil, xerr.New(xerr.InvalidArgument, err.Error()) + } pin, ok, err := s.repository.AdminCreateRoomPin(ctx, AdminCreateRoomPinInput{ RoomID: strings.TrimSpace(req.GetRoomId()), + PinType: normalizeRoomPinType(req.GetPinType()), Weight: req.GetWeight(), DurationDays: req.GetDurationDays(), + PinnedAtMS: pinnedAtMS, + ExpiresAtMS: expiresAtMS, AdminID: req.GetAdminId(), NowMS: nowMS, }) @@ -113,6 +132,7 @@ func roomPinToAdminProto(pin AdminRoomPinEntry) *roomv1.AdminRoomPin { RoomId: pin.RoomID, Weight: pin.Weight, Status: pin.Status, + PinType: pin.PinType, PinnedAtMs: pin.PinnedAtMS, ExpiresAtMs: pin.ExpiresAtMS, CancelledAtMs: pin.CancelledAtMS, @@ -123,7 +143,7 @@ func roomPinToAdminProto(pin AdminRoomPinEntry) *roomv1.AdminRoomPin { Room: &roomv1.AdminRoomPinRoom{ RoomId: pin.RoomID, RoomShortId: pin.RoomShortID, - VisibleRegionId: pin.VisibleRegionID, + VisibleRegionId: pin.RoomVisibleRegionID, OwnerUserId: pin.OwnerUserID, Title: pin.Title, CoverUrl: pin.CoverURL, @@ -131,3 +151,29 @@ func roomPinToAdminProto(pin AdminRoomPinEntry) *roomv1.AdminRoomPin { }, } } + +func normalizeRoomPinType(pinType string) string { + switch strings.ToLower(strings.TrimSpace(pinType)) { + case roomPinTypeGlobal: + return roomPinTypeGlobal + default: + // 空值和未知值都回落到区域置顶,兼容旧后台只传 room_id/duration_days 的请求。 + return roomPinTypeRegion + } +} + +func normalizeAdminRoomPinInterval(pinnedAtMS int64, expiresAtMS int64, durationDays int64, nowMS int64) (int64, int64, error) { + if pinnedAtMS <= 0 { + pinnedAtMS = nowMS + } + if expiresAtMS <= 0 && durationDays > 0 { + expiresAtMS = pinnedAtMS + durationDays*roomPinDayMillis + } + if expiresAtMS <= pinnedAtMS { + return 0, 0, errors.New("room pin time range is invalid") + } + if expiresAtMS-pinnedAtMS > 3650*roomPinDayMillis { + return 0, 0, errors.New("room pin time range is too long") + } + return pinnedAtMS, expiresAtMS, nil +} diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index 5a2e9eb8..7cdb77aa 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -172,6 +172,7 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r PoolId: cmd.PoolID, GiftCount: cmd.GiftCount, GiftValue: targetBilling.Billing.GetHeatValue(), + CoinSpent: targetBilling.Billing.GetCoinSpent(), BillingReceiptId: targetBilling.Billing.GetBillingReceiptId(), VisibleRegionId: roomMeta.VisibleRegionID, CommandId: targetBilling.CommandID, diff --git a/services/room-service/internal/room/service/list.go b/services/room-service/internal/room/service/list.go index d1c76c99..2baf6f4f 100644 --- a/services/room-service/internal/room/service/list.go +++ b/services/room-service/internal/room/service/list.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/json" "log/slog" + "math" "strings" roomv1 "hyapp.local/api/proto/room/v1" @@ -23,6 +24,11 @@ const ( defaultRoomListLimit = 20 maxRoomListLimit = 50 maxRoomListQueryRunes = 64 + roomHotHeatWeight = 650000 + roomHotOnlineWeight = 300000 + roomHotMicWeight = 50000 + roomHotOnlineCap = 50 + roomHotMicCap = 10 ) // roomListCursor 是服务端生成的不透明翻页游标。 @@ -34,13 +40,14 @@ type roomListCursor struct { CreatedAtMS int64 `json:"created_at_ms,omitempty"` UpdatedAtMS int64 `json:"updated_at_ms,omitempty"` SubjectUserID int64 `json:"subject_user_id,omitempty"` + PinListRank int64 `json:"pin_list_rank,omitempty"` Pinned bool `json:"pinned,omitempty"` PinWeight int64 `json:"pin_weight,omitempty"` PinnedUntilMS int64 `json:"pinned_until_ms,omitempty"` RoomID string `json:"room_id"` } -// ListRooms 查询当前用户区域内的公共房间发现列表读模型。 +// ListRooms 查询公共房间发现列表读模型,并用服务端解析出的用户区域决定置顶和普通房排序桶。 func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) (*roomv1.ListRoomsResponse, error) { ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) viewerUserID := req.GetViewerUserId() @@ -73,6 +80,7 @@ func (s *Service) ListRooms(ctx context.Context, req *roomv1.ListRoomsRequest) ( CursorSortScore: cursor.SortScore, CursorCreatedAtMS: cursor.CreatedAtMS, CursorRoomID: cursor.RoomID, + CursorPinListRank: cursor.PinListRank, CursorPinned: cursor.Pinned, CursorPinWeight: cursor.PinWeight, CursorPinnedUntilMS: cursor.PinnedUntilMS, @@ -289,8 +297,29 @@ func roomListEntryFromSnapshot(snapshot *roomv1.RoomSnapshot, visibleRegionID in } func roomListSortScore(heat int64, onlineCount int32, occupiedSeatCount int32) int64 { - // 排序分只属于列表读模型,不进入 RoomState,后续调整公式不需要回放 command log。 - return heat*1000 + int64(onlineCount)*100 + int64(occupiedSeatCount)*10 + // 热门分只属于列表读模型,不进入 RoomState;贡献值先做 log 压缩,避免历史大房间永久碾压当前有人房间。 + if heat < 0 { + heat = 0 + } + online := int64(onlineCount) + if online < 0 { + online = 0 + } + if online > roomHotOnlineCap { + online = roomHotOnlineCap + } + occupied := int64(occupiedSeatCount) + if occupied < 0 { + occupied = 0 + } + if occupied > roomHotMicCap { + occupied = roomHotMicCap + } + + heatScore := math.Log2(float64(heat) + 1) + onlineScore := math.Log2(float64(online) + 1) + micScore := float64(occupied) + return int64(heatScore*roomHotHeatWeight + onlineScore*roomHotOnlineWeight + micScore*roomHotMicWeight) } // normalizeRoomListTab 只支持公共发现列表 tab,Mine 关系流走 ListRoomFeeds。 @@ -391,6 +420,7 @@ func encodeRoomListCursor(tab string, query string, entry RoomListEntry) string CreatedAtMS: entry.CreatedAtMS, UpdatedAtMS: entry.UpdatedAtMS, SubjectUserID: entry.FeedSubjectUserID, + PinListRank: entry.PinListRank, Pinned: entry.IsPinned, PinWeight: entry.PinWeight, PinnedUntilMS: entry.PinnedUntilMS, diff --git a/services/room-service/internal/room/service/list_score_test.go b/services/room-service/internal/room/service/list_score_test.go new file mode 100644 index 00000000..b10b0614 --- /dev/null +++ b/services/room-service/internal/room/service/list_score_test.go @@ -0,0 +1,18 @@ +package service + +import "testing" + +func TestRoomListSortScoreUsesCompressedWeightedInputs(t *testing.T) { + score := roomListSortScore(7, 3, 2) + if score != 2650000 { + t.Fatalf("hot score should use 65/30/5 weighted compressed inputs, got %d", score) + } +} + +func TestRoomListSortScoreCapsPresenceInputs(t *testing.T) { + capped := roomListSortScore(0, 50, 10) + overCap := roomListSortScore(0, 999, 999) + if capped != overCap { + t.Fatalf("hot score should cap online and occupied seats, capped=%d over_cap=%d", capped, overCap) + } +} diff --git a/services/room-service/internal/room/service/pin_test.go b/services/room-service/internal/room/service/pin_test.go index 73589e81..9c09670c 100644 --- a/services/room-service/internal/room/service/pin_test.go +++ b/services/room-service/internal/room/service/pin_test.go @@ -64,6 +64,90 @@ func TestRegionalPinOrdersPublicRoomList(t *testing.T) { } } +func TestPinnedRoomListOrdersGlobalRegionLocalThenOtherForHot(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-pin-hot-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + createPinnedListRoom(t, ctx, svc, "room-global-pin", "global-pin", 3101, 9002) + createPinnedListRoom(t, ctx, svc, "room-region-pin", "region-pin", 3102, 9001) + createPinnedListRoom(t, ctx, svc, "room-local-online", "local-online", 3103, 9001) + createPinnedListRoom(t, ctx, svc, "room-other-online", "other-online", 3104, 9002) + createPinnedListRoom(t, ctx, svc, "room-local-empty", "local-empty", 3105, 9001) + createPinnedListRoom(t, ctx, svc, "room-other-empty", "other-empty", 3106, 9002) + repository.SetRoomSortScore("room-global-pin", 1) + repository.SetRoomSortScore("room-region-pin", 2) + repository.SetRoomSortScore("room-local-online", 100) + repository.SetRoomSortScore("room-other-online", 10000) + repository.SetRoomSortScore("room-local-empty", 100000) + repository.SetRoomSortScore("room-other-empty", 200000) + repository.SetRoomPresence("room-local-online", 1, 0) + repository.SetRoomPresence("room-other-online", 1, 0) + repository.SetRoomPresence("room-local-empty", 0, 0) + repository.SetRoomPresence("room-other-empty", 0, 0) + expiresAtMS := time.Now().UTC().Add(24 * time.Hour).UnixMilli() + repository.PinRoomWithType("room-global-pin", "global", 0, 1, expiresAtMS) + repository.PinRoom("room-region-pin", 9001, 99, expiresAtMS) + + page, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + Tab: "hot", + Limit: 6, + }) + if err != nil { + t.Fatalf("list hot rooms failed: %v", err) + } + if got := roomIDs(page.GetRooms()); len(got) != 6 || got[0] != "room-global-pin" || got[1] != "room-region-pin" || got[2] != "room-local-online" || got[3] != "room-other-online" || got[4] != "room-local-empty" || got[5] != "room-other-empty" { + t.Fatalf("hot order mismatch: %+v", got) + } +} + +func TestPinnedRoomListOrdersGlobalRegionLocalThenOtherForNew(t *testing.T) { + ctx := context.Background() + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-pin-new-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + createPinnedListRoom(t, ctx, svc, "room-global-new", "global-new", 3201, 9002) + createPinnedListRoom(t, ctx, svc, "room-region-new", "region-new", 3202, 9001) + createPinnedListRoom(t, ctx, svc, "room-local-newer", "local-newer", 3203, 9001) + createPinnedListRoom(t, ctx, svc, "room-local-older", "local-older", 3204, 9001) + createPinnedListRoom(t, ctx, svc, "room-other-newest", "other-newest", 3205, 9002) + repository.SetRoomCreatedAt("room-global-new", 10) + repository.SetRoomCreatedAt("room-region-new", 20) + repository.SetRoomCreatedAt("room-local-newer", 300) + repository.SetRoomCreatedAt("room-local-older", 100) + repository.SetRoomCreatedAt("room-other-newest", 1000) + expiresAtMS := time.Now().UTC().Add(24 * time.Hour).UnixMilli() + repository.PinRoomWithType("room-global-new", "global", 0, 1, expiresAtMS) + repository.PinRoom("room-region-new", 9001, 99, expiresAtMS) + + page, err := svc.ListRooms(ctx, &roomv1.ListRoomsRequest{ + Meta: &roomv1.RequestMeta{AppCode: appcode.Default}, + ViewerUserId: 4001, + VisibleRegionId: 9001, + Tab: "new", + Limit: 5, + }) + if err != nil { + t.Fatalf("list new rooms failed: %v", err) + } + if got := roomIDs(page.GetRooms()); len(got) != 5 || got[0] != "room-global-new" || got[1] != "room-region-new" || got[2] != "room-local-newer" || got[3] != "room-local-older" || got[4] != "room-other-newest" { + t.Fatalf("new order mismatch: %+v", got) + } +} + func createPinnedListRoom(t *testing.T, ctx context.Context, svc *roomservice.Service, roomID string, shortID string, ownerID int64, regionID int64) { t.Helper() diff --git a/services/room-service/internal/room/service/repository.go b/services/room-service/internal/room/service/repository.go index 16cbde3b..7827e835 100644 --- a/services/room-service/internal/room/service/repository.go +++ b/services/room-service/internal/room/service/repository.go @@ -126,7 +126,7 @@ type RoomListEntry struct { RoomID string // RoomShortID 是列表卡片展示/搜索用短房号。 RoomShortID string - // VisibleRegionID 是列表隔离桶,查询只能按该字段过滤。 + // VisibleRegionID 是房间自身的列表区域;公共发现列表会用它把当前区域房间排在其他区域之前。 VisibleRegionID int64 // OwnerUserID 是房间所有者,用于卡片展示和运营排查。 OwnerUserID int64 @@ -156,11 +156,13 @@ type RoomListEntry struct { UpdatedAtMS int64 // FeedSubjectUserID 是关系房间流命中的好友/关注用户;只用于生成稳定 cursor,不出现在 HTTP 卡片里。 FeedSubjectUserID int64 - // IsPinned 表达该卡片在当前区域列表查询中是否命中有效区域置顶。 + // IsPinned 表达该卡片在当前公共列表查询中是否命中有效置顶。 IsPinned bool - // PinWeight 是区域置顶权重;只用于公共房间列表排序和 cursor。 + // PinListRank 是公共发现列表排序桶;hot 会把有人房和空房再拆层,new 仍只区分本区和外区。 + PinListRank int64 + // PinWeight 是命中置顶的排序权重;只用于公共房间列表排序和 cursor。 PinWeight int64 - // PinnedUntilMS 是区域置顶过期时间;只用于公共房间列表排序和 cursor。 + // PinnedUntilMS 是命中置顶的过期时间;只用于公共房间列表排序和 cursor。 PinnedUntilMS int64 } @@ -193,28 +195,31 @@ type AdminRoomListQuery struct { Keyword string Status string RegionID int64 + OwnerUserID int64 SortBy string SortDirection string } type AdminRoomPinEntry struct { - ID int64 - VisibleRegionID int64 - RoomID string - Weight int64 - Status string - PinnedAtMS int64 - ExpiresAtMS int64 - CancelledAtMS int64 - CreatedByAdminID uint64 - CancelledByAdminID uint64 - CreatedAtMS int64 - UpdatedAtMS int64 - RoomShortID string - Title string - CoverURL string - OwnerUserID int64 - RoomStatus string + ID int64 + VisibleRegionID int64 + PinType string + RoomID string + Weight int64 + Status string + PinnedAtMS int64 + ExpiresAtMS int64 + CancelledAtMS int64 + CreatedByAdminID uint64 + CancelledByAdminID uint64 + CreatedAtMS int64 + UpdatedAtMS int64 + RoomShortID string + RoomVisibleRegionID int64 + Title string + CoverURL string + OwnerUserID int64 + RoomStatus string } type AdminRoomPinQuery struct { @@ -224,13 +229,17 @@ type AdminRoomPinQuery struct { Keyword string Status string RegionID int64 + PinType string NowMS int64 } type AdminCreateRoomPinInput struct { RoomID string + PinType string Weight int64 DurationDays int64 + PinnedAtMS int64 + ExpiresAtMS int64 AdminID uint64 NowMS int64 } @@ -365,7 +374,9 @@ type RoomListQuery struct { CursorUpdatedAtMS int64 // CursorRoomID 是同分或同时间下的稳定翻页边界。 CursorRoomID string - // CursorPinned 是上一页最后一条是否为置顶卡片,公共列表 cursor 用它跨置顶/普通分区翻页。 + // CursorPinListRank 是上一页最后一条所在排序桶,公共列表用它跨全区、区域和普通房分区翻页。 + CursorPinListRank int64 + // CursorPinned 是旧游标兼容字段;新排序以 CursorPinListRank 为准。 CursorPinned bool // CursorPinWeight 是上一页最后一条置顶权重。 CursorPinWeight int64 diff --git a/services/room-service/internal/room/service/user_region_sync.go b/services/room-service/internal/room/service/user_region_sync.go new file mode 100644 index 00000000..a814ee76 --- /dev/null +++ b/services/room-service/internal/room/service/user_region_sync.go @@ -0,0 +1,74 @@ +package service + +import ( + "context" + "encoding/json" + "errors" + "strings" + + roomv1 "hyapp.local/api/proto/room/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/usermq" + "hyapp/services/room-service/internal/room/state" +) + +type userRegionChangedPayload struct { + UserID int64 `json:"user_id"` + OldCountry string `json:"old_country"` + NewCountry string `json:"new_country"` + OldRegionID int64 `json:"old_region_id"` + NewRegionID int64 `json:"new_region_id"` + Source string `json:"source"` + RequestID string `json:"request_id"` + ChangedAtMS int64 `json:"changed_at_ms"` +} + +// HandleUserOutboxMessage 只消费 user-service 的当前区域迁移事实;历史注册、邀请或麦位事实不是 room-service 的状态输入。 +func (s *Service) HandleUserOutboxMessage(ctx context.Context, message usermq.UserOutboxMessage) error { + if strings.TrimSpace(message.EventType) != "UserRegionChanged" { + return nil + } + var payload userRegionChangedPayload + if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil { + return err + } + if payload.UserID <= 0 || payload.NewRegionID < 0 { + // user_outbox 已经是 owner service 提交后的事实;结构错误交给 MQ 重试和告警,不在本地猜测修复。 + return errors.New("user region changed payload is invalid") + } + if payload.UserID != message.AggregateID { + // aggregate_id 是 outbox 幂等和审计键,必须和 payload 指向同一个用户,避免错误事件迁移别人的房间。 + return errors.New("user region changed aggregate_id mismatch") + } + + ctx = appcode.WithContext(ctx, message.AppCode) + meta, exists, err := s.repository.GetRoomMetaByOwner(ctx, payload.UserID) + if err != nil { + return err + } + if !exists || meta.Status == state.RoomStatusDeleted || meta.VisibleRegionID == payload.NewRegionID { + return nil + } + + requestID := strings.TrimSpace(payload.RequestID) + if requestID == "" { + requestID = message.EventID + } + sentAtMS := payload.ChangedAtMS + if sentAtMS <= 0 { + sentAtMS = message.OccurredAtMS + } + _, err = s.AdminUpdateRoom(ctx, &roomv1.AdminUpdateRoomRequest{ + Meta: &roomv1.RequestMeta{ + AppCode: message.AppCode, + RequestId: requestID, + CommandId: message.EventID, + ActorUserId: payload.UserID, + RoomId: meta.RoomID, + SentAtMs: sentAtMS, + }, + VisibleRegionId: &payload.NewRegionID, + AdminName: "user-region-sync", + }) + return err +} diff --git a/services/room-service/internal/room/service/user_region_sync_test.go b/services/room-service/internal/room/service/user_region_sync_test.go new file mode 100644 index 00000000..65ca02a1 --- /dev/null +++ b/services/room-service/internal/room/service/user_region_sync_test.go @@ -0,0 +1,92 @@ +package service_test + +import ( + "context" + "encoding/json" + "testing" + "time" + + roomv1 "hyapp.local/api/proto/room/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/usermq" + "hyapp/services/room-service/internal/integration" + roomservice "hyapp/services/room-service/internal/room/service" + "hyapp/services/room-service/internal/router" + "hyapp/services/room-service/internal/testutil/mysqltest" +) + +func TestHandleUserRegionChangedUpdatesOwnerRoomRegionIdempotently(t *testing.T) { + ctx := appcode.WithContext(context.Background(), appcode.Default) + repository := mysqltest.NewRepository(t) + svc := roomservice.New(roomservice.Config{ + NodeID: "node-user-region-sync-test", + LeaseTTL: 10 * time.Second, + RankLimit: 20, + SnapshotEveryN: 1, + }, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher()) + + roomID := "room-user-region-sync" + ownerID := int64(163212) + if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{ + Meta: roomservice.NewRequestMeta(roomID, ownerID), + SeatCount: 10, + Mode: "voice", + VisibleRegionId: 3, + RoomName: "Region Sync Room", + RoomAvatar: testRoomCoverURL, + RoomShortId: "163212", + }); err != nil { + t.Fatalf("create room failed: %v", err) + } + + payload, err := json.Marshal(map[string]any{ + "user_id": ownerID, + "old_country": "AE", + "new_country": "BD", + "old_region_id": 3, + "new_region_id": 2, + "source": "admin", + "request_id": "req-user-region-sync", + "changed_at_ms": int64(1_700_000_789_000), + }) + if err != nil { + t.Fatalf("marshal payload failed: %v", err) + } + message := usermq.UserOutboxMessage{ + AppCode: appcode.Default, + EventID: "UserRegionChanged:admin:163212:3:2:1700000789000", + EventType: "UserRegionChanged", + AggregateType: "user", + AggregateID: ownerID, + PayloadJSON: string(payload), + OccurredAtMS: 1_700_000_789_000, + } + if err := svc.HandleUserOutboxMessage(ctx, message); err != nil { + t.Fatalf("HandleUserOutboxMessage failed: %v", err) + } + if err := svc.HandleUserOutboxMessage(ctx, message); err != nil { + t.Fatalf("replayed HandleUserOutboxMessage failed: %v", err) + } + + meta, exists, err := repository.GetRoomMeta(ctx, roomID) + if err != nil || !exists { + t.Fatalf("room meta missing after sync: exists=%t err=%v", exists, err) + } + if meta.VisibleRegionID != 2 { + t.Fatalf("rooms visible region mismatch: %+v", meta) + } + newRegionEntries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 2, Tab: "new", Limit: 10}) + if err != nil { + t.Fatalf("list new region entries failed: %v", err) + } + if len(newRegionEntries) != 1 || newRegionEntries[0].RoomID != roomID || newRegionEntries[0].VisibleRegionID != 2 { + t.Fatalf("new region list projection mismatch: %+v", newRegionEntries) + } + oldRegionEntries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 3, Tab: "new", Limit: 10}) + if err != nil { + t.Fatalf("list old region entries failed: %v", err) + } + if len(oldRegionEntries) != 0 { + t.Fatalf("old region list must not contain migrated room: %+v", oldRegionEntries) + } +} diff --git a/services/room-service/internal/storage/mysql/repository.go b/services/room-service/internal/storage/mysql/repository.go index d775196e..a3ffc3ad 100644 --- a/services/room-service/internal/storage/mysql/repository.go +++ b/services/room-service/internal/storage/mysql/repository.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "sort" + "strconv" "strings" "time" @@ -229,6 +230,7 @@ func (r *Repository) Migrate(ctx context.Context) error { id BIGINT NOT NULL AUTO_INCREMENT, app_code VARCHAR(32) NOT NULL, visible_region_id BIGINT NOT NULL, + pin_type VARCHAR(32) NOT NULL DEFAULT 'region', room_id VARCHAR(64) NOT NULL, weight BIGINT NOT NULL DEFAULT 0, status VARCHAR(32) NOT NULL, @@ -240,10 +242,10 @@ func (r *Repository) Migrate(ctx context.Context) error { created_at_ms BIGINT NOT NULL, updated_at_ms BIGINT NOT NULL, PRIMARY KEY (id), - UNIQUE KEY uk_room_region_pins_room (app_code, visible_region_id, room_id), - KEY idx_room_region_pins_active (app_code, visible_region_id, status, expires_at_ms, weight DESC, room_id), + UNIQUE KEY uk_room_region_pins_scope (app_code, pin_type, visible_region_id, room_id), + KEY idx_room_region_pins_active_scope (app_code, pin_type, visible_region_id, status, pinned_at_ms, expires_at_ms, weight DESC, room_id), KEY idx_room_region_pins_room (app_code, room_id, status) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间置顶表'`, `CREATE TABLE IF NOT EXISTS room_seat_configs ( app_code VARCHAR(32) NOT NULL, allowed_seat_counts VARCHAR(128) NOT NULL, @@ -341,10 +343,55 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureRoomUserPresenceSchema(ctx); err != nil { return err } + if err := r.ensureRoomPinSchema(ctx); err != nil { + return err + } return r.ensureOutboxRetrySchema(ctx) } +func (r *Repository) ensureRoomPinSchema(ctx context.Context) error { + hasColumn, err := r.columnExists(ctx, "room_region_pins", "pin_type") + if err != nil { + return err + } + if !hasColumn { + // pin_type 把“全区置顶”和“区域置顶”的作用域写进同一 owner 表;历史数据默认都是区域置顶。 + if _, err := r.db.ExecContext(ctx, `ALTER TABLE room_region_pins ADD COLUMN pin_type VARCHAR(32) NOT NULL DEFAULT 'region' AFTER visible_region_id`); err != nil { + return err + } + } + hasScopeUnique, err := r.indexExists(ctx, "room_region_pins", "uk_room_region_pins_scope") + if err != nil { + return err + } + if !hasScopeUnique { + if _, err := r.db.ExecContext(ctx, `ALTER TABLE room_region_pins ADD UNIQUE KEY uk_room_region_pins_scope (app_code, pin_type, visible_region_id, room_id)`); err != nil { + return err + } + } + hasLegacyUnique, err := r.indexExists(ctx, "room_region_pins", "uk_room_region_pins_room") + if err != nil { + return err + } + if hasLegacyUnique { + // 新唯一键允许 region_id=0 的区域置顶和全区置顶并存;旧唯一键会错误地把两者互斥。 + if _, err := r.db.ExecContext(ctx, `ALTER TABLE room_region_pins DROP INDEX uk_room_region_pins_room`); err != nil { + return err + } + } + hasActiveScope, err := r.indexExists(ctx, "room_region_pins", "idx_room_region_pins_active_scope") + if err != nil { + return err + } + if !hasActiveScope { + if _, err := r.db.ExecContext(ctx, `ALTER TABLE room_region_pins ADD INDEX idx_room_region_pins_active_scope (app_code, pin_type, visible_region_id, status, pinned_at_ms, expires_at_ms, weight DESC, room_id)`); err != nil { + return err + } + } + return nil +} + func (r *Repository) ensureRoomUserPresenceSchema(ctx context.Context) error { hasColumn, err := r.columnExists(ctx, "room_user_presence", "joined_at_ms") if err != nil { @@ -1451,7 +1498,7 @@ func (r *Repository) UpsertRoomListEntry(ctx context.Context, entry roomservice. return err } -// ListRoomListEntries 按区域读取房间列表读模型。 +// ListRoomListEntries 读取公共发现列表读模型,并按查询区域把全区置顶、区域置顶、本区房和外区房排成稳定分页序列。 func (r *Repository) ListRoomListEntries(ctx context.Context, query roomservice.RoomListQuery) ([]roomservice.RoomListEntry, error) { if query.Limit <= 0 { query.Limit = 20 @@ -1491,6 +1538,7 @@ func (r *Repository) ListRoomListEntries(ctx context.Context, query roomservice. &entry.CreatedAtMS, &entry.UpdatedAtMS, &pinned, + &entry.PinListRank, &entry.PinWeight, &entry.PinnedUntilMS, ); err != nil { @@ -1858,22 +1906,43 @@ const roomFollowSelectColumns = ` JOIN room_list_entries r ON r.app_code = f.app_code AND r.room_id = f.room_id` func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) { - pinnedExpr := "CASE WHEN p.room_id IS NULL THEN 0 ELSE 1 END" - pinWeightExpr := "COALESCE(p.weight, 0)" - pinExpiresExpr := "COALESCE(p.expires_at_ms, 0)" + regionID := query.VisibleRegionID + if regionID < 0 { + regionID = 0 + } + regionLiteral := strconv.FormatInt(regionID, 10) + pinnedExpr := "CASE WHEN gp.room_id IS NULL AND rp.room_id IS NULL THEN 0 ELSE 1 END" + newPinRankExpr := "CASE WHEN gp.room_id IS NOT NULL THEN 0 WHEN rp.room_id IS NOT NULL THEN 1 WHEN r.visible_region_id = " + regionLiteral + " THEN 2 ELSE 3 END" + hotPinRankExpr := "CASE WHEN gp.room_id IS NOT NULL THEN 0 WHEN rp.room_id IS NOT NULL THEN 1 WHEN r.visible_region_id = " + regionLiteral + " AND r.online_count > 0 THEN 2 WHEN r.visible_region_id <> " + regionLiteral + " AND r.online_count > 0 THEN 3 WHEN r.visible_region_id = " + regionLiteral + " THEN 4 ELSE 5 END" + pinRankExpr := hotPinRankExpr + if query.Tab == "new" { + pinRankExpr = newPinRankExpr + } + pinWeightExpr := "CASE WHEN gp.room_id IS NOT NULL THEN gp.weight WHEN rp.room_id IS NOT NULL THEN rp.weight ELSE 0 END" + pinExpiresExpr := "CASE WHEN gp.room_id IS NOT NULL THEN gp.expires_at_ms WHEN rp.room_id IS NOT NULL THEN rp.expires_at_ms ELSE 0 END" selectSQL := ` SELECT r.app_code, r.room_id, r.room_short_id, r.visible_region_id, r.owner_user_id, r.title, r.cover_url, r.mode, r.status, r.locked, r.heat, r.online_count, r.seat_count, r.occupied_seat_count, r.sort_score, r.created_at_ms, r.updated_at_ms, - ` + pinnedExpr + ` AS is_pinned, ` + pinWeightExpr + ` AS pin_weight, ` + pinExpiresExpr + ` AS pinned_until_ms + ` + pinnedExpr + ` AS is_pinned, ` + pinRankExpr + ` AS pin_list_rank, ` + pinWeightExpr + ` AS pin_weight, ` + pinExpiresExpr + ` AS pinned_until_ms FROM room_list_entries r - LEFT JOIN room_region_pins p - ON p.app_code = r.app_code - AND p.visible_region_id = r.visible_region_id - AND p.room_id = r.room_id - AND p.status = ? - AND p.expires_at_ms > ?` - where := []string{"r.app_code = ?", "r.visible_region_id = ?", "r.status = ?"} - args := []any{"active", query.NowMS, appcode.Normalize(query.AppCode), query.VisibleRegionID, "active"} + LEFT JOIN room_region_pins gp + ON gp.app_code = r.app_code + AND gp.pin_type = 'global' + AND gp.visible_region_id = 0 + AND gp.room_id = r.room_id + AND gp.status = ? + AND gp.pinned_at_ms <= ? + AND gp.expires_at_ms > ? + LEFT JOIN room_region_pins rp + ON rp.app_code = r.app_code + AND rp.pin_type = 'region' + AND rp.visible_region_id = ? + AND rp.room_id = r.room_id + AND rp.status = ? + AND rp.pinned_at_ms <= ? + AND rp.expires_at_ms > ?` + where := []string{"r.app_code = ?", "r.status = ?"} + args := []any{"active", query.NowMS, query.NowMS, regionID, "active", query.NowMS, query.NowMS, appcode.Normalize(query.AppCode), "active"} if query.OwnerUserID > 0 { where = append(where, "r.owner_user_id = ?") args = append(args, query.OwnerUserID) @@ -1885,19 +1954,19 @@ func buildRoomListQuerySQL(query roomservice.RoomListQuery) (string, []any) { } if query.Tab == "new" { if query.CursorRoomID != "" { - where = append(where, roomListAfterCursorSQL(pinnedExpr, pinWeightExpr, pinExpiresExpr, "r.created_at_ms")) - args = append(args, roomListAfterCursorArgs(query.CursorPinned, query.CursorPinWeight, query.CursorPinnedUntilMS, query.CursorCreatedAtMS, query.CursorRoomID)...) + where = append(where, roomListAfterCursorSQL(pinRankExpr, pinWeightExpr, pinExpiresExpr, "r.created_at_ms")) + args = append(args, roomListAfterCursorArgs(query.CursorPinListRank, query.CursorPinWeight, query.CursorPinnedUntilMS, query.CursorCreatedAtMS, query.CursorRoomID)...) } args = append(args, query.Limit) - return selectSQL + "\n\tWHERE " + strings.Join(where, " AND ") + "\n\tORDER BY " + pinnedExpr + " DESC, " + pinWeightExpr + " DESC, " + pinExpiresExpr + " DESC, r.created_at_ms DESC, r.room_id ASC\n\tLIMIT ?", args + return selectSQL + "\n\tWHERE " + strings.Join(where, " AND ") + "\n\tORDER BY " + pinRankExpr + " ASC, " + pinWeightExpr + " DESC, " + pinExpiresExpr + " DESC, r.created_at_ms DESC, r.room_id ASC\n\tLIMIT ?", args } if query.CursorRoomID != "" { - where = append(where, roomListAfterCursorSQL(pinnedExpr, pinWeightExpr, pinExpiresExpr, "r.sort_score")) - args = append(args, roomListAfterCursorArgs(query.CursorPinned, query.CursorPinWeight, query.CursorPinnedUntilMS, query.CursorSortScore, query.CursorRoomID)...) + where = append(where, roomListAfterCursorSQL(pinRankExpr, pinWeightExpr, pinExpiresExpr, "r.sort_score")) + args = append(args, roomListAfterCursorArgs(query.CursorPinListRank, query.CursorPinWeight, query.CursorPinnedUntilMS, query.CursorSortScore, query.CursorRoomID)...) } args = append(args, query.Limit) - return selectSQL + "\n\tWHERE " + strings.Join(where, " AND ") + "\n\tORDER BY " + pinnedExpr + " DESC, " + pinWeightExpr + " DESC, " + pinExpiresExpr + " DESC, r.sort_score DESC, r.room_id ASC\n\tLIMIT ?", args + return selectSQL + "\n\tWHERE " + strings.Join(where, " AND ") + "\n\tORDER BY " + pinRankExpr + " ASC, " + pinWeightExpr + " DESC, " + pinExpiresExpr + " DESC, r.sort_score DESC, r.room_id ASC\n\tLIMIT ?", args } func (r *Repository) AdminListRooms(ctx context.Context, query roomservice.AdminRoomListQuery) ([]roomservice.AdminRoomListEntry, int64, error) { @@ -1976,6 +2045,10 @@ func adminRoomWhere(ctx context.Context, query roomservice.AdminRoomListQuery) ( where = append(where, "rle.visible_region_id = ?") args = append(args, query.RegionID) } + if query.OwnerUserID > 0 { + where = append(where, "rle.owner_user_id = ?") + args = append(args, query.OwnerUserID) + } if strings.TrimSpace(query.Keyword) != "" { like := "%" + strings.ReplaceAll(strings.TrimSpace(query.Keyword), "%", "\\%") + "%" where = append(where, "(rle.room_id LIKE ? ESCAPE '\\\\' OR rle.room_short_id LIKE ? ESCAPE '\\\\' OR rle.title LIKE ? ESCAPE '\\\\' OR CAST(rle.owner_user_id AS CHAR) LIKE ? ESCAPE '\\\\')") @@ -2063,21 +2136,36 @@ func (r *Repository) AdminCreateRoomPin(ctx context.Context, input roomservice.A if room.Status != "active" { return roomservice.AdminRoomPinEntry{}, false, nil } - expiresAtMS := input.NowMS + input.DurationDays*24*60*60*1000 + pinType := strings.TrimSpace(input.PinType) + if pinType == "" { + pinType = "region" + } + visibleRegionID := room.VisibleRegionID + if pinType == "global" { + visibleRegionID = 0 + } + pinnedAtMS := input.PinnedAtMS + if pinnedAtMS <= 0 { + pinnedAtMS = input.NowMS + } + expiresAtMS := input.ExpiresAtMS + if expiresAtMS <= 0 { + expiresAtMS = pinnedAtMS + input.DurationDays*24*60*60*1000 + } if _, err := r.db.ExecContext(ctx, ` INSERT INTO room_region_pins ( - app_code, visible_region_id, room_id, weight, status, pinned_at_ms, expires_at_ms, + app_code, visible_region_id, pin_type, room_id, weight, status, pinned_at_ms, expires_at_ms, cancelled_at_ms, created_by_admin_id, cancelled_by_admin_id, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, 'active', ?, ?, 0, ?, 0, ?, ?) + ) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, 0, ?, 0, ?, ?) ON DUPLICATE KEY UPDATE weight = VALUES(weight), status = VALUES(status), pinned_at_ms = VALUES(pinned_at_ms), expires_at_ms = VALUES(expires_at_ms), cancelled_at_ms = 0, created_by_admin_id = VALUES(created_by_admin_id), cancelled_by_admin_id = 0, created_at_ms = VALUES(created_at_ms), updated_at_ms = VALUES(updated_at_ms) - `, app, room.VisibleRegionID, room.RoomID, input.Weight, input.NowMS, expiresAtMS, input.AdminID, input.NowMS, input.NowMS); err != nil { + `, app, visibleRegionID, pinType, room.RoomID, input.Weight, pinnedAtMS, expiresAtMS, input.AdminID, input.NowMS, input.NowMS); err != nil { return roomservice.AdminRoomPinEntry{}, false, err } - return r.adminGetRoomPin(ctx, `WHERE p.app_code = ? AND p.visible_region_id = ? AND p.room_id = ?`, app, room.VisibleRegionID, room.RoomID) + return r.adminGetRoomPin(ctx, `WHERE p.app_code = ? AND p.pin_type = ? AND p.visible_region_id = ? AND p.room_id = ?`, app, pinType, visibleRegionID, room.RoomID) } func (r *Repository) AdminCancelRoomPin(ctx context.Context, pinID int64, adminID uint64, nowMS int64) (roomservice.AdminRoomPinEntry, bool, error) { @@ -2105,10 +2193,10 @@ func (r *Repository) adminGetRoomPin(ctx context.Context, where string, args ... func adminRoomPinSelectSQL() string { return ` - SELECT p.id, p.visible_region_id, p.room_id, p.weight, p.status, + SELECT p.id, p.visible_region_id, p.pin_type, p.room_id, p.weight, p.status, p.pinned_at_ms, p.expires_at_ms, p.cancelled_at_ms, p.created_by_admin_id, p.cancelled_by_admin_id, p.created_at_ms, p.updated_at_ms, - r.room_short_id, r.title, r.cover_url, r.owner_user_id, r.status + r.room_short_id, r.visible_region_id, r.title, r.cover_url, r.owner_user_id, r.status FROM room_region_pins p JOIN room_list_entries r ON r.app_code = p.app_code AND r.room_id = p.room_id ` } @@ -2135,6 +2223,10 @@ func adminRoomPinWhere(ctx context.Context, query roomservice.AdminRoomPinQuery) where = append(where, "p.visible_region_id = ?") args = append(args, query.RegionID) } + if strings.TrimSpace(query.PinType) != "" { + where = append(where, "p.pin_type = ?") + args = append(args, strings.TrimSpace(query.PinType)) + } if strings.TrimSpace(query.Keyword) != "" { like := "%" + strings.ReplaceAll(strings.TrimSpace(query.Keyword), "%", "\\%") + "%" where = append(where, "(p.room_id LIKE ? ESCAPE '\\\\' OR r.room_short_id LIKE ? ESCAPE '\\\\' OR r.title LIKE ? ESCAPE '\\\\' OR CAST(r.owner_user_id AS CHAR) LIKE ? ESCAPE '\\\\')") @@ -2145,31 +2237,27 @@ func adminRoomPinWhere(ctx context.Context, query roomservice.AdminRoomPinQuery) func scanAdminRoomPin(scanner interface{ Scan(dest ...any) error }) (roomservice.AdminRoomPinEntry, error) { var item roomservice.AdminRoomPinEntry - err := scanner.Scan(&item.ID, &item.VisibleRegionID, &item.RoomID, &item.Weight, &item.Status, &item.PinnedAtMS, &item.ExpiresAtMS, &item.CancelledAtMS, &item.CreatedByAdminID, &item.CancelledByAdminID, &item.CreatedAtMS, &item.UpdatedAtMS, &item.RoomShortID, &item.Title, &item.CoverURL, &item.OwnerUserID, &item.RoomStatus) + err := scanner.Scan(&item.ID, &item.VisibleRegionID, &item.PinType, &item.RoomID, &item.Weight, &item.Status, &item.PinnedAtMS, &item.ExpiresAtMS, &item.CancelledAtMS, &item.CreatedByAdminID, &item.CancelledByAdminID, &item.CreatedAtMS, &item.UpdatedAtMS, &item.RoomShortID, &item.RoomVisibleRegionID, &item.Title, &item.CoverURL, &item.OwnerUserID, &item.RoomStatus) return item, err } -func roomListAfterCursorSQL(pinnedExpr string, pinWeightExpr string, pinExpiresExpr string, sortExpr string) string { - // 置顶分区、权重、过期时间和原有排序键共同组成游标,避免区域置顶跨页时重复或跳过普通房间。 +func roomListAfterCursorSQL(pinRankExpr string, pinWeightExpr string, pinExpiresExpr string, sortExpr string) string { + // 排序桶、置顶权重、过期时间和 tab 排序键共同组成游标,避免跨全区置顶/区域置顶/普通房分区翻页时重复或跳过。 return "(" + - pinnedExpr + " < ? OR (" + - pinnedExpr + " = ? AND " + pinWeightExpr + " < ?) OR (" + - pinnedExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " < ?) OR (" + - pinnedExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " = ? AND " + sortExpr + " < ?) OR (" + - pinnedExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " = ? AND " + sortExpr + " = ? AND r.room_id > ?))" + pinRankExpr + " > ? OR (" + + pinRankExpr + " = ? AND " + pinWeightExpr + " < ?) OR (" + + pinRankExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " < ?) OR (" + + pinRankExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " = ? AND " + sortExpr + " < ?) OR (" + + pinRankExpr + " = ? AND " + pinWeightExpr + " = ? AND " + pinExpiresExpr + " = ? AND " + sortExpr + " = ? AND r.room_id > ?))" } -func roomListAfterCursorArgs(pinned bool, pinWeight int64, pinnedUntilMS int64, sortValue int64, roomID string) []any { - pinnedValue := 0 - if pinned { - pinnedValue = 1 - } +func roomListAfterCursorArgs(pinListRank int64, pinWeight int64, pinnedUntilMS int64, sortValue int64, roomID string) []any { return []any{ - pinnedValue, - pinnedValue, pinWeight, - pinnedValue, pinWeight, pinnedUntilMS, - pinnedValue, pinWeight, pinnedUntilMS, sortValue, - pinnedValue, pinWeight, pinnedUntilMS, sortValue, roomID, + pinListRank, + pinListRank, pinWeight, + pinListRank, pinWeight, pinnedUntilMS, + pinListRank, pinWeight, pinnedUntilMS, sortValue, + pinListRank, pinWeight, pinnedUntilMS, sortValue, roomID, } } diff --git a/services/room-service/internal/testutil/mysqltest/mysqltest.go b/services/room-service/internal/testutil/mysqltest/mysqltest.go index 536a0c3b..bad4c5c3 100644 --- a/services/room-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/room-service/internal/testutil/mysqltest/mysqltest.go @@ -76,33 +76,68 @@ func (r *Repository) DeleteRoomListEntry(roomID string) { func (r *Repository) SetRoomSortScore(roomID string, sortScore int64) { r.t.Helper() + r.requireRoomListEntry(roomID) if _, err := r.schema.DB.ExecContext(context.Background(), `UPDATE room_list_entries SET sort_score = ? WHERE app_code = ? AND room_id = ?`, sortScore, appcode.Default, roomID); err != nil { r.t.Fatalf("update room sort score failed: %v", err) } } +// SetRoomPresence rewrites discovery presence counters for deterministic hot bucket tests. +func (r *Repository) SetRoomPresence(roomID string, onlineCount int32, occupiedSeatCount int32) { + r.t.Helper() + + r.requireRoomListEntry(roomID) + if _, err := r.schema.DB.ExecContext(context.Background(), `UPDATE room_list_entries SET online_count = ?, occupied_seat_count = ? WHERE app_code = ? AND room_id = ?`, onlineCount, occupiedSeatCount, appcode.Default, roomID); err != nil { + r.t.Fatalf("update room presence failed: %v", err) + } +} + +func (r *Repository) requireRoomListEntry(roomID string) { + r.t.Helper() + + var exists int + if err := r.schema.DB.QueryRowContext(context.Background(), `SELECT 1 FROM room_list_entries WHERE app_code = ? AND room_id = ? LIMIT 1`, appcode.Default, roomID).Scan(&exists); err != nil { + r.t.Fatalf("room list entry %s is missing: %v", roomID, err) + } +} + // PinRoom inserts an active regional pin exactly as the admin backend writes it. func (r *Repository) PinRoom(roomID string, regionID int64, weight int64, expiresAtMS int64) { + r.PinRoomWithType(roomID, "region", regionID, weight, expiresAtMS) +} + +// PinRoomWithType inserts an active pin with the same scope fields used by admin writes. +func (r *Repository) PinRoomWithType(roomID string, pinType string, regionID int64, weight int64, expiresAtMS int64) { r.t.Helper() nowMS := int64(1000) if _, err := r.schema.DB.ExecContext(context.Background(), ` INSERT INTO room_region_pins ( - app_code, visible_region_id, room_id, weight, status, pinned_at_ms, expires_at_ms, + app_code, visible_region_id, pin_type, room_id, weight, status, pinned_at_ms, expires_at_ms, cancelled_at_ms, created_by_admin_id, cancelled_by_admin_id, created_at_ms, updated_at_ms - ) VALUES (?, ?, ?, ?, 'active', ?, ?, 0, 1, 0, ?, ?) + ) VALUES (?, ?, ?, ?, ?, 'active', ?, ?, 0, 1, 0, ?, ?) ON DUPLICATE KEY UPDATE weight = VALUES(weight), status = VALUES(status), + pin_type = VALUES(pin_type), pinned_at_ms = VALUES(pinned_at_ms), expires_at_ms = VALUES(expires_at_ms), cancelled_at_ms = 0, updated_at_ms = VALUES(updated_at_ms) - `, appcode.Default, regionID, roomID, weight, nowMS, expiresAtMS, nowMS, nowMS); err != nil { + `, appcode.Default, regionID, pinType, roomID, weight, nowMS, expiresAtMS, nowMS, nowMS); err != nil { r.t.Fatalf("pin room failed: %v", err) } } +// SetRoomCreatedAt rewrites discovery created_at_ms for deterministic new-tab order tests. +func (r *Repository) SetRoomCreatedAt(roomID string, createdAtMS int64) { + r.t.Helper() + + if _, err := r.schema.DB.ExecContext(context.Background(), `UPDATE room_list_entries SET created_at_ms = ? WHERE app_code = ? AND room_id = ?`, createdAtMS, appcode.Default, roomID); err != nil { + r.t.Fatalf("update room created_at_ms failed: %v", err) + } +} + // OutboxRecord reads one outbox row, including delivered rows that normal scans skip. func (r *Repository) OutboxRecord(eventID string) (outbox.Record, bool) { r.t.Helper() diff --git a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql index c825d46d..f7375e78 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -29,6 +29,7 @@ CREATE TABLE IF NOT EXISTS stat_app_day_country ( coin_seller_recharge_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '币商充值美元最小单位', mifapay_recharge_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT 'MifaPay 充值美元最小单位', google_recharge_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT 'Google 充值美元最小单位', + coin_seller_transfer_coin BIGINT NOT NULL DEFAULT 0 COMMENT '币商向用户转普通金币数量', gift_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '礼物消耗金币', lucky_gift_turnover BIGINT NOT NULL DEFAULT 0 COMMENT '幸运礼物流水', lucky_gift_payout BIGINT NOT NULL DEFAULT 0 COMMENT '幸运礼物返奖', diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 1e907d9e..d828b5ee 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -229,6 +229,11 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { payload := mysqlstorage.DecodeJSON(message.PayloadJSON) rechargeType := firstNonEmpty(mysqlstorage.String(payload, "recharge_type"), mysqlstorage.String(payload, "channel"), mysqlstorage.String(payload, "provider"), "coin_seller_transfer") usdMinor := rechargeUSDMinorFromPayload(payload, rechargeType) + coinAmount := int64(0) + if isCoinSellerRechargeType(rechargeType) { + usdMinor = 0 + coinAmount = firstNonZeroInt64(mysqlstorage.Int64(payload, "amount"), mysqlstorage.Int64(payload, "coin_amount"), mysqlstorage.Int64(payload, "available_delta")) + } regionID := firstNonZeroInt64(mysqlstorage.Int64(payload, "target_region_id"), mysqlstorage.Int64(payload, "region_id")) return mysqlstorage.RechargeEvent{ AppCode: message.AppCode, @@ -236,6 +241,7 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { EventType: message.EventType, UserID: message.UserID, USDMinor: usdMinor, + CoinAmount: coinAmount, RechargeSequence: mysqlstorage.Int64(payload, "recharge_sequence"), TargetRegionID: regionID, RechargeType: rechargeType, @@ -244,6 +250,10 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { } func rechargeUSDMinorFromPayload(payload map[string]any, rechargeType string) int64 { + // 币商向用户转账是普通金币到账事实,只用于充值用户和金币金额统计;即使历史 payload 携带 recharge_usd_minor,也不能进入用户 USDT/USD 充值。 + if isCoinSellerRechargeType(rechargeType) { + return 0 + } if value := mysqlstorage.Int64(payload, "recharge_usd_minor"); value > 0 { return value } @@ -263,6 +273,15 @@ func isGoogleRechargeType(value string) bool { } } +func isCoinSellerRechargeType(value string) bool { + switch strings.ToLower(strings.TrimSpace(value)) { + case "coin_seller_transfer", "coin_seller": + return true + default: + return false + } +} + func amountMicroToUSDMinor(amountMicro int64) int64 { if amountMicro <= 0 { return 0 @@ -309,11 +328,23 @@ func roomGiftEvent(body []byte) (mysqlstorage.RoomGiftEvent, bool, error) { SenderUserID: gift.GetSenderUserId(), VisibleRegionID: gift.GetVisibleRegionId(), GiftValue: gift.GetGiftValue(), + CoinSpent: roomGiftCoinSpent(&gift), PoolID: gift.GetPoolId(), OccurredAtMS: envelope.GetOccurredAtMs(), }, true, nil } +func roomGiftCoinSpent(gift *roomeventsv1.RoomGiftSent) int64 { + if gift == nil { + return 0 + } + // Databi 的礼物消费和幸运礼物流水按金币展示;新版 RoomGiftSent 会直接携带 coin_spent,历史事件没有该字段时才回退旧的 gift_value 热度口径。 + if gift.GetCoinSpent() > 0 { + return gift.GetCoinSpent() + } + return gift.GetGiftValue() +} + func roomJoinActiveEvent(body []byte) (mysqlstorage.UserActiveEvent, bool, error) { envelope, _, err := roommq.DecodeRoomOutboxMessage(body) if err != nil { diff --git a/services/statistics-service/internal/app/local_flow_test.go b/services/statistics-service/internal/app/local_flow_test.go index 20d9d05d..6d9ff8fa 100644 --- a/services/statistics-service/internal/app/local_flow_test.go +++ b/services/statistics-service/internal/app/local_flow_test.go @@ -60,12 +60,36 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { t.Fatalf("consume google recharge failed: %v", err) } + coinSellerRecharge := walletMessage(t, walletmq.WalletOutboxMessage{ + AppCode: appCode, + EventID: "WalletRechargeRecorded:coin_seller:1", + EventType: "WalletRechargeRecorded", + TransactionID: "wallet_tx_coin_seller_1", + CommandID: "coin_seller_transfer_1", + UserID: userID + 1, + PayloadJSON: mustJSON(t, map[string]any{ + "amount": int64(160_000), + "recharge_type": "coin_seller_transfer", + "target_region_id": regionID, + "recharge_sequence": int64(1), + }), + OccurredAtMS: occurredAt, + }) + coinSeller, ok, err := rechargeEvent(coinSellerRecharge) + if err != nil || !ok { + t.Fatalf("decode coin seller recharge failed: ok=%v err=%v", ok, err) + } + if err := repo.ConsumeRecharge(ctx, coinSeller); err != nil { + t.Fatalf("consume coin seller recharge failed: %v", err) + } + roomGiftBody := roomGiftMessage(t, appCode, "room_gift_1", "room_1", occurredAt, &roomeventsv1.RoomGiftSent{ SenderUserId: userID, TargetUserId: 99, GiftId: "rose", GiftCount: 10, GiftValue: 1_000, + CoinSpent: 1_250, VisibleRegionId: regionID, CommandId: "gift_command_1", PoolId: "lucky_100", @@ -129,17 +153,17 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { if err != nil { t.Fatalf("query overview failed: %v", err) } - if overview.GoogleRechargeUSDMinor != 150 || overview.RechargeUSDMinor != 150 || overview.NewUserRechargeUSDMinor != 150 { + if overview.GoogleRechargeUSDMinor != 150 || overview.CoinSellerRechargeUSDMinor != 0 || overview.CoinSellerTransferCoin != 160_000 || overview.RechargeUSDMinor != 150 || overview.NewUserRechargeUSDMinor != 150 || overview.PaidUsers != 2 { t.Fatalf("google recharge metrics mismatch: %+v", overview) } - if overview.LuckyGiftTurnover != 1_000 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 700 || overview.LuckyGiftPayers != 1 { + if overview.LuckyGiftTurnover != 1_250 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 950 || overview.LuckyGiftPayers != 1 { t.Fatalf("lucky gift metrics mismatch: %+v", overview) } if len(overview.LuckyGiftPools) != 1 { t.Fatalf("lucky gift pool breakdown missing: %+v", overview.LuckyGiftPools) } pool := overview.LuckyGiftPools[0] - if pool.PoolID != "lucky_100" || pool.TurnoverCoin != 1_000 || pool.PayoutCoin != 300 || pool.ProfitCoin != 700 { + if pool.PoolID != "lucky_100" || pool.TurnoverCoin != 1_250 || pool.PayoutCoin != 300 || pool.ProfitCoin != 950 { t.Fatalf("lucky gift pool metrics mismatch: %+v", pool) } if overview.GameTurnover != 700 || overview.GamePayout != 200 || overview.GameProfit != 500 || overview.GamePlayers != 1 { diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index e208a631..eda6d6f2 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -28,6 +28,7 @@ type Overview struct { CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` + CoinSellerTransferCoin int64 `json:"coin_seller_transfer_coin"` GiftCoinSpent int64 `json:"gift_coin_spent"` LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` LuckyGiftPayout int64 `json:"lucky_gift_payout"` @@ -96,7 +97,8 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov SELECT COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), COALESCE(SUM(coin_seller_recharge_usd_minor),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), - COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(gift_coin_spent),0), + COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), + COALESCE(SUM(gift_coin_spent),0), COALESCE(SUM(lucky_gift_turnover),0), COALESCE(SUM(lucky_gift_payout),0), COALESCE(SUM(lucky_gift_payers),0), COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0), COALESCE(SUM(game_players),0) @@ -104,9 +106,14 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+countryFilter, args...) var overview Overview overview.AppCode, overview.StartMS, overview.EndMS, overview.CountryID = app, query.StartMS, query.EndMS, query.CountryID - if err := row.Scan(&overview.NewUsers, &overview.ActiveUsers, &overview.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { + if err := row.Scan(&overview.NewUsers, &overview.ActiveUsers, &overview.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { return Overview{}, err } + // 历史聚合行可能只写了真实 USD 渠道列、没有同步修正 recharge_usd_minor;查询时用渠道合计兜底,但币商转普通金币只展示金币卡片,不进入用户 USDT 充值。 + channelRechargeUSDMinor := overview.MifaPayRechargeUSDMinor + overview.GoogleRechargeUSDMinor + if channelRechargeUSDMinor > overview.RechargeUSDMinor { + overview.RechargeUSDMinor = channelRechargeUSDMinor + } overview.LuckyGiftProfit = overview.LuckyGiftTurnover - overview.LuckyGiftPayout overview.LuckyGiftPayoutRate = ratio(overview.LuckyGiftPayout, overview.LuckyGiftTurnover) overview.LuckyGiftProfitRate = ratio(overview.LuckyGiftProfit, overview.LuckyGiftTurnover) diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index 6bb4231a..205c9a44 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -74,7 +74,8 @@ func (r *Repository) Migrate(ctx context.Context) error { new_users BIGINT NOT NULL DEFAULT 0, active_users BIGINT NOT NULL DEFAULT 0, paid_users BIGINT NOT NULL DEFAULT 0, recharge_usd_minor BIGINT NOT NULL DEFAULT 0, new_user_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, coin_seller_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, mifapay_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, - google_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, gift_coin_spent BIGINT NOT NULL DEFAULT 0, + google_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, coin_seller_transfer_coin BIGINT NOT NULL DEFAULT 0, + gift_coin_spent BIGINT NOT NULL DEFAULT 0, lucky_gift_turnover BIGINT NOT NULL DEFAULT 0, lucky_gift_payout BIGINT NOT NULL DEFAULT 0, lucky_gift_payers BIGINT NOT NULL DEFAULT 0, game_turnover BIGINT NOT NULL DEFAULT 0, game_players BIGINT NOT NULL DEFAULT 0, game_payout BIGINT NOT NULL DEFAULT 0, game_refund BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, @@ -132,6 +133,7 @@ func (r *Repository) Migrate(ctx context.Context) error { `ALTER TABLE stat_app_day_country ADD COLUMN paid_users BIGINT NOT NULL DEFAULT 0 AFTER active_users`, `ALTER TABLE stat_app_day_country ADD COLUMN game_refund BIGINT NOT NULL DEFAULT 0 AFTER game_payout`, `ALTER TABLE stat_app_day_country ADD COLUMN lucky_gift_payout BIGINT NOT NULL DEFAULT 0 AFTER lucky_gift_turnover`, + `ALTER TABLE stat_app_day_country ADD COLUMN coin_seller_transfer_coin BIGINT NOT NULL DEFAULT 0 AFTER google_recharge_usd_minor`, `ALTER TABLE stat_game_day_country ADD COLUMN refund_coin BIGINT NOT NULL DEFAULT 0 AFTER payout_coin`, } for _, statement := range alterStatements { @@ -156,6 +158,7 @@ type RechargeEvent struct { EventType string UserID int64 USDMinor int64 + CoinAmount int64 RechargeSequence int64 TargetRegionID int64 RechargeType string @@ -168,6 +171,7 @@ type RoomGiftEvent struct { SenderUserID int64 VisibleRegionID int64 GiftValue int64 + CoinSpent int64 PoolID string OccurredAtMS int64 } @@ -244,12 +248,14 @@ func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) e if event.RechargeSequence == 1 { newUserUSD = event.USDMinor } - coinSellerUSD, mifapayUSD, googleUSD := int64(0), int64(0), int64(0) + coinSellerUSD, mifapayUSD, googleUSD, coinSellerTransferCoin := int64(0), int64(0), int64(0), int64(0) switch strings.ToLower(strings.TrimSpace(event.RechargeType)) { case "google", "google_play": googleUSD = event.USDMinor case "mifapay": mifapayUSD = event.USDMinor + case "coin_seller_transfer", "coin_seller": + coinSellerTransferCoin = event.CoinAmount default: coinSellerUSD = event.USDMinor } @@ -260,10 +266,11 @@ func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) e coin_seller_recharge_usd_minor = coin_seller_recharge_usd_minor + ?, mifapay_recharge_usd_minor = mifapay_recharge_usd_minor + ?, google_recharge_usd_minor = google_recharge_usd_minor + ?, + coin_seller_transfer_coin = coin_seller_transfer_coin + ?, paid_users = paid_users + ?, updated_at_ms = ? WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.USDMinor, newUserUSD, coinSellerUSD, mifapayUSD, googleUSD, paidUsers, nowMS, appcode.Normalize(event.AppCode), day, countryID) + `, event.USDMinor, newUserUSD, coinSellerUSD, mifapayUSD, googleUSD, coinSellerTransferCoin, paidUsers, nowMS, appcode.Normalize(event.AppCode), day, countryID) return err }) } @@ -278,7 +285,7 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e luckyTurnover, luckyPayers := int64(0), int64(0) poolID := strings.TrimSpace(event.PoolID) if poolID != "" { - luckyTurnover = event.GiftValue + luckyTurnover = event.CoinSpent affected, err := insertUnique(ctx, tx, ` INSERT IGNORE INTO stat_lucky_gift_day_payers (app_code, stat_day, country_id, user_id, first_paid_at_ms) VALUES (?, ?, ?, ?, ?) @@ -304,7 +311,7 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e SET gift_coin_spent = gift_coin_spent + ?, lucky_gift_turnover = lucky_gift_turnover + ?, lucky_gift_payers = lucky_gift_payers + ?, updated_at_ms = ? WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.GiftValue, luckyTurnover, luckyPayers, nowMS, appcode.Normalize(event.AppCode), day, countryID) + `, event.CoinSpent, luckyTurnover, luckyPayers, nowMS, appcode.Normalize(event.AppCode), day, countryID) return err }) } diff --git a/services/user-service/internal/app/app.go b/services/user-service/internal/app/app.go index 21eb649f..86250235 100644 --- a/services/user-service/internal/app/app.go +++ b/services/user-service/internal/app/app.go @@ -228,6 +228,7 @@ func New(cfg config.Config) (*App, error) { userservice.WithCountryAdminRepository(regionRepo), userservice.WithRegionAdminRepository(regionRepo), userservice.WithRegionRebuildRepository(regionRepo), + userservice.WithRoleSummaryRepository(hostRepo), userservice.WithDeviceRepository(deviceRepo), userservice.WithModerationRepository(userRepo), userservice.WithSessionDenylist(ipDecisionCache, time.Duration(cfg.JWT.AccessTokenTTLSec+60)*time.Second), diff --git a/services/user-service/internal/domain/host/host.go b/services/user-service/internal/domain/host/host.go index 96a29a92..874dbedb 100644 --- a/services/user-service/internal/domain/host/host.go +++ b/services/user-service/internal/domain/host/host.go @@ -18,6 +18,8 @@ const ( AgencyStatusActive = "active" // AgencyStatusClosed 表示 Agency 已关闭,历史关系仍保留。 AgencyStatusClosed = "closed" + // AgencyStatusDeleted 表示后台删除 Agency 身份;主播身份保留,当前 Agency 归属会被解除。 + AgencyStatusDeleted = "deleted" // BDStatusActive 表示 BD 或 BD Leader 可邀请下级角色。 BDStatusActive = "active" @@ -107,6 +109,8 @@ const ( CommandTypeCreateAgency = "admin_create_agency" // CommandTypeCloseAgency 记录后台关闭 Agency 命令。 CommandTypeCloseAgency = "admin_close_agency" + // CommandTypeDeleteAgency 记录后台删除 Agency 身份命令。 + CommandTypeDeleteAgency = "admin_delete_agency" // CommandTypeSetAgencyJoinEnabled 记录后台设置 Agency 入会开关命令。 CommandTypeSetAgencyJoinEnabled = "admin_set_agency_join_enabled" // CommandTypeCreateCoinSeller 记录后台创建币商身份命令。 @@ -154,6 +158,7 @@ type Agency struct { ActiveHostCount int32 Status string JoinEnabled bool + // MaxHosts 是历史字段,当前 Agency 不再限制主播数量,只保留数据库兼容读写。 MaxHosts int32 CreatedByUserID int64 CreatedAtMs int64 diff --git a/services/user-service/internal/domain/user/user.go b/services/user-service/internal/domain/user/user.go index 31fed33f..30cec989 100644 --- a/services/user-service/internal/domain/user/user.go +++ b/services/user-service/internal/domain/user/user.go @@ -364,11 +364,13 @@ type CountryChangeCommand struct { NewCountry string // NewRegionID 是按 NewCountry 解析出的区域快照,0 表示 GLOBAL 兜底桶。 NewRegionID int64 + // Source 标记本次修改来自 App 自助、后台覆盖或区域重建任务,供下游 owner service 判定当前读模型来源。 + Source string // RequestID 是入口请求 ID,写入国家修改日志。 RequestID string // ChangedAtMs 是本次修改时间。 ChangedAtMs int64 - // CooldownMs 是国家修改冷却窗口,当前按滚动 30 天计算。 + // CooldownMs 是可选冷却窗口;为 0 时不限制连续修改,保留字段用于历史兼容和定向测试。 CooldownMs int64 } diff --git a/services/user-service/internal/service/host/commands.go b/services/user-service/internal/service/host/commands.go index 376077f7..d656d60d 100644 --- a/services/user-service/internal/service/host/commands.go +++ b/services/user-service/internal/service/host/commands.go @@ -149,7 +149,6 @@ type ProcessRoleInvitationCommand struct { type CreateBDLeaderInput struct { CommandID string AdminUserID int64 - RegionID int64 TargetUserID int64 Reason string RequestID string @@ -159,7 +158,6 @@ type CreateBDLeaderInput struct { type CreateBDLeaderCommand struct { CommandID string AdminUserID int64 - RegionID int64 TargetUserID int64 Reason string RequestID string @@ -261,7 +259,6 @@ type CreateAgencyInput struct { ParentBDUserID int64 Name string JoinEnabled bool - MaxHosts int32 Reason string RequestID string } @@ -274,7 +271,6 @@ type CreateAgencyCommand struct { ParentBDUserID int64 Name string JoinEnabled bool - MaxHosts int32 Reason string RequestID string AgencyID int64 @@ -303,6 +299,26 @@ type CloseAgencyCommand struct { NowMs int64 } +// DeleteAgencyInput 是后台删除 Agency 身份的外部输入。 +type DeleteAgencyInput struct { + CommandID string + AdminUserID int64 + AgencyID int64 + Reason string + RequestID string +} + +// DeleteAgencyCommand 是后台删除 Agency 身份事务需要的完整命令。 +type DeleteAgencyCommand struct { + CommandID string + AdminUserID int64 + AgencyID int64 + Reason string + RequestID string + EventID int64 + NowMs int64 +} + // SetAgencyJoinEnabledInput 是后台设置 Agency 入会开关的外部输入。 type SetAgencyJoinEnabledInput struct { CommandID string diff --git a/services/user-service/internal/service/host/service.go b/services/user-service/internal/service/host/service.go index 25419e16..7100787d 100644 --- a/services/user-service/internal/service/host/service.go +++ b/services/user-service/internal/service/host/service.go @@ -31,6 +31,7 @@ type Repository interface { SetCoinSellerStatus(ctx context.Context, command SetCoinSellerStatusCommand) (hostdomain.CoinSellerProfile, error) CreateAgency(ctx context.Context, command CreateAgencyCommand) (hostdomain.CreateAgencyResult, error) CloseAgency(ctx context.Context, command CloseAgencyCommand) (hostdomain.Agency, error) + DeleteAgency(ctx context.Context, command DeleteAgencyCommand) (hostdomain.Agency, error) SetAgencyJoinEnabled(ctx context.Context, command SetAgencyJoinEnabledCommand) (hostdomain.Agency, error) GetHostProfile(ctx context.Context, userID int64) (hostdomain.HostProfile, error) GetBDProfile(ctx context.Context, userID int64) (hostdomain.BDProfile, error) @@ -326,15 +327,14 @@ func (s *Service) CreateBDLeader(ctx context.Context, command CreateBDLeaderInpu if err := s.requireWriteDependencies(); err != nil { return hostdomain.BDProfile{}, err } - if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.TargetUserID <= 0 || command.RegionID <= 0 { - return hostdomain.BDProfile{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id, target_user_id and region_id are required") + if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.TargetUserID <= 0 { + return hostdomain.BDProfile{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id and target_user_id are required") } nowMs := s.now().UnixMilli() return s.repository.CreateBDLeader(ctx, CreateBDLeaderCommand{ CommandID: strings.TrimSpace(command.CommandID), AdminUserID: command.AdminUserID, - RegionID: command.RegionID, TargetUserID: command.TargetUserID, Reason: strings.TrimSpace(command.Reason), RequestID: strings.TrimSpace(command.RequestID), @@ -441,7 +441,7 @@ func (s *Service) SetCoinSellerStatus(ctx context.Context, command SetCoinSeller }) } -// CreateAgency 由后台直接创建 Agency;父级 BD 可选,并原子创建 owner 的 host_profile 和 owner membership。 +// CreateAgency 由后台直接创建 Agency;父级 BD 可选,并原子创建或复用 owner 的 host_profile 和 owner membership。 func (s *Service) CreateAgency(ctx context.Context, command CreateAgencyInput) (hostdomain.CreateAgencyResult, error) { if err := s.requireWriteDependencies(); err != nil { return hostdomain.CreateAgencyResult{}, err @@ -453,9 +453,6 @@ func (s *Service) CreateAgency(ctx context.Context, command CreateAgencyInput) ( if command.ParentBDUserID < 0 { return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "parent_bd_user_id must not be negative") } - if command.MaxHosts < 0 { - return hostdomain.CreateAgencyResult{}, xerr.New(xerr.InvalidArgument, "max_hosts must not be negative") - } nowMs := s.now().UnixMilli() eventID := s.nextEventIDRange(3) @@ -466,7 +463,6 @@ func (s *Service) CreateAgency(ctx context.Context, command CreateAgencyInput) ( ParentBDUserID: command.ParentBDUserID, Name: name, JoinEnabled: command.JoinEnabled, - MaxHosts: command.MaxHosts, Reason: strings.TrimSpace(command.Reason), RequestID: strings.TrimSpace(command.RequestID), AgencyID: s.idGenerator.NewInt64(), @@ -497,6 +493,27 @@ func (s *Service) CloseAgency(ctx context.Context, command CloseAgencyInput) (ho }) } +// DeleteAgency 删除 Agency 身份;它只解除当前 Agency 关系,不删除主播身份和历史记录。 +func (s *Service) DeleteAgency(ctx context.Context, command DeleteAgencyInput) (hostdomain.Agency, error) { + if err := s.requireWriteDependencies(); err != nil { + return hostdomain.Agency{}, err + } + if strings.TrimSpace(command.CommandID) == "" || command.AdminUserID <= 0 || command.AgencyID <= 0 { + return hostdomain.Agency{}, xerr.New(xerr.InvalidArgument, "command_id, admin_user_id and agency_id are required") + } + nowMs := s.now().UnixMilli() + + return s.repository.DeleteAgency(ctx, DeleteAgencyCommand{ + CommandID: strings.TrimSpace(command.CommandID), + AdminUserID: command.AdminUserID, + AgencyID: command.AgencyID, + Reason: strings.TrimSpace(command.Reason), + RequestID: strings.TrimSpace(command.RequestID), + EventID: s.idGenerator.NewInt64(), + NowMs: nowMs, + }) +} + // SetAgencyJoinEnabled 设置 Agency 是否允许 App 用户申请加入。 func (s *Service) SetAgencyJoinEnabled(ctx context.Context, command SetAgencyJoinEnabledInput) (hostdomain.Agency, error) { if err := s.requireWriteDependencies(); err != nil { diff --git a/services/user-service/internal/service/host/service_test.go b/services/user-service/internal/service/host/service_test.go index a99484c4..d0f91a90 100644 --- a/services/user-service/internal/service/host/service_test.go +++ b/services/user-service/internal/service/host/service_test.go @@ -172,7 +172,7 @@ func TestApplyReviewApproveCreatesHostMembershipIdempotently(t *testing.T) { } } -func TestAcceptAgencyInvitationCreatesOwnerHostAndRejectsActiveHost(t *testing.T) { +func TestAcceptAgencyInvitationCreatesOwnerHostAndReusesDetachedHost(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) seedActiveUser(t, repository, 501, 10) @@ -219,14 +219,34 @@ func TestAcceptAgencyInvitationCreatesOwnerHostAndRejectsActiveHost(t *testing.T RegionID: 10, Source: "test", }) - _, err = svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ + secondInvitation, err := svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ CommandID: "invite-agency-602", InviterUserID: 501, TargetUserID: 602, + AgencyName: "Reused Host Agency", + }) + if err != nil { + t.Fatalf("detached active host should become agency owner: %v", err) + } + secondSummary, err := svc.GetUserRoleSummary(ctx, 602) + if err != nil { + t.Fatalf("GetUserRoleSummary for reused host failed: %v", err) + } + secondHostProfile, err := svc.GetHostProfile(ctx, 602) + if err != nil { + t.Fatalf("GetHostProfile for reused host failed: %v", err) + } + if !secondSummary.IsAgency || !secondSummary.IsHost || secondHostProfile.CurrentAgencyID <= 0 || secondHostProfile.Source != "test" || secondInvitation.Status != hostdomain.InvitationStatusAccepted { + t.Fatalf("detached host reuse mismatch: summary=%+v host=%+v invitation=%+v", secondSummary, secondHostProfile, secondInvitation) + } + _, err = svc.InviteAgency(ctx, hostservice.InviteAgencyInput{ + CommandID: "invite-agency-602-again", + InviterUserID: 501, + TargetUserID: 602, AgencyName: "Blocked Agency", }) if got := xerr.CodeOf(err); got != xerr.Conflict { - t.Fatalf("active host must not become agency owner: got %s err=%v", got, err) + t.Fatalf("host with active membership must not become another agency owner: got %s err=%v", got, err) } } @@ -270,7 +290,7 @@ func TestAdminCreateBDLeaderAndBDIdempotently(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) repository.PutRegion(userdomain.Region{RegionID: 20, RegionCode: "R20", Name: "Region 20"}) - seedActiveUser(t, repository, 801, 10) + seedActiveUser(t, repository, 801, 20) seedActiveUser(t, repository, 802, 20) seedActiveUser(t, repository, 804, 20) svc := newHostService(repository, 4000, 5000) @@ -278,7 +298,6 @@ func TestAdminCreateBDLeaderAndBDIdempotently(t *testing.T) { leader, err := svc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ CommandID: "admin-create-leader-801", AdminUserID: 1, - RegionID: 20, TargetUserID: 801, Reason: "seed leader", RequestID: "req-leader-1", @@ -294,12 +313,11 @@ func TestAdminCreateBDLeaderAndBDIdempotently(t *testing.T) { t.Fatalf("GetUser after CreateBDLeader failed: %v", err) } if updatedUser.RegionID != 20 { - t.Fatalf("CreateBDLeader must move target user region: %+v", updatedUser) + t.Fatalf("CreateBDLeader must keep target user region as profile region: %+v", updatedUser) } retriedLeader, err := svc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ CommandID: "admin-create-leader-801", AdminUserID: 1, - RegionID: 20, TargetUserID: 801, }) if err != nil { @@ -358,13 +376,12 @@ func TestAdminCreateBDLeaderRejectsDisabledRegion(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) repository.PutRegion(userdomain.Region{RegionID: 21, RegionCode: "R21", Name: "Region 21", Status: userdomain.RegionStatusDisabled}) - seedActiveUser(t, repository, 803, 10) + seedActiveUser(t, repository, 803, 21) svc := newHostService(repository, 4100, 5100) _, err := svc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ CommandID: "admin-create-leader-disabled-region", AdminUserID: 1, - RegionID: 21, TargetUserID: 803, }) if got := xerr.CodeOf(err); got != xerr.RegionDisabled { @@ -393,7 +410,6 @@ func TestAdminCreateAgencyControlsAppSearch(t *testing.T) { ParentBDUserID: 900, Name: "Admin Seed Agency", JoinEnabled: true, - MaxHosts: 100, Reason: "seed agency", RequestID: "req-agency-1", }) @@ -416,7 +432,6 @@ func TestAdminCreateAgencyControlsAppSearch(t *testing.T) { ParentBDUserID: 900, Name: "Other Country Agency", JoinEnabled: true, - MaxHosts: 100, Reason: "seed agency", RequestID: "req-agency-2", }); err != nil { @@ -479,6 +494,43 @@ func TestAdminCreateAgencyControlsAppSearch(t *testing.T) { if closed.Status != hostdomain.AgencyStatusClosed || closed.JoinEnabled { t.Fatalf("closed agency mismatch: %+v", closed) } + + deleted, err := svc.DeleteAgency(ctx, hostservice.DeleteAgencyInput{ + CommandID: "admin-delete-agency-901", + AdminUserID: 1, + AgencyID: created.Agency.AgencyID, + Reason: "delete agency", + RequestID: "req-agency-delete-1", + }) + if err != nil { + t.Fatalf("DeleteAgency failed: %v", err) + } + if deleted.Status != hostdomain.AgencyStatusDeleted || deleted.JoinEnabled { + t.Fatalf("deleted agency mismatch: %+v", deleted) + } + hostProfile, err := svc.GetHostProfile(ctx, 901) + if err != nil { + t.Fatalf("GetHostProfile after delete failed: %v", err) + } + if hostProfile.CurrentAgencyID != 0 || hostProfile.CurrentMembershipID != 0 || hostProfile.Status != hostdomain.HostStatusActive { + t.Fatalf("delete agency should detach but keep host profile: %+v", hostProfile) + } + recreated, err := svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ + CommandID: "admin-create-agency-901-after-delete", + AdminUserID: 1, + OwnerUserID: 901, + ParentBDUserID: 900, + Name: "Recreated Agency", + JoinEnabled: true, + Reason: "recreate agency", + RequestID: "req-agency-recreate-1", + }) + if err != nil { + t.Fatalf("detached owner host should be reusable after delete: %v", err) + } + if recreated.HostProfile.CurrentAgencyID != recreated.Agency.AgencyID || recreated.HostProfile.FirstBecameHostAtMs != hostProfile.FirstBecameHostAtMs { + t.Fatalf("recreated agency should reuse host identity: host=%+v agency=%+v oldHost=%+v", recreated.HostProfile, recreated.Agency, hostProfile) + } } func TestAdminCreateAgencyWithoutParentBD(t *testing.T) { @@ -493,7 +545,6 @@ func TestAdminCreateAgencyWithoutParentBD(t *testing.T) { OwnerUserID: 904, Name: "Independent Agency", JoinEnabled: true, - MaxHosts: 20, Reason: "seed independent agency", RequestID: "req-agency-independent-1", }) @@ -508,7 +559,7 @@ func TestAdminCreateAgencyWithoutParentBD(t *testing.T) { } } -func TestAdminCreateAgencyRejectsExistingHost(t *testing.T) { +func TestAdminCreateAgencyReusesDetachedHost(t *testing.T) { ctx := context.Background() repository := mysqltest.NewRepository(t) seedActiveUser(t, repository, 911, 40) @@ -526,16 +577,30 @@ func TestAdminCreateAgencyRejectsExistingHost(t *testing.T) { }) svc := newHostService(repository, 6000, 7000) - _, err := svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ + created, err := svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ CommandID: "admin-create-agency-existing-host", AdminUserID: 1, OwnerUserID: 911, ParentBDUserID: 910, + Name: "Reused Host Agency", + JoinEnabled: true, + }) + if err != nil { + t.Fatalf("detached host should become agency owner: %v", err) + } + if created.HostProfile.CurrentAgencyID != created.Agency.AgencyID || created.HostProfile.Source != "test" { + t.Fatalf("existing host identity should be reused without rewriting source: %+v", created.HostProfile) + } + _, err = svc.CreateAgency(ctx, hostservice.CreateAgencyInput{ + CommandID: "admin-create-agency-existing-host-again", + AdminUserID: 1, + OwnerUserID: 911, + ParentBDUserID: 910, Name: "Blocked Agency", JoinEnabled: true, }) if got := xerr.CodeOf(err); got != xerr.Conflict { - t.Fatalf("existing host must not become agency owner: got %s err=%v", got, err) + t.Fatalf("host with active membership must not become another agency owner: got %s err=%v", got, err) } } diff --git a/services/user-service/internal/service/user/country_outbox_test.go b/services/user-service/internal/service/user/country_outbox_test.go new file mode 100644 index 00000000..1344307f --- /dev/null +++ b/services/user-service/internal/service/user/country_outbox_test.go @@ -0,0 +1,86 @@ +package user_test + +import ( + "context" + "encoding/json" + "testing" + "time" + + "hyapp/pkg/appcode" + hostdomain "hyapp/services/user-service/internal/domain/host" + userdomain "hyapp/services/user-service/internal/domain/user" + userservice "hyapp/services/user-service/internal/service/user" + "hyapp/services/user-service/internal/testutil/mysqltest" +) + +func TestAdminChangeUserCountryOverridesProtectedRoleAndWritesOutbox(t *testing.T) { + ctx := appcode.WithContext(context.Background(), appcode.Default) + repository := mysqltest.NewRepository(t) + repository.PutCountry(userdomain.Country{CountryCode: "US", Enabled: true}) + repository.PutCountry(userdomain.Country{CountryCode: "TH", Enabled: true}) + repository.PutRegion(userdomain.Region{RegionID: 101, RegionCode: "US-REGION", Name: "US Region", Countries: []string{"US"}}) + repository.PutRegion(userdomain.Region{RegionID: 202, RegionCode: "TH-REGION", Name: "TH Region", Countries: []string{"TH"}}) + repository.PutUser(userdomain.User{ + UserID: 91001, + DefaultDisplayUserID: "91001", + CurrentDisplayUserID: "91001", + Country: "US", + RegionID: 101, + ProfileCompleted: true, + ProfileCompletedAtMs: 1, + OnboardingStatus: userdomain.OnboardingStatusCompleted, + Status: userdomain.StatusActive, + }) + repository.PutHostProfile(hostdomain.HostProfile{UserID: 91001, RegionID: 101, Status: hostdomain.HostStatusActive}) + if _, err := repository.RawDB().ExecContext(ctx, ` + INSERT INTO auth_sessions ( + app_code, session_id, user_id, refresh_token_hash, device_id, expires_at_ms, + revoked_at_ms, revoked_reason, revoked_request_id, revoked_by, created_at_ms, updated_at_ms + ) + VALUES (?, ?, ?, ?, ?, ?, NULL, '', '', '', ?, ?) + `, appcode.Default, "sess_country_admin", int64(91001), "refresh_hash_country_admin", "device_country_admin", int64(1_700_100_000_000), int64(1), int64(1)); err != nil { + t.Fatalf("seed auth session failed: %v", err) + } + svc := userservice.New(repository, + userservice.WithCountryRegionRepository(repository), + userservice.WithClock(func() time.Time { return time.UnixMilli(1_700_000_123_000).UTC() }), + ) + + updated, nextAllowedAt, err := svc.AdminChangeUserCountry(ctx, 91001, "TH", "req-admin-country") + if err != nil { + t.Fatalf("AdminChangeUserCountry failed: %v", err) + } + if nextAllowedAt != 0 || updated.Country != "TH" || updated.RegionID != 202 { + t.Fatalf("admin country result mismatch: user=%+v next=%d", updated, nextAllowedAt) + } + + var payloadJSON string + if err := repository.RawDB().QueryRowContext(ctx, ` + SELECT CAST(payload_json AS CHAR) + FROM user_outbox + WHERE app_code = ? AND event_type = 'UserRegionChanged' AND aggregate_id = ? + `, appcode.Default, int64(91001)).Scan(&payloadJSON); err != nil { + t.Fatalf("query UserRegionChanged outbox failed: %v", err) + } + var payload map[string]any + if err := json.Unmarshal([]byte(payloadJSON), &payload); err != nil { + t.Fatalf("decode outbox payload failed: %v", err) + } + if payload["source"] != "admin" || int64(payload["old_region_id"].(float64)) != 101 || int64(payload["new_region_id"].(float64)) != 202 { + t.Fatalf("outbox payload mismatch: %v", payload) + } + var revokedAtMs int64 + var revokedReason string + var revokedRequestID string + var revokedBy string + if err := repository.RawDB().QueryRowContext(ctx, ` + SELECT revoked_at_ms, revoked_reason, revoked_request_id, revoked_by + FROM auth_sessions + WHERE app_code = ? AND session_id = ? + `, appcode.Default, "sess_country_admin").Scan(&revokedAtMs, &revokedReason, &revokedRequestID, &revokedBy); err != nil { + t.Fatalf("query revoked auth session failed: %v", err) + } + if revokedAtMs != 1_700_000_123_000 || revokedReason != "USER_COUNTRY_CHANGED" || revokedRequestID != "req-admin-country" || revokedBy != "country_change" { + t.Fatalf("country change session revoke mismatch: at=%d reason=%q request=%q by=%q", revokedAtMs, revokedReason, revokedRequestID, revokedBy) + } +} diff --git a/services/user-service/internal/service/user/moderation.go b/services/user-service/internal/service/user/moderation.go index 534b7b4a..6376ab9e 100644 --- a/services/user-service/internal/service/user/moderation.go +++ b/services/user-service/internal/service/user/moderation.go @@ -12,7 +12,10 @@ import ( userdomain "hyapp/services/user-service/internal/domain/user" ) -const userStatusRevokeReason = "USER_STATUS_CHANGED" +const ( + userStatusRevokeReason = "USER_STATUS_CHANGED" + countryChangeRevokeReason = "USER_COUNTRY_CHANGED" +) const ( OperatorTypeAdmin = "admin" @@ -90,13 +93,13 @@ func (s *Service) SetUserStatus(ctx context.Context, command UserStatusCommand) return result, nil } - result.AccessTokenRevoked, result.AccessTokenError = s.writeSessionDenylist(ctx, command, persisted.RevokedSessionIDs) + result.AccessTokenRevoked, result.AccessTokenError = s.writeSessionDenylist(ctx, command, persisted.RevokedSessionIDs, userStatusRevokeReason) result.IMKicked, result.IMKickError = s.kickIMLogin(ctx, command.TargetUserID) result.RoomEvicted, result.RoomID, result.RTCKicked, result.RTCKickError, result.RoomEvictError = s.evictCurrentRoom(ctx, command) return result, nil } -func (s *Service) writeSessionDenylist(ctx context.Context, command UserStatusCommand, sessionIDs []string) (bool, string) { +func (s *Service) writeSessionDenylist(ctx context.Context, command UserStatusCommand, sessionIDs []string, reason string) (bool, string) { if len(sessionIDs) == 0 { return true, "" } @@ -107,6 +110,10 @@ func (s *Service) writeSessionDenylist(ctx context.Context, command UserStatusCo if ttl <= 0 { ttl = time.Hour } + reason = strings.TrimSpace(reason) + if reason == "" { + reason = userStatusRevokeReason + } failed := 0 var firstError string for _, sessionID := range sessionIDs { @@ -114,8 +121,8 @@ func (s *Service) writeSessionDenylist(ctx context.Context, command UserStatusCo if sessionID == "" { continue } - // 单个 Redis 写入失败不能回滚已经提交的封禁事实;调用方可通过重复封禁补偿剩余 session。 - if err := s.sessionDenylist.SetRevokedSession(ctx, command.AppCode, sessionID, userStatusRevokeReason, ttl); err != nil { + // 单个 Redis 写入失败不能回滚已经提交的封禁事实;调用方可通过重复封禁或重新修改国家补偿剩余 session。 + if err := s.sessionDenylist.SetRevokedSession(ctx, command.AppCode, sessionID, reason, ttl); err != nil { failed++ if firstError == "" { firstError = err.Error() diff --git a/services/user-service/internal/service/user/moderation_test.go b/services/user-service/internal/service/user/moderation_test.go index 43db0e73..8bda14dc 100644 --- a/services/user-service/internal/service/user/moderation_test.go +++ b/services/user-service/internal/service/user/moderation_test.go @@ -102,10 +102,13 @@ func TestSetUserStatusSurfacesAccessDenylistError(t *testing.T) { } type fakeModerationRepository struct { - user userdomain.User - sessionIDs []string - lastCommand UserStatusCommand - lastReport userdomain.Report + user userdomain.User + sessionIDs []string + countrySessionIDs []string + lastCommand UserStatusCommand + lastCountryCommand userdomain.CountryChangeCommand + countryChangeCalls int + lastReport userdomain.Report } func (r *fakeModerationRepository) SetUserStatus(_ context.Context, command UserStatusCommand) (UserStatusPersistenceResult, error) { @@ -191,17 +194,24 @@ func (r *fakeModerationRepository) CompleteOnboarding(context.Context, userdomai return r.user, nil } -func (r *fakeModerationRepository) ChangeUserCountry(context.Context, userdomain.CountryChangeCommand) (userdomain.User, int64, error) { - return r.user, 0, nil +func (r *fakeModerationRepository) ChangeUserCountry(_ context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, []string, error) { + r.lastCountryCommand = command + r.countryChangeCalls++ + r.user.Country = command.NewCountry + r.user.RegionID = command.NewRegionID + r.user.UpdatedAtMs = command.ChangedAtMs + return r.user, 0, append([]string{}, r.countrySessionIDs...), nil } type fakeSessionDenylist struct { sessions []string + reasons []string err error } -func (d *fakeSessionDenylist) SetRevokedSession(_ context.Context, _ string, sessionID string, _ string, _ time.Duration) error { +func (d *fakeSessionDenylist) SetRevokedSession(_ context.Context, _ string, sessionID string, reason string, _ time.Duration) error { d.sessions = append(d.sessions, sessionID) + d.reasons = append(d.reasons, reason) return d.err } diff --git a/services/user-service/internal/service/user/profile.go b/services/user-service/internal/service/user/profile.go index f0d73296..e227892b 100644 --- a/services/user-service/internal/service/user/profile.go +++ b/services/user-service/internal/service/user/profile.go @@ -6,6 +6,7 @@ import ( "hyapp/pkg/appcode" "hyapp/pkg/xerr" + hostdomain "hyapp/services/user-service/internal/domain/host" invitedomain "hyapp/services/user-service/internal/domain/invite" userdomain "hyapp/services/user-service/internal/domain/user" ) @@ -153,9 +154,8 @@ func (s *Service) CompleteOnboarding(ctx context.Context, userID int64, username }) } -// ChangeUserCountry 修改用户国家并写审计日志;同一用户滚动 30 天内只能成功修改一次。 +// ChangeUserCountry 是 App 用户自助修改国家入口;普通用户不再受冷却期限制,业务身份用户必须走后台治理流程。 func (s *Service) ChangeUserCountry(ctx context.Context, userID int64, country string, requestID string) (userdomain.User, int64, error) { - country = userdomain.NormalizeCountryCode(country) if userID <= 0 { return userdomain.User{}, 0, xerr.New(xerr.InvalidArgument, "user_id is required") } @@ -166,39 +166,130 @@ func (s *Service) ChangeUserCountry(ctx context.Context, userID int64, country s // 未完成 onboarding 时拒绝在这里改国家,避免首次国家选择写入变更日志并消耗冷却期。 return userdomain.User{}, 0, err } - if country == "" { - return userdomain.User{}, 0, xerr.New(xerr.InvalidArgument, "country is required") + if s.roleSummaryRepository != nil { + summary, err := s.roleSummaryRepository.GetUserRoleSummary(ctx, userID) + if err != nil { + return userdomain.User{}, 0, err + } + if role := blockedCountryChangeRole(summary); role != "" { + // App 自助入口不能改变已有经营身份的区域归属,否则房间、组织和币商读模型会在用户侧无审计地漂移。 + return userdomain.User{}, 0, xerr.New(xerr.PermissionDenied, "you have "+role+" id, not allow modify country") + } } - if !userdomain.ValidCountryCode(country) { - return userdomain.User{}, 0, xerr.New(xerr.InvalidArgument, "country must use 2 to 3 uppercase letters") - } - if s.countryRegionRepository == nil { - return userdomain.User{}, 0, xerr.New(xerr.Unavailable, "country repository is not configured") - } - resolvedCountry, ok, err := s.countryRegionRepository.ResolveEnabledCountryByCode(ctx, country) + resolvedCountry, regionID, err := s.resolveCountryRegionForChange(ctx, country) if err != nil { return userdomain.User{}, 0, err } - if !ok { - return userdomain.User{}, 0, xerr.New(xerr.InvalidArgument, "country is not supported") - } - var regionID int64 - if region, ok, err := s.countryRegionRepository.ResolveActiveRegionByCountry(ctx, resolvedCountry.CountryCode); err != nil { - return userdomain.User{}, 0, err - } else if ok { - regionID = region.RegionID - } nowMs := s.now().UnixMilli() - return s.userRepository.ChangeUserCountry(ctx, userdomain.CountryChangeCommand{ + command := userdomain.CountryChangeCommand{ AppCode: appcode.FromContext(ctx), UserID: userID, NewCountry: resolvedCountry.CountryCode, NewRegionID: regionID, + Source: "app", RequestID: strings.TrimSpace(requestID), ChangedAtMs: nowMs, - CooldownMs: s.countryChangeCooldown.Milliseconds(), - }) + CooldownMs: 0, + } + updated, nextAllowedAt, revokedSessionIDs, err := s.userRepository.ChangeUserCountry(ctx, command) + if err != nil { + return userdomain.User{}, nextAllowedAt, err + } + s.writeCountryChangeSessionDenylist(ctx, command, revokedSessionIDs) + return updated, nextAllowedAt, nil +} + +// AdminChangeUserCountry 是后台修改用户国家入口;后台操作已在 admin-server 做 RBAC 和审计,这里只保证用户主数据和 outbox 原子一致。 +func (s *Service) AdminChangeUserCountry(ctx context.Context, targetUserID int64, country string, requestID string) (userdomain.User, int64, error) { + if targetUserID <= 0 { + return userdomain.User{}, 0, xerr.New(xerr.InvalidArgument, "target_user_id is required") + } + if s.userRepository == nil { + return userdomain.User{}, 0, xerr.New(xerr.Unavailable, "user repository is not configured") + } + resolvedCountry, regionID, err := s.resolveCountryRegionForChange(ctx, country) + if err != nil { + return userdomain.User{}, 0, err + } + + nowMs := s.now().UnixMilli() + command := userdomain.CountryChangeCommand{ + AppCode: appcode.FromContext(ctx), + UserID: targetUserID, + NewCountry: resolvedCountry.CountryCode, + NewRegionID: regionID, + Source: "admin", + RequestID: strings.TrimSpace(requestID), + ChangedAtMs: nowMs, + CooldownMs: 0, + } + updated, nextAllowedAt, revokedSessionIDs, err := s.userRepository.ChangeUserCountry(ctx, command) + if err != nil { + return userdomain.User{}, nextAllowedAt, err + } + s.writeCountryChangeSessionDenylist(ctx, command, revokedSessionIDs) + return updated, nextAllowedAt, nil +} + +func (s *Service) writeCountryChangeSessionDenylist(ctx context.Context, command userdomain.CountryChangeCommand, sessionIDs []string) { + if len(sessionIDs) == 0 || s.sessionDenylist == nil { + // MySQL auth_sessions 是登录态的持久事实;Redis denylist 只用于让已经签出的 access token 在过期前更快失效。 + return + } + _, _ = s.writeSessionDenylist(ctx, UserStatusCommand{ + AppCode: command.AppCode, + TargetUserID: command.UserID, + RequestID: command.RequestID, + NowMs: command.ChangedAtMs, + }, sessionIDs, countryChangeRevokeReason) +} + +func (s *Service) resolveCountryRegionForChange(ctx context.Context, country string) (userdomain.Country, int64, error) { + country = userdomain.NormalizeCountryCode(country) + if country == "" { + return userdomain.Country{}, 0, xerr.New(xerr.InvalidArgument, "country is required") + } + if !userdomain.ValidCountryCode(country) { + return userdomain.Country{}, 0, xerr.New(xerr.InvalidArgument, "country must use 2 to 3 uppercase letters") + } + if s.countryRegionRepository == nil { + return userdomain.Country{}, 0, xerr.New(xerr.Unavailable, "country repository is not configured") + } + resolvedCountry, ok, err := s.countryRegionRepository.ResolveEnabledCountryByCode(ctx, country) + if err != nil { + return userdomain.Country{}, 0, err + } + if !ok { + return userdomain.Country{}, 0, xerr.New(xerr.InvalidArgument, "country is not supported") + } + var regionID int64 + if region, ok, err := s.countryRegionRepository.ResolveActiveRegionByCountry(ctx, resolvedCountry.CountryCode); err != nil { + return userdomain.Country{}, 0, err + } else if ok { + regionID = region.RegionID + } + + return resolvedCountry, regionID, nil +} + +func blockedCountryChangeRole(summary hostdomain.UserRoleSummary) string { + switch { + case summary.IsHost: + return "host" + case summary.IsAgency: + return "agency" + case summary.IsBDLeader: + return "bd leader" + case summary.IsBD: + return "bd" + case summary.IsManager: + return "manager" + case summary.IsCoinSeller: + return "coin seller" + default: + return "" + } } func (s *Service) requireCompletedProfile(ctx context.Context, userID int64) error { diff --git a/services/user-service/internal/service/user/profile_test.go b/services/user-service/internal/service/user/profile_test.go new file mode 100644 index 00000000..5a5e282b --- /dev/null +++ b/services/user-service/internal/service/user/profile_test.go @@ -0,0 +1,129 @@ +package user + +import ( + "context" + "strings" + "testing" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + hostdomain "hyapp/services/user-service/internal/domain/host" + userdomain "hyapp/services/user-service/internal/domain/user" +) + +type fakeCountryRegionRepository struct { + countries map[string]userdomain.Country + regions map[string]userdomain.Region +} + +func (r fakeCountryRegionRepository) ResolveEnabledCountryByCode(_ context.Context, countryCode string) (userdomain.Country, bool, error) { + country, ok := r.countries[countryCode] + return country, ok, nil +} + +func (r fakeCountryRegionRepository) ListRegistrationCountries(context.Context) ([]userdomain.Country, error) { + return nil, nil +} + +func (r fakeCountryRegionRepository) ResolveActiveRegionByCountry(_ context.Context, countryCode string) (userdomain.Region, bool, error) { + region, ok := r.regions[countryCode] + return region, ok, nil +} + +type fakeRoleSummaryRepository struct { + summary hostdomain.UserRoleSummary +} + +func (r fakeRoleSummaryRepository) GetUserRoleSummary(context.Context, int64) (hostdomain.UserRoleSummary, error) { + return r.summary, nil +} + +func TestChangeUserCountryAllowsNormalUserWithoutCooldown(t *testing.T) { + ctx := appcode.WithContext(context.Background(), "lalu") + repository := &fakeModerationRepository{user: userdomain.User{ + AppCode: "lalu", + UserID: 10001, + Country: "US", + RegionID: 1, + ProfileCompleted: true, + }, countrySessionIDs: []string{"country_sess"}} + denylist := &fakeSessionDenylist{} + svc := New(repository, + WithCountryRegionRepository(fakeCountryRegionRepository{ + countries: map[string]userdomain.Country{ + "ID": {CountryCode: "ID", Enabled: true}, + "TH": {CountryCode: "TH", Enabled: true}, + }, + regions: map[string]userdomain.Region{ + "ID": {RegionID: 2, Status: userdomain.RegionStatusActive}, + "TH": {RegionID: 3, Status: userdomain.RegionStatusActive}, + }, + }), + WithRoleSummaryRepository(fakeRoleSummaryRepository{}), + WithSessionDenylist(denylist, time.Minute), + WithClock(func() time.Time { return time.UnixMilli(1_700_000_000_000).UTC() }), + ) + + if _, nextAllowedAt, err := svc.ChangeUserCountry(ctx, 10001, "ID", "req-id"); err != nil || nextAllowedAt != 0 { + t.Fatalf("first normal country change failed: next=%d err=%v", nextAllowedAt, err) + } + if repository.lastCountryCommand.CooldownMs != 0 || repository.lastCountryCommand.Source != "app" || repository.lastCountryCommand.NewRegionID != 2 { + t.Fatalf("app change command mismatch: %+v", repository.lastCountryCommand) + } + if _, nextAllowedAt, err := svc.ChangeUserCountry(ctx, 10001, "TH", "req-th"); err != nil || nextAllowedAt != 0 { + t.Fatalf("second normal country change must not hit cooldown: next=%d err=%v", nextAllowedAt, err) + } + if repository.countryChangeCalls != 2 { + t.Fatalf("repository must receive both app changes, calls=%d", repository.countryChangeCalls) + } + if len(denylist.sessions) != 2 || denylist.sessions[0] != "country_sess" || denylist.reasons[0] != countryChangeRevokeReason { + t.Fatalf("country change must write revoked sessions to denylist: sessions=%+v reasons=%+v", denylist.sessions, denylist.reasons) + } +} + +func TestChangeUserCountryRejectsProtectedRoles(t *testing.T) { + cases := []struct { + name string + summary hostdomain.UserRoleSummary + role string + }{ + {name: "host", summary: hostdomain.UserRoleSummary{IsHost: true}, role: "host"}, + {name: "agency", summary: hostdomain.UserRoleSummary{IsAgency: true}, role: "agency"}, + {name: "bd leader", summary: hostdomain.UserRoleSummary{IsBDLeader: true, IsBD: true}, role: "bd leader"}, + {name: "bd", summary: hostdomain.UserRoleSummary{IsBD: true}, role: "bd"}, + {name: "manager", summary: hostdomain.UserRoleSummary{IsManager: true}, role: "manager"}, + {name: "coin seller", summary: hostdomain.UserRoleSummary{IsCoinSeller: true}, role: "coin seller"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + repository := &fakeModerationRepository{user: userdomain.User{ + AppCode: "lalu", + UserID: 10001, + Country: "US", + RegionID: 1, + ProfileCompleted: true, + }} + svc := New(repository, + WithCountryRegionRepository(fakeCountryRegionRepository{ + countries: map[string]userdomain.Country{"ID": {CountryCode: "ID", Enabled: true}}, + regions: map[string]userdomain.Region{"ID": {RegionID: 2, Status: userdomain.RegionStatusActive}}, + }), + WithRoleSummaryRepository(fakeRoleSummaryRepository{summary: tc.summary}), + ) + + _, _, err := svc.ChangeUserCountry(appcode.WithContext(context.Background(), "lalu"), 10001, "ID", "req-protected") + if xerr.CodeOf(err) != xerr.PermissionDenied { + t.Fatalf("protected role must be permission denied: role=%s err=%v", tc.role, err) + } + want := "you have " + tc.role + " id, not allow modify country" + if !strings.Contains(err.Error(), want) { + t.Fatalf("protected role message mismatch: got=%q want contains=%q", err.Error(), want) + } + if repository.countryChangeCalls != 0 { + t.Fatalf("protected role must not update repository, calls=%d", repository.countryChangeCalls) + } + }) + } +} diff --git a/services/user-service/internal/service/user/service.go b/services/user-service/internal/service/user/service.go index 9f9ec2c4..ebc62724 100644 --- a/services/user-service/internal/service/user/service.go +++ b/services/user-service/internal/service/user/service.go @@ -7,6 +7,7 @@ import ( roomv1 "hyapp.local/api/proto/room/v1" "hyapp/pkg/idgen" + hostdomain "hyapp/services/user-service/internal/domain/host" userdomain "hyapp/services/user-service/internal/domain/user" ) @@ -51,8 +52,8 @@ type UserRepository interface { UpdateUserProfile(ctx context.Context, command userdomain.ProfileUpdateCommand) (userdomain.User, error) // CompleteOnboarding 原子写注册页必填资料并标记 profile_completed。 CompleteOnboarding(ctx context.Context, command userdomain.CompleteOnboardingCommand) (userdomain.User, error) - // ChangeUserCountry 原子修改用户国家并写变更日志。 - ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, error) + // ChangeUserCountry 原子修改用户国家、写变更日志,并返回需要立即失效的 auth session。 + ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, []string, error) } // AppRegistryRepository 负责把客户端包名解析成内部 app_code。 @@ -93,6 +94,11 @@ type RegionRebuildRepository interface { ProcessNextRegionRebuildTask(ctx context.Context, workerID string, nowMs int64, lockTTL time.Duration, batchSize int) (userdomain.RegionRebuildProcessResult, error) } +// RoleSummaryRepository 提供用户当前业务身份摘要,App 自助改国家必须先基于该事实做权限截断。 +type RoleSummaryRepository interface { + GetUserRoleSummary(ctx context.Context, userID int64) (hostdomain.UserRoleSummary, error) +} + // IdentityRepository 隔离 display_user_id 的归属、解析、变更和靓号租约。 // 用户 service 通过该接口表达短号用例,不直接感知 MySQL 的 identity/change_log/lease 表布局。 type IdentityRepository interface { @@ -169,6 +175,8 @@ type Service struct { regionAdminRepository RegionAdminRepository // regionRebuildRepository 持有历史用户区域快照重算能力。 regionRebuildRepository RegionRebuildRepository + // roleSummaryRepository 持有用户当前业务身份摘要,避免 App 自助改国家绕过 host/BD/币商等身份边界。 + roleSummaryRepository RoleSummaryRepository // deviceRepository 持有设备 push token 绑定能力。 deviceRepository DeviceRepository // moderationRepository 持有用户状态和 session 吊销事务能力。 @@ -305,6 +313,15 @@ func WithRegionRebuildRepository(repository RegionRebuildRepository) Option { } } +// WithRoleSummaryRepository 注入角色摘要 repository。 +func WithRoleSummaryRepository(repository RoleSummaryRepository) Option { + return func(s *Service) { + if repository != nil { + s.roleSummaryRepository = repository + } + } +} + // WithDeviceRepository 注入设备 push token repository。 func WithDeviceRepository(repository DeviceRepository) Option { return func(s *Service) { diff --git a/services/user-service/internal/storage/mysql/host/admin.go b/services/user-service/internal/storage/mysql/host/admin.go index 54813f18..3c1e5003 100644 --- a/services/user-service/internal/storage/mysql/host/admin.go +++ b/services/user-service/internal/storage/mysql/host/admin.go @@ -2,7 +2,9 @@ package host import ( "context" + "fmt" + "hyapp/pkg/appcode" "hyapp/pkg/xerr" hostdomain "hyapp/services/user-service/internal/domain/host" hostservice "hyapp/services/user-service/internal/service/host" @@ -25,11 +27,11 @@ func (r *Repository) CreateBDLeader(ctx context.Context, command hostservice.Cre return queryBDProfile(ctx, tx, "WHERE user_id = ?", existing.ResultID) } - if err := requireActiveRegion(ctx, tx, command.RegionID); err != nil { + regionID, err := r.userRegion(ctx, tx, command.TargetUserID, "FOR UPDATE") + if err != nil { return hostdomain.BDProfile{}, err } - currentRegionID, err := r.userRegion(ctx, tx, command.TargetUserID, "FOR UPDATE") - if err != nil { + if err := requireActiveRegion(ctx, tx, regionID); err != nil { return hostdomain.BDProfile{}, err } if _, ok, err := queryBDProfileByUserMaybe(ctx, tx, command.TargetUserID, true); err != nil { @@ -37,16 +39,11 @@ func (r *Repository) CreateBDLeader(ctx context.Context, command hostservice.Cre } else if ok { return hostdomain.BDProfile{}, xerr.New(xerr.Conflict, "target already has bd profile") } - if currentRegionID != command.RegionID { - if err := updateUserRegion(ctx, tx, command.TargetUserID, command.RegionID, command.NowMs); err != nil { - return hostdomain.BDProfile{}, err - } - } profile := hostdomain.BDProfile{ UserID: command.TargetUserID, Role: hostdomain.BDRoleLeader, - RegionID: command.RegionID, + RegionID: regionID, Status: hostdomain.BDStatusActive, CreatedByUserID: command.AdminUserID, CreatedAtMs: command.NowMs, @@ -303,14 +300,9 @@ func (r *Repository) CreateAgency(ctx context.Context, command hostservice.Creat } else if ok { return hostdomain.CreateAgencyResult{}, xerr.New(xerr.Conflict, "owner already has active agency membership") } - if _, ok, err := queryHostProfileByUserMaybe(ctx, tx, command.OwnerUserID, true); err != nil { - return hostdomain.CreateAgencyResult{}, err - } else if ok { - // 后台直接创建 Agency 会同时创建 owner 的 Host 身份;已存在 Host 身份时拒绝,避免后台把已有主播静默改挂到新 Agency。 - return hostdomain.CreateAgencyResult{}, xerr.New(xerr.Conflict, "owner already has host profile") - } - agency := hostdomain.Agency{AgencyID: command.AgencyID, OwnerUserID: command.OwnerUserID, RegionID: regionID, ParentBDUserID: command.ParentBDUserID, Name: command.Name, Status: hostdomain.AgencyStatusActive, JoinEnabled: command.JoinEnabled, MaxHosts: command.MaxHosts, CreatedByUserID: command.AdminUserID, CreatedAtMs: command.NowMs, UpdatedAtMs: command.NowMs} + // max_hosts 是历史兼容字段,当前业务不再限制主播数量,新建 Agency 固化为 0。 + agency := hostdomain.Agency{AgencyID: command.AgencyID, OwnerUserID: command.OwnerUserID, RegionID: regionID, ParentBDUserID: command.ParentBDUserID, Name: command.Name, Status: hostdomain.AgencyStatusActive, JoinEnabled: command.JoinEnabled, MaxHosts: 0, CreatedByUserID: command.AdminUserID, CreatedAtMs: command.NowMs, UpdatedAtMs: command.NowMs} if err := insertAgency(ctx, tx, agency); err != nil { return hostdomain.CreateAgencyResult{}, mapHostDuplicateError(err) } @@ -351,6 +343,87 @@ func (r *Repository) CloseAgency(ctx context.Context, command hostservice.CloseA }) } +// DeleteAgency 删除 Agency 身份;历史 Agency、membership 和 host_profile 都保留,只解除当前有效归属。 +func (r *Repository) DeleteAgency(ctx context.Context, command hostservice.DeleteAgencyCommand) (hostdomain.Agency, error) { + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return hostdomain.Agency{}, err + } + defer tx.Rollback() + + if existing, ok, err := commandResult(ctx, tx, command.CommandID); err != nil { + return hostdomain.Agency{}, err + } else if ok { + if err := requireCommandResult(existing, hostdomain.CommandTypeDeleteAgency, hostdomain.ResultTypeAgency); err != nil { + return hostdomain.Agency{}, err + } + return queryAgency(ctx, tx, "WHERE agency_id = ?", existing.ResultID) + } + + agency, err := queryAgency(ctx, tx, "WHERE agency_id = ? FOR UPDATE", command.AgencyID) + if err != nil { + return hostdomain.Agency{}, err + } + if agency.Status == hostdomain.AgencyStatusDeleted { + return hostdomain.Agency{}, xerr.New(xerr.Conflict, "agency already deleted") + } + + activeMemberships, err := queryAgencyMemberships(ctx, tx, fmt.Sprintf(` + SELECT %s + FROM agency_memberships + WHERE app_code = ? AND agency_id = ? AND status = ? + FOR UPDATE + `, agencyMembershipColumns), appcode.FromContext(ctx), agency.AgencyID, hostdomain.MembershipStatusActive) + if err != nil { + return hostdomain.Agency{}, err + } + + endReason := command.Reason + if endReason == "" { + endReason = "delete agency" + } + for _, membership := range activeMemberships { + hostProfile, err := queryHostProfile(ctx, tx, "WHERE user_id = ? FOR UPDATE", membership.HostUserID) + if err != nil { + return hostdomain.Agency{}, err + } + membership.Status = hostdomain.MembershipStatusEnded + membership.EndedAtMs = command.NowMs + membership.EndedByUserID = command.AdminUserID + membership.EndedReason = endReason + membership.UpdatedAtMs = command.NowMs + if err := endAgencyMembership(ctx, tx, membership); err != nil { + return hostdomain.Agency{}, err + } + if hostProfile.CurrentMembershipID == membership.MembershipID { + // 删除 Agency 只释放当前归属指针,主播身份、来源和首次成为主播时间都保留。 + hostProfile.CurrentAgencyID = 0 + hostProfile.CurrentMembershipID = 0 + hostProfile.UpdatedAtMs = command.NowMs + if err := updateHostCurrentMembership(ctx, tx, hostProfile); err != nil { + return hostdomain.Agency{}, err + } + } + } + + agency.Status = hostdomain.AgencyStatusDeleted + agency.JoinEnabled = false + agency.UpdatedAtMs = command.NowMs + if err := updateAgencyAdminState(ctx, tx, agency); err != nil { + return hostdomain.Agency{}, err + } + if err := insertCommandResult(ctx, tx, hostdomain.CommandResult{CommandID: command.CommandID, CommandType: hostdomain.CommandTypeDeleteAgency, ResultType: hostdomain.ResultTypeAgency, ResultID: agency.AgencyID, CreatedAtMs: command.NowMs}); err != nil { + return hostdomain.Agency{}, mapHostDuplicateError(err) + } + if err := insertHostOutbox(ctx, tx, command.EventID, "AgencyDeleted", "agency", agency.AgencyID, command.NowMs); err != nil { + return hostdomain.Agency{}, err + } + if err := tx.Commit(); err != nil { + return hostdomain.Agency{}, err + } + return agency, nil +} + // SetAgencyJoinEnabled 调整 Agency 入会开关。 func (r *Repository) SetAgencyJoinEnabled(ctx context.Context, command hostservice.SetAgencyJoinEnabledCommand) (hostdomain.Agency, error) { return r.updateAgencyAdmin(ctx, command.CommandID, hostdomain.CommandTypeSetAgencyJoinEnabled, command.AgencyID, command.EventID, command.NowMs, func(agency hostdomain.Agency) hostdomain.Agency { diff --git a/services/user-service/internal/storage/mysql/host/invitations.go b/services/user-service/internal/storage/mysql/host/invitations.go index e6b2c604..b614d3a4 100644 --- a/services/user-service/internal/storage/mysql/host/invitations.go +++ b/services/user-service/internal/storage/mysql/host/invitations.go @@ -45,12 +45,11 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit if targetRegionID != inviter.RegionID { return hostdomain.RoleInvitation{}, xerr.New(xerr.PermissionDenied, "target region does not match inviter region") } - // Agency 拥有者在本阶段也会被建成 host_profile 和拥有者成员关系, - // 因此已是有效 Host 的用户不能再走“成为 Agency”邀请。 - if _, ok, err := queryHostProfileMaybe(ctx, tx, command.TargetUserID, true); err != nil { + // Agency 拥有者必须没有当前有效 Agency 归属;已有 Host 身份但未归属 Agency 时可以复用身份。 + if _, ok, err := queryActiveMembershipByHost(ctx, tx, command.TargetUserID, true); err != nil { return hostdomain.RoleInvitation{}, err } else if ok { - return hostdomain.RoleInvitation{}, xerr.New(xerr.Conflict, "active host cannot become agency") + return hostdomain.RoleInvitation{}, xerr.New(xerr.Conflict, "target already has active agency membership") } // 一个用户只能拥有一个有效 Agency;这里先拦截,最终仍依赖唯一索引兜底并发。 if _, ok, err := queryActiveAgencyByOwner(ctx, tx, command.TargetUserID, true); err != nil { @@ -88,7 +87,7 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit return hostdomain.RoleInvitation{}, mapHostDuplicateError(err) } result := hostdomain.ProcessRoleInvitationResult{Invitation: invitation} - created, err := r.acceptAgencyInvitation(ctx, tx, hostservice.ProcessRoleInvitationCommand{ + hostProfileCreated, err := r.acceptAgencyInvitation(ctx, tx, hostservice.ProcessRoleInvitationCommand{ CommandID: command.CommandID, ActorUserID: command.InviterUserID, InvitationID: command.InvitationID, @@ -102,16 +101,16 @@ func (r *Repository) InviteAgency(ctx context.Context, command hostservice.Invit if err != nil { return hostdomain.RoleInvitation{}, err } - if created { + if hostProfileCreated { if err := insertHostOutbox(ctx, tx, command.EventID, "HostCreated", "host_profile", invitation.TargetUserID, command.NowMs); err != nil { return hostdomain.RoleInvitation{}, err } - if err := insertHostOutbox(ctx, tx, command.EventID+1, "AgencyCreated", "agency", command.AgencyID, command.NowMs); err != nil { - return hostdomain.RoleInvitation{}, err - } - if err := insertHostOutbox(ctx, tx, command.EventID+2, "AgencyMembershipChanged", "agency_membership", command.MembershipID, command.NowMs); err != nil { - return hostdomain.RoleInvitation{}, err - } + } + if err := insertHostOutbox(ctx, tx, command.EventID+1, "AgencyCreated", "agency", command.AgencyID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err + } + if err := insertHostOutbox(ctx, tx, command.EventID+2, "AgencyMembershipChanged", "agency_membership", command.MembershipID, command.NowMs); err != nil { + return hostdomain.RoleInvitation{}, err } if err := insertCommandResult(ctx, tx, hostdomain.CommandResult{ CommandID: command.CommandID, @@ -274,22 +273,22 @@ func (r *Repository) ProcessRoleInvitation(ctx context.Context, command hostserv invitation.Status = hostdomain.InvitationStatusAccepted if invitation.InvitationType == hostdomain.InvitationTypeAgency { // Agency 邀请的接受会一次性创建 Agency 拥有者身份、Agency 和拥有者成员关系。 - created, err := r.acceptAgencyInvitation(ctx, tx, command, &invitation, &result) + hostProfileCreated, err := r.acceptAgencyInvitation(ctx, tx, command, &invitation, &result) if err != nil { return hostdomain.ProcessRoleInvitationResult{}, err } - if created { - // 事件 ID 在业务层预分配;这里按固定偏移写多条事件箱记录, - // 让同一个接受事务中的派生事件保持可追踪顺序。 + // 事件 ID 在业务层预分配;这里按固定偏移写多条事件箱记录, + // 让同一个接受事务中的派生事件保持可追踪顺序。 + if hostProfileCreated { if err := insertHostOutbox(ctx, tx, command.EventID, "HostCreated", "host_profile", invitation.TargetUserID, command.NowMs); err != nil { return hostdomain.ProcessRoleInvitationResult{}, err } - if err := insertHostOutbox(ctx, tx, command.EventID+1, "AgencyCreated", "agency", command.AgencyID, command.NowMs); err != nil { - return hostdomain.ProcessRoleInvitationResult{}, err - } - if err := insertHostOutbox(ctx, tx, command.EventID+2, "AgencyMembershipChanged", "agency_membership", command.MembershipID, command.NowMs); err != nil { - return hostdomain.ProcessRoleInvitationResult{}, err - } + } + if err := insertHostOutbox(ctx, tx, command.EventID+1, "AgencyCreated", "agency", command.AgencyID, command.NowMs); err != nil { + return hostdomain.ProcessRoleInvitationResult{}, err + } + if err := insertHostOutbox(ctx, tx, command.EventID+2, "AgencyMembershipChanged", "agency_membership", command.MembershipID, command.NowMs); err != nil { + return hostdomain.ProcessRoleInvitationResult{}, err } } else if invitation.InvitationType == hostdomain.InvitationTypeBD { // BD 邀请的接受只创建 bd_profile;BD 不需要 host_profile。 @@ -333,11 +332,11 @@ func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, com if regionID != invitation.RegionID { return false, xerr.New(xerr.PermissionDenied, "target region no longer matches invitation") } - // 目标用户在邀请创建后可能已经通过申请成为 Host,接受时需要重新阻断。 - if _, ok, err := queryHostProfileMaybe(ctx, tx, invitation.TargetUserID, true); err != nil { + // 目标用户在邀请创建后可能已经加入其他 Agency;接受前必须再次阻断有效归属。 + if _, ok, err := queryActiveMembershipByHost(ctx, tx, invitation.TargetUserID, true); err != nil { return false, err } else if ok { - return false, xerr.New(xerr.Conflict, "active host cannot become agency") + return false, xerr.New(xerr.Conflict, "target already has active agency membership") } // 同一用户不能拥有多个有效 Agency;这里和唯一索引共同处理并发接受。 if _, ok, err := queryActiveAgencyByOwner(ctx, tx, invitation.TargetUserID, true); err != nil { @@ -349,13 +348,14 @@ func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, com // Agency、拥有者 host_profile、拥有者成员关系是同一业务事实的三张表投影, // 必须全部创建成功后邀请才能进入已接受状态。 agency := hostdomain.Agency{ - AgencyID: command.AgencyID, - OwnerUserID: invitation.TargetUserID, - RegionID: invitation.RegionID, - ParentBDUserID: invitation.ParentBDUserID, - Name: invitation.AgencyName, - Status: hostdomain.AgencyStatusActive, - JoinEnabled: true, + AgencyID: command.AgencyID, + OwnerUserID: invitation.TargetUserID, + RegionID: invitation.RegionID, + ParentBDUserID: invitation.ParentBDUserID, + Name: invitation.AgencyName, + Status: hostdomain.AgencyStatusActive, + JoinEnabled: true, + // max_hosts 是历史兼容字段,当前业务不再限制主播数量。 MaxHosts: 0, CreatedByUserID: invitation.InviterUserID, CreatedAtMs: command.NowMs, @@ -364,19 +364,9 @@ func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, com if err := insertAgency(ctx, tx, agency); err != nil { return false, mapHostDuplicateError(err) } - hostProfile := hostdomain.HostProfile{ - UserID: invitation.TargetUserID, - Status: hostdomain.HostStatusActive, - RegionID: invitation.RegionID, - CurrentAgencyID: agency.AgencyID, - CurrentMembershipID: command.MembershipID, - Source: hostdomain.HostSourceAgencyInvitation, - FirstBecameHostAtMs: command.NowMs, - CreatedAtMs: command.NowMs, - UpdatedAtMs: command.NowMs, - } - if err := insertHostProfile(ctx, tx, hostProfile); err != nil { - return false, mapHostDuplicateError(err) + hostProfile, hostProfileCreated, err := ensureHostProfileForMembership(ctx, tx, invitation.TargetUserID, invitation.RegionID, command.MembershipID, agency.AgencyID, hostdomain.HostSourceAgencyInvitation, command.NowMs) + if err != nil { + return false, err } membership := hostdomain.AgencyMembership{ MembershipID: command.MembershipID, @@ -395,7 +385,7 @@ func (r *Repository) acceptAgencyInvitation(ctx context.Context, tx *sql.Tx, com result.HostProfile = hostProfile result.Agency = agency result.Membership = membership - return true, nil + return hostProfileCreated, nil } func (r *Repository) acceptBDInvitation(ctx context.Context, tx *sql.Tx, command hostservice.ProcessRoleInvitationCommand, invitation *hostdomain.RoleInvitation, result *hostdomain.ProcessRoleInvitationResult) error { diff --git a/services/user-service/internal/storage/mysql/region/rebuild_tasks.go b/services/user-service/internal/storage/mysql/region/rebuild_tasks.go index c81c5e78..8335b89d 100644 --- a/services/user-service/internal/storage/mysql/region/rebuild_tasks.go +++ b/services/user-service/internal/storage/mysql/region/rebuild_tasks.go @@ -3,6 +3,8 @@ package region import ( "context" "database/sql" + "encoding/json" + "fmt" "strings" "time" @@ -72,11 +74,11 @@ func (r *Repository) processClaimedRegionRebuildTask(ctx context.Context, taskID return result, nil } - userIDs, err := selectRegionRebuildUserIDs(ctx, tx, task.AppCode, task.CountryCode, task.CursorUserID, batchSize) + users, err := selectRegionRebuildUsers(ctx, tx, task.AppCode, task.CountryCode, task.CursorUserID, batchSize) if err != nil { return result, err } - if len(userIDs) == 0 { + if len(users) == 0 { if err := finishRegionRebuildTask(ctx, tx, task.TaskID, workerID, userdomain.RegionRebuildTaskStatusCompleted, task.CursorUserID, "", nowMs); err != nil { return result, err } @@ -87,6 +89,16 @@ func (r *Repository) processClaimedRegionRebuildTask(ctx context.Context, taskID return result, nil } + userIDs := make([]int64, 0, len(users)) + for _, user := range users { + userIDs = append(userIDs, user.UserID) + if user.RegionID == task.TargetRegionID { + continue + } + if err := insertRegionRebuildUserRegionChangedOutbox(ctx, tx, task, user, nowMs); err != nil { + return result, err + } + } if err := updateUsersRegionByIDs(ctx, tx, task.AppCode, userIDs, task.TargetRegionID, nowMs); err != nil { return result, err } @@ -108,6 +120,11 @@ func (r *Repository) processClaimedRegionRebuildTask(ctx context.Context, taskID return result, nil } +type regionRebuildUser struct { + UserID int64 + RegionID int64 +} + func insertRebuildTask(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, countryCode string, targetRegionID int64, revision int64) error { _, err := tx.ExecContext(ctx, ` INSERT INTO user_region_rebuild_tasks (app_code, region_id, country_code, target_region_id, mapping_revision, status, cursor_user_id, created_at_ms, updated_at_ms) @@ -264,29 +281,57 @@ func newerRegionRebuildTaskExists(ctx context.Context, q queryer, appCode string return true, nil } -func selectRegionRebuildUserIDs(ctx context.Context, q queryer, appCode string, countryCode string, cursorUserID int64, batchSize int) ([]int64, error) { +func selectRegionRebuildUsers(ctx context.Context, q queryer, appCode string, countryCode string, cursorUserID int64, batchSize int) ([]regionRebuildUser, error) { rows, err := queryRows(ctx, q, ` - SELECT user_id + SELECT user_id, region_id FROM users WHERE app_code = ? AND country = ? AND user_id > ? ORDER BY user_id ASC LIMIT ? + FOR UPDATE `, appcode.Normalize(appCode), countryCode, cursorUserID, batchSize) if err != nil { return nil, err } defer rows.Close() - userIDs := make([]int64, 0, batchSize) + users := make([]regionRebuildUser, 0, batchSize) for rows.Next() { - var userID int64 - if err := rows.Scan(&userID); err != nil { + var user regionRebuildUser + var regionID sql.Null[int64] + if err := rows.Scan(&user.UserID, ®ionID); err != nil { return nil, err } - userIDs = append(userIDs, userID) + if regionID.Valid { + user.RegionID = regionID.V + } + users = append(users, user) } - return userIDs, rows.Err() + return users, rows.Err() +} + +func insertRegionRebuildUserRegionChangedOutbox(ctx context.Context, tx *sql.Tx, task userdomain.UserRegionRebuildTask, user regionRebuildUser, nowMs int64) error { + payload := map[string]any{ + "user_id": user.UserID, + "old_country": task.CountryCode, + "new_country": task.CountryCode, + "old_region_id": user.RegionID, + "new_region_id": task.TargetRegionID, + "source": "region_rebuild", + "request_id": fmt.Sprintf("region_rebuild_task:%d", task.TaskID), + "changed_at_ms": nowMs, + } + payloadJSON, err := json.Marshal(payload) + if err != nil { + return err + } + eventID := fmt.Sprintf("UserRegionChanged:region_rebuild:%d:%d:%d:%d", user.UserID, user.RegionID, task.TargetRegionID, nowMs) + _, err = tx.ExecContext(ctx, ` + INSERT IGNORE INTO user_outbox (app_code, event_id, event_type, aggregate_type, aggregate_id, status, payload_json, created_at_ms, updated_at_ms) + VALUES (?, ?, 'UserRegionChanged', 'user', ?, 'pending', ?, ?, ?) + `, appcode.Normalize(task.AppCode), eventID, user.UserID, string(payloadJSON), nowMs, nowMs) + return err } func updateUsersRegionByIDs(ctx context.Context, tx *sql.Tx, appCode string, userIDs []int64, targetRegionID int64, nowMs int64) error { diff --git a/services/user-service/internal/storage/mysql/region/rebuild_tasks_test.go b/services/user-service/internal/storage/mysql/region/rebuild_tasks_test.go new file mode 100644 index 00000000..9f44cb8f --- /dev/null +++ b/services/user-service/internal/storage/mysql/region/rebuild_tasks_test.go @@ -0,0 +1,85 @@ +package region_test + +import ( + "context" + "encoding/json" + "testing" + "time" + + "hyapp/pkg/appcode" + userdomain "hyapp/services/user-service/internal/domain/user" + "hyapp/services/user-service/internal/testutil/mysqltest" +) + +func TestProcessRegionRebuildTaskWritesUserRegionChangedOutbox(t *testing.T) { + ctx := appcode.WithContext(context.Background(), appcode.Default) + repository := mysqltest.NewRepository(t) + repository.PutCountry(userdomain.Country{CountryCode: "US", Enabled: true}) + repository.PutRegion(userdomain.Region{RegionID: 301, RegionCode: "OLD-US", Name: "Old US", Countries: []string{"US"}}) + repository.PutRegion(userdomain.Region{RegionID: 302, RegionCode: "NEW-US", Name: "New US", Countries: []string{"US"}}) + repository.PutUser(userdomain.User{ + UserID: 93001, + DefaultDisplayUserID: "93001", + CurrentDisplayUserID: "93001", + Country: "US", + RegionID: 301, + ProfileCompleted: true, + OnboardingStatus: userdomain.OnboardingStatusCompleted, + Status: userdomain.StatusActive, + }) + repository.PutUser(userdomain.User{ + UserID: 93002, + DefaultDisplayUserID: "93002", + CurrentDisplayUserID: "93002", + Country: "US", + RegionID: 302, + ProfileCompleted: true, + OnboardingStatus: userdomain.OnboardingStatusCompleted, + Status: userdomain.StatusActive, + }) + if _, err := repository.RawDB().ExecContext(ctx, `DELETE FROM user_region_rebuild_tasks WHERE app_code = ?`, appcode.Default); err != nil { + t.Fatalf("clear seeded rebuild tasks failed: %v", err) + } + nowMS := int64(1_700_000_456_000) + if _, err := repository.RawDB().ExecContext(ctx, ` + INSERT INTO user_region_rebuild_tasks (app_code, region_id, country_code, target_region_id, mapping_revision, status, cursor_user_id, created_at_ms, updated_at_ms) + VALUES (?, ?, 'US', ?, ?, ?, 0, ?, ?) + `, appcode.Default, int64(302), int64(302), nowMS, userdomain.RegionRebuildTaskStatusPending, nowMS, nowMS); err != nil { + t.Fatalf("insert rebuild task failed: %v", err) + } + + result, err := repository.ProcessNextRegionRebuildTask(ctx, "region-test-worker", nowMS+1, time.Minute, 10) + if err != nil { + t.Fatalf("ProcessNextRegionRebuildTask failed: %v", err) + } + if result.ProcessedUsers != 2 || result.Status != userdomain.RegionRebuildTaskStatusCompleted { + t.Fatalf("rebuild result mismatch: %+v", result) + } + + var changedRegionID int64 + if err := repository.RawDB().QueryRowContext(ctx, `SELECT COALESCE(region_id, 0) FROM users WHERE app_code = ? AND user_id = ?`, appcode.Default, int64(93001)).Scan(&changedRegionID); err != nil { + t.Fatalf("query changed user failed: %v", err) + } + if changedRegionID != 302 { + t.Fatalf("changed user region mismatch: %d", changedRegionID) + } + var outboxCount int + var payloadJSON string + if err := repository.RawDB().QueryRowContext(ctx, ` + SELECT COUNT(*), COALESCE(MAX(CAST(payload_json AS CHAR)), '') + FROM user_outbox + WHERE app_code = ? AND event_type = 'UserRegionChanged' + `, appcode.Default).Scan(&outboxCount, &payloadJSON); err != nil { + t.Fatalf("query region rebuild outbox failed: %v", err) + } + if outboxCount != 1 { + t.Fatalf("only changed users should write region outbox, count=%d", outboxCount) + } + var payload map[string]any + if err := json.Unmarshal([]byte(payloadJSON), &payload); err != nil { + t.Fatalf("decode outbox payload failed: %v", err) + } + if payload["source"] != "region_rebuild" || int64(payload["user_id"].(float64)) != 93001 || int64(payload["old_region_id"].(float64)) != 301 || int64(payload["new_region_id"].(float64)) != 302 { + t.Fatalf("region rebuild payload mismatch: %v", payload) + } +} diff --git a/services/user-service/internal/storage/mysql/user/repository.go b/services/user-service/internal/storage/mysql/user/repository.go index 0c5a28bb..2439549f 100644 --- a/services/user-service/internal/storage/mysql/user/repository.go +++ b/services/user-service/internal/storage/mysql/user/repository.go @@ -16,6 +16,8 @@ import ( "hyapp/services/user-service/internal/storage/mysql/shared" ) +const countryChangeSessionRevokeReason = "USER_COUNTRY_CHANGED" + func (r *Repository) GetUser(ctx context.Context, userID int64) (userdomain.User, error) { // 普通查询不加锁,靓号过期恢复由 service 层判断后调用 identity 事务。 user, err := QueryUser(ctx, r.db, "WHERE user_id = ?", userID) @@ -176,6 +178,37 @@ func insertUserRegisteredOutbox(ctx context.Context, tx *sql.Tx, user userdomain return err } +func insertUserRegionChangedOutbox(ctx context.Context, tx *sql.Tx, command userdomain.CountryChangeCommand, oldCountry string, oldRegionID int64) error { + if oldRegionID == command.NewRegionID { + // 下游只同步当前区域归属读模型;同区域改国家不产生区域迁移事实,避免无意义重放刷新房间和 IM 分组。 + return nil + } + source := strings.TrimSpace(command.Source) + if source == "" { + source = "unknown" + } + payload := map[string]any{ + "user_id": command.UserID, + "old_country": oldCountry, + "new_country": command.NewCountry, + "old_region_id": oldRegionID, + "new_region_id": command.NewRegionID, + "source": source, + "request_id": strings.TrimSpace(command.RequestID), + "changed_at_ms": command.ChangedAtMs, + } + payloadJSON, err := json.Marshal(payload) + if err != nil { + return err + } + eventID := fmt.Sprintf("UserRegionChanged:%s:%d:%d:%d:%d", source, command.UserID, oldRegionID, command.NewRegionID, command.ChangedAtMs) + _, err = tx.ExecContext(ctx, ` + INSERT IGNORE INTO user_outbox (app_code, event_id, event_type, aggregate_type, aggregate_id, status, payload_json, created_at_ms, updated_at_ms) + VALUES (?, ?, 'UserRegionChanged', 'user', ?, 'pending', ?, ?, ?) + `, appcode.Normalize(command.AppCode), eventID, command.UserID, string(payloadJSON), command.ChangedAtMs, command.ChangedAtMs) + return err +} + // UpdateUserProfile 修改用户基础资料并返回更新后的 users 快照。 func (r *Repository) UpdateUserProfile(ctx context.Context, command userdomain.ProfileUpdateCommand) (userdomain.User, error) { @@ -285,32 +318,34 @@ func (r *Repository) CompleteOnboarding(ctx context.Context, command userdomain. return updated, err } -// ChangeUserCountry 修改国家并写日志;冷却期检查和日志写入必须在同一事务内完成。 +// ChangeUserCountry 修改国家并写日志;冷却期、outbox 和登录 session 撤销必须在同一事务内完成。 -func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, error) { +func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, []string, error) { tx, err := r.db.BeginTx(ctx, nil) if err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } defer tx.Rollback() user, err := QueryUser(ctx, tx, "WHERE user_id = ? FOR UPDATE", command.UserID) if err == sql.ErrNoRows { - return userdomain.User{}, 0, xerr.New(xerr.NotFound, "user not found") + return userdomain.User{}, 0, nil, xerr.New(xerr.NotFound, "user not found") } if err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } lastChangedAt, err := latestCountryChangedAt(ctx, tx, command.UserID) if err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } nextAllowedAt := int64(0) if lastChangedAt > 0 && command.CooldownMs > 0 { nextAllowedAt = lastChangedAt + command.CooldownMs } + revokedSessionIDs := make([]string, 0) if user.Country == command.NewCountry { // 修改为相同国家不写日志,也不消耗冷却期;映射变化时允许修正 stale region_id。 + oldRegionID := user.RegionID if user.RegionID != command.NewRegionID { user.RegionID = command.NewRegionID user.UpdatedAtMs = command.ChangedAtMs @@ -319,20 +354,28 @@ func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.C SET region_id = ?, updated_at_ms = ? WHERE app_code = ? AND user_id = ? `, shared.NullableRegionID(user.RegionID), user.UpdatedAtMs, appcode.Normalize(command.AppCode), command.UserID); err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err + } + if err := insertUserRegionChangedOutbox(ctx, tx, command, user.Country, oldRegionID); err != nil { + return userdomain.User{}, 0, nil, err + } + revokedSessionIDs, err = revokeActiveUserSessionsForCountryChange(ctx, tx, command, appcode.Normalize(command.AppCode)) + if err != nil { + return userdomain.User{}, 0, nil, err } } if err := tx.Commit(); err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } updated, err := r.GetUser(ctx, command.UserID) - return updated, nextAllowedAt, err + return updated, nextAllowedAt, revokedSessionIDs, err } if nextAllowedAt > 0 && command.ChangedAtMs < nextAllowedAt { - return userdomain.User{}, nextAllowedAt, xerr.New(xerr.CountryChangeCooldown, "country change is cooling down") + return userdomain.User{}, nextAllowedAt, nil, xerr.New(xerr.CountryChangeCooldown, "country change is cooling down") } oldCountry := user.Country + oldRegionID := user.RegionID user.Country = command.NewCountry user.RegionID = command.NewRegionID user.UpdatedAtMs = command.ChangedAtMs @@ -342,21 +385,68 @@ func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.C WHERE app_code = ? AND user_id = ? `, shared.NullableString(user.Country), shared.NullableRegionID(user.RegionID), user.UpdatedAtMs, appcode.Normalize(command.AppCode), command.UserID) if err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } _, err = tx.ExecContext(ctx, ` INSERT INTO user_country_change_logs (app_code, user_id, old_country, new_country, request_id, changed_at_ms) VALUES (?, ?, ?, ?, ?, ?) `, appcode.Normalize(command.AppCode), command.UserID, shared.NullableString(oldCountry), command.NewCountry, command.RequestID, command.ChangedAtMs) if err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err + } + if err := insertUserRegionChangedOutbox(ctx, tx, command, oldCountry, oldRegionID); err != nil { + return userdomain.User{}, 0, nil, err + } + revokedSessionIDs, err = revokeActiveUserSessionsForCountryChange(ctx, tx, command, appcode.Normalize(command.AppCode)) + if err != nil { + return userdomain.User{}, 0, nil, err } if err := tx.Commit(); err != nil { - return userdomain.User{}, 0, err + return userdomain.User{}, 0, nil, err } updated, err := r.GetUser(ctx, command.UserID) - return updated, command.ChangedAtMs + command.CooldownMs, err + nextAllowedAt = int64(0) + if command.CooldownMs > 0 { + nextAllowedAt = command.ChangedAtMs + command.CooldownMs + } + return updated, nextAllowedAt, revokedSessionIDs, err +} + +func revokeActiveUserSessionsForCountryChange(ctx context.Context, tx *sql.Tx, command userdomain.CountryChangeCommand, appCode string) ([]string, error) { + sessionIDs := make([]string, 0) + rows, err := tx.QueryContext(ctx, ` + SELECT session_id + FROM auth_sessions + WHERE app_code = ? AND user_id = ? AND expires_at_ms > ? AND revoked_at_ms IS NULL + FOR UPDATE + `, appCode, command.UserID, command.ChangedAtMs) + if err != nil { + return nil, err + } + for rows.Next() { + var sessionID string + if err := rows.Scan(&sessionID); err != nil { + _ = rows.Close() + return nil, err + } + sessionIDs = append(sessionIDs, sessionID) + } + if err := rows.Close(); err != nil { + return nil, err + } + if len(sessionIDs) == 0 { + return sessionIDs, nil + } + _, err = tx.ExecContext(ctx, ` + UPDATE auth_sessions + SET revoked_at_ms = ?, revoked_reason = ?, revoked_request_id = ?, revoked_by = ?, updated_at_ms = ? + WHERE app_code = ? AND user_id = ? AND expires_at_ms > ? AND revoked_at_ms IS NULL + `, command.ChangedAtMs, countryChangeSessionRevokeReason, strings.TrimSpace(command.RequestID), "country_change", command.ChangedAtMs, appCode, command.UserID, command.ChangedAtMs) + if err != nil { + return nil, err + } + return sessionIDs, nil } func (r *Repository) hydrateInviteOverview(ctx context.Context, user *userdomain.User) error { diff --git a/services/user-service/internal/testutil/mysqltest/mysqltest.go b/services/user-service/internal/testutil/mysqltest/mysqltest.go index 544ba51f..a3bf4c47 100644 --- a/services/user-service/internal/testutil/mysqltest/mysqltest.go +++ b/services/user-service/internal/testutil/mysqltest/mysqltest.go @@ -146,7 +146,7 @@ func (r *Repository) CompleteOnboarding(ctx context.Context, command userdomain. } // ChangeUserCountry 让测试 wrapper 继续满足业务层国家修改接口。 -func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, error) { +func (r *Repository) ChangeUserCountry(ctx context.Context, command userdomain.CountryChangeCommand) (userdomain.User, int64, []string, error) { return r.Repository.UserRepository().ChangeUserCountry(ctx, command) } diff --git a/services/user-service/internal/transport/grpc/host_admin.go b/services/user-service/internal/transport/grpc/host_admin.go index 037282ea..7f950bbf 100644 --- a/services/user-service/internal/transport/grpc/host_admin.go +++ b/services/user-service/internal/transport/grpc/host_admin.go @@ -17,10 +17,9 @@ func (s *Server) CreateBDLeader(ctx context.Context, req *userv1.CreateBDLeaderR profile, err := s.hostSvc.CreateBDLeader(ctx, hostservice.CreateBDLeaderInput{ CommandID: req.GetCommandId(), AdminUserID: req.GetAdminUserId(), - RegionID: req.GetRegionId(), TargetUserID: req.GetTargetUserId(), Reason: req.GetReason(), - RequestID: req.GetMeta().GetRequestId(), + RequestID: requestIDFromMeta(req.GetMeta()), }) if err != nil { return nil, xerr.ToGRPCError(err) @@ -120,7 +119,6 @@ func (s *Server) CreateAgency(ctx context.Context, req *userv1.CreateAgencyReque ParentBDUserID: req.GetParentBdUserId(), Name: req.GetName(), JoinEnabled: req.GetJoinEnabled(), - MaxHosts: req.GetMaxHosts(), Reason: req.GetReason(), RequestID: req.GetMeta().GetRequestId(), }) @@ -153,6 +151,25 @@ func (s *Server) CloseAgency(ctx context.Context, req *userv1.CloseAgencyRequest return &userv1.CloseAgencyResponse{Agency: toProtoAgency(agency)}, nil } +// DeleteAgency 处理后台删除 Agency 身份;主播身份不删除,只解除当前 Agency 归属。 +func (s *Server) DeleteAgency(ctx context.Context, req *userv1.DeleteAgencyRequest) (*userv1.DeleteAgencyResponse, error) { + if s.hostSvc == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "host service is not configured")) + } + ctx = contextWithApp(ctx, req.GetMeta()) + agency, err := s.hostSvc.DeleteAgency(ctx, hostservice.DeleteAgencyInput{ + CommandID: req.GetCommandId(), + AdminUserID: req.GetAdminUserId(), + AgencyID: req.GetAgencyId(), + Reason: req.GetReason(), + RequestID: req.GetMeta().GetRequestId(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &userv1.DeleteAgencyResponse{Agency: toProtoAgency(agency)}, nil +} + // SetAgencyJoinEnabled 处理后台设置 Agency 入会开关。 func (s *Server) SetAgencyJoinEnabled(ctx context.Context, req *userv1.SetAgencyJoinEnabledRequest) (*userv1.SetAgencyJoinEnabledResponse, error) { if s.hostSvc == nil { diff --git a/services/user-service/internal/transport/grpc/server.go b/services/user-service/internal/transport/grpc/server.go index 77f79440..6e219483 100644 --- a/services/user-service/internal/transport/grpc/server.go +++ b/services/user-service/internal/transport/grpc/server.go @@ -481,15 +481,36 @@ func (s *Server) UpdateUserProfile(ctx context.Context, req *userv1.UpdateUserPr return &userv1.UpdateUserProfileResponse{User: toProtoUser(user)}, nil } -// ChangeUserCountry 单独修改国家并返回下一次可修改时间。 +// ChangeUserCountry 是 App 自助改国家入口;受限经营身份会被 service 层按当前角色摘要拦截。 func (s *Server) ChangeUserCountry(ctx context.Context, req *userv1.ChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error) { ctx = contextWithApp(ctx, req.GetMeta()) - // 国家修改有独立审计和冷却期,不能混进普通资料更新。 + // 先读取旧区域只用于响应对比;真正的一致性事件在 repository 事务内写 user_outbox。 before, err := s.userSvc.GetUser(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } - user, nextChangeAllowedAtMs, err := s.userSvc.ChangeUserCountry(ctx, req.GetUserId(), req.GetCountry(), req.GetMeta().GetRequestId()) + user, nextChangeAllowedAtMs, err := s.userSvc.ChangeUserCountry(ctx, req.GetUserId(), req.GetCountry(), requestIDFromMeta(req.GetMeta())) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + + return &userv1.ChangeUserCountryResponse{ + User: toProtoUser(user), + NextChangeAllowedAtMs: nextChangeAllowedAtMs, + OldRegionId: before.RegionID, + NewRegionId: user.RegionID, + RegionChanged: before.RegionID != user.RegionID, + }, nil +} + +// AdminChangeUserCountry 是后台显式覆盖国家入口;后台可治理受限身份用户,仍必须通过 user-service 事务写主表和 outbox。 +func (s *Server) AdminChangeUserCountry(ctx context.Context, req *userv1.AdminChangeUserCountryRequest) (*userv1.ChangeUserCountryResponse, error) { + ctx = contextWithApp(ctx, req.GetMeta()) + before, err := s.userSvc.GetUser(ctx, req.GetTargetUserId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + user, nextChangeAllowedAtMs, err := s.userSvc.AdminChangeUserCountry(ctx, req.GetTargetUserId(), req.GetCountry(), requestIDFromMeta(req.GetMeta())) if err != nil { return nil, xerr.ToGRPCError(err) } @@ -744,3 +765,10 @@ func contextWithApp(ctx context.Context, meta *userv1.RequestMeta) context.Conte } return appcode.WithContext(ctx, meta.GetAppCode()) } + +func requestIDFromMeta(meta *userv1.RequestMeta) string { + if meta == nil { + return "" + } + return meta.GetRequestId() +} diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index 994eaf00..b9a6c32b 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -2611,7 +2611,7 @@ func TestListGiftConfigsWithoutTypeFilterIncludesLuckyTypes(t *testing.T) { // 显式传入 lucky 时仍保留类型过滤能力,避免修复全部礼物预加载时破坏后台按类型筛选。 luckyItems, luckyTotal, err := svc.ListGiftConfigs(ctx, resourcedomain.ListGiftConfigsQuery{ - GiftTypeCode: resourcedomain.GiftTypeLucky, + GiftTypeCode: resourcedomain.GiftTypeLucky, ActiveOnly: true, FilterRegion: true, RegionID: 0, diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 95c7fd16..43a27c85 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -1147,7 +1147,7 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. } transactionID := transactionID(command.AppCode, command.CommandID) - // 币商转账的事实口径只记录金币数量;USD 价格策略属于外部充值定价,不参与币商库存转普通金币。 + // 币商向用户转普通金币只计普通金币到账和充值用户,不计入用户 USDT/USD 充值金额。 rechargeUSDMinor := int64(0) rechargeSequence, err := r.reserveUserRechargeSequence(ctx, tx, command.AppCode, command.TargetUserID, transactionID, command.Amount, rechargeUSDMinor, nowMs) if err != nil { diff --git a/tools/migrate-room-visible-region/main.go b/tools/migrate-room-visible-region/main.go new file mode 100644 index 00000000..ceb5f941 --- /dev/null +++ b/tools/migrate-room-visible-region/main.go @@ -0,0 +1,163 @@ +package main + +import ( + "context" + "crypto/sha1" + "database/sql" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "log" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + roomv1 "hyapp.local/api/proto/room/v1" + "hyapp/pkg/appcode" +) + +type roomCandidate struct { + RoomID string `json:"room_id"` + RoomShortID string `json:"room_short_id"` + OwnerUserID int64 `json:"owner_user_id"` + VisibleRegionID int64 `json:"visible_region_id"` + OwnerRegionID int64 `json:"owner_region_id"` +} + +func main() { + var roomDSN string + var userDSN string + var roomGRPCAddr string + var app string + var shortID string + var limit int + var apply bool + var adminID uint64 + flag.StringVar(&roomDSN, "room_mysql_dsn", "", "room-service MySQL DSN") + flag.StringVar(&userDSN, "user_mysql_dsn", "", "user-service MySQL DSN") + flag.StringVar(&roomGRPCAddr, "room_grpc_addr", "", "room-service gRPC address; required with -apply") + flag.StringVar(&app, "app_code", appcode.Default, "app_code scope") + flag.StringVar(&shortID, "room_short_id", "", "optional room_short_id filter") + flag.IntVar(&limit, "limit", 500, "maximum rooms to scan") + flag.BoolVar(&apply, "apply", false, "call room-service AdminUpdateRoom; omitted means dry-run") + flag.Uint64Var(&adminID, "admin_id", 0, "admin id written to AdminUpdateRoom") + flag.Parse() + + if strings.TrimSpace(roomDSN) == "" || strings.TrimSpace(userDSN) == "" { + log.Fatal("room_mysql_dsn and user_mysql_dsn are required") + } + if apply && strings.TrimSpace(roomGRPCAddr) == "" { + log.Fatal("room_grpc_addr is required when -apply is set") + } + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) + defer cancel() + + roomDB, err := sql.Open("mysql", roomDSN) + if err != nil { + log.Fatalf("open room mysql failed: %v", err) + } + defer roomDB.Close() + userDB, err := sql.Open("mysql", userDSN) + if err != nil { + log.Fatalf("open user mysql failed: %v", err) + } + defer userDB.Close() + + mismatches, err := findMismatches(ctx, roomDB, userDB, appcode.Normalize(app), shortID, limit) + if err != nil { + log.Fatalf("find mismatches failed: %v", err) + } + encoder := json.NewEncoder(log.Writer()) + for _, item := range mismatches { + if err := encoder.Encode(item); err != nil { + log.Fatalf("write dry-run row failed: %v", err) + } + } + log.Printf("mismatch_count=%d apply=%t", len(mismatches), apply) + if !apply || len(mismatches) == 0 { + return + } + + conn, err := grpc.DialContext(ctx, roomGRPCAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Fatalf("dial room-service failed: %v", err) + } + defer conn.Close() + client := roomv1.NewRoomCommandServiceClient(conn) + for _, item := range mismatches { + // 迁移必须走 Room Cell 命令链路,让 command log、snapshot、rooms 和 room_list_entries 在同一事务内收敛。 + if _, err := client.AdminUpdateRoom(ctx, &roomv1.AdminUpdateRoomRequest{ + Meta: &roomv1.RequestMeta{ + AppCode: appcode.Normalize(app), + RequestId: "room-visible-region-migration", + CommandId: migrationCommandID(item), + RoomId: item.RoomID, + SentAtMs: time.Now().UTC().UnixMilli(), + }, + VisibleRegionId: &item.OwnerRegionID, + AdminId: adminID, + AdminName: "room-visible-region-migration", + }); err != nil { + log.Fatalf("migrate room_id=%s short_id=%s failed: %v", item.RoomID, item.RoomShortID, err) + } + } + log.Printf("migrated_count=%d", len(mismatches)) +} + +func findMismatches(ctx context.Context, roomDB *sql.DB, userDB *sql.DB, app string, shortID string, limit int) ([]roomCandidate, error) { + if limit <= 0 { + limit = 500 + } + where := "WHERE app_code = ? AND status <> 'deleted'" + args := []any{app} + if strings.TrimSpace(shortID) != "" { + where += " AND room_short_id = ?" + args = append(args, strings.TrimSpace(shortID)) + } + args = append(args, limit) + rows, err := roomDB.QueryContext(ctx, ` + SELECT room_id, room_short_id, owner_user_id, COALESCE(visible_region_id, 0) + FROM rooms + `+where+` + ORDER BY room_id ASC + LIMIT ? + `, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + mismatches := make([]roomCandidate, 0) + for rows.Next() { + var item roomCandidate + if err := rows.Scan(&item.RoomID, &item.RoomShortID, &item.OwnerUserID, &item.VisibleRegionID); err != nil { + return nil, err + } + var ownerRegionID int64 + err := userDB.QueryRowContext(ctx, ` + SELECT COALESCE(region_id, 0) + FROM users + WHERE app_code = ? AND user_id = ? AND COALESCE(region_id, 0) > 0 + `, app, item.OwnerUserID).Scan(&ownerRegionID) + if err == sql.ErrNoRows { + continue + } + if err != nil { + return nil, err + } + if ownerRegionID == item.VisibleRegionID { + continue + } + item.OwnerRegionID = ownerRegionID + mismatches = append(mismatches, item) + } + return mismatches, rows.Err() +} + +func migrationCommandID(item roomCandidate) string { + sum := sha1.Sum([]byte(fmt.Sprintf("%s:%d:%d", item.RoomID, item.VisibleRegionID, item.OwnerRegionID))) + return "room-region-migrate:" + hex.EncodeToString(sum[:]) +} From 02ce8874c3b8a71ccf3768450098ae3b06fedeec Mon Sep 17 00:00:00 2001 From: zhx Date: Sat, 6 Jun 2026 13:50:46 +0800 Subject: [PATCH 24/28] Add activity reward programs --- .gitignore | 5 +- api/proto/activity/v1/activity.pb.go | 5484 +++++++++++++++-- api/proto/activity/v1/activity.proto | 454 ++ api/proto/activity/v1/activity_grpc.pb.go | 1255 +++- api/proto/wallet/v1/wallet.pb.go | 729 ++- api/proto/wallet/v1/wallet.proto | 25 + api/proto/wallet/v1/wallet_grpc.pb.go | 38 + server/admin/cmd/server/main.go | 6 + .../integration/activityclient/client.go | 76 + .../internal/integration/userclient/client.go | 16 +- .../integration/userclient/client_test.go | 34 + .../admin/internal/modules/appuser/handler.go | 6 + .../admin/internal/modules/appuser/request.go | 5 + .../admin/internal/modules/appuser/service.go | 72 +- .../internal/modules/appuser/service_test.go | 45 +- .../admin/internal/modules/coinledger/dto.go | 36 +- .../internal/modules/coinledger/handler.go | 22 + .../internal/modules/coinledger/routes.go | 1 + .../internal/modules/coinledger/service.go | 137 +- .../modules/coinledger/service_test.go | 31 + .../cumulativerechargereward/handler.go | 356 ++ .../cumulativerechargereward/routes.go | 16 + .../modules/gamemanagement/sync_games.go | 72 + .../modules/gamemanagement/sync_games_test.go | 31 + .../admin/internal/modules/hostorg/reader.go | 126 +- .../admin/internal/modules/hostorg/service.go | 7 +- .../internal/modules/hostorg/service_test.go | 32 + .../modules/registrationreward/handler.go | 64 +- .../modules/roomturnoverreward/handler.go | 227 + .../modules/roomturnoverreward/routes.go | 17 + .../internal/modules/weeklystar/handler.go | 350 ++ .../internal/modules/weeklystar/routes.go | 20 + server/admin/internal/repository/seed.go | 36 +- server/admin/internal/router/router.go | 9 + .../036_room_turnover_reward_navigation.sql | 60 + .../migrations/037_weekly_star_navigation.sql | 61 + ..._cumulative_recharge_reward_navigation.sql | 59 + .../039_admin_parent_menu_order.sql | 39 + .../configs/config.docker.yaml | 4 + .../configs/config.tencent.example.yaml | 4 + services/activity-service/configs/config.yaml | 4 + .../mysql/initdb/001_activity_service.sql | 272 + services/activity-service/internal/app/app.go | 529 +- .../internal/app/dependencies.go | 71 + .../internal/app/grpc_registration.go | 40 + .../activity-service/internal/app/health.go | 24 + services/activity-service/internal/app/mq.go | 236 + .../activity-service/internal/app/services.go | 110 + .../internal/app/wallet_events.go | 296 + .../activity-service/internal/app/workers.go | 20 + .../internal/config/config.go | 24 +- .../cumulativerecharge/cumulative_recharge.go | 130 + .../registrationreward/registration_reward.go | 12 +- .../room_turnover_reward.go | 120 + .../internal/domain/weeklystar/weekly_star.go | 126 + .../service/cumulativerecharge/service.go | 356 ++ .../internal/service/luckygift/service.go | 4 + .../service/luckygift/service_test.go | 4 + .../service/registrationreward/service.go | 16 +- .../service/roomturnoverreward/service.go | 517 ++ .../roomturnoverreward/service_test.go | 219 + .../internal/service/weeklystar/service.go | 359 ++ .../cumulative_recharge_reward_migration.go | 96 + .../cumulative_recharge_reward_repository.go | 696 +++ .../storage/mysql/lucky_gift_repository.go | 191 +- .../mysql/lucky_gift_repository_test.go | 31 + .../mysql/registration_reward_repository.go | 34 +- .../internal/storage/mysql/repository.go | 54 + .../mysql/repository_migration_test.go | 28 + .../mysql/room_turnover_reward_migration.go | 87 + .../mysql/room_turnover_reward_repository.go | 562 ++ .../storage/mysql/weekly_star_migration.go | 96 + .../storage/mysql/weekly_star_repository.go | 876 +++ .../transport/grpc/broadcast_server.go | 33 +- .../internal/transport/grpc/cron_server.go | 51 +- .../grpc/cumulative_recharge_reward_server.go | 212 + .../grpc/registration_reward_server.go | 18 +- .../grpc/room_turnover_reward_server.go | 185 + .../transport/grpc/weekly_star_server.go | 250 + .../cron-service/configs/config.docker.yaml | 14 + .../configs/config.tencent.example.yaml | 14 + services/cron-service/configs/config.yaml | 14 + services/cron-service/internal/app/app.go | 2 + .../cron-service/internal/config/config.go | 16 + .../internal/integration/activity.go | 19 + .../game-service/internal/domain/game/game.go | 11 +- .../internal/service/game/service.go | 38 +- .../internal/service/game/service_test.go | 181 + .../service/game/vivagames_adapter.go | 494 ++ services/gateway-service/internal/app/app.go | 6 + .../cumulative_recharge_reward_client.go | 25 + .../client/room_turnover_reward_client.go | 25 + .../internal/client/weekly_star_client.go | 35 + .../cumulative_recharge_reward_handler.go | 225 + .../transport/http/activityapi/handler.go | 30 +- .../room_turnover_reward_handler.go | 237 + .../http/activityapi/weekly_star_handler.go | 282 + .../internal/transport/http/handler.go | 18 + .../transport/http/httproutes/router.go | 26 +- .../internal/transport/http/router.go | 3 + .../configs/config.docker.yaml | 1 + .../configs/config.tencent.example.yaml | 1 + .../statistics-service/configs/config.yaml | 1 + .../statistics-service/internal/app/app.go | 2 +- .../internal/config/config.go | 34 +- .../internal/storage/mysql/query.go | 62 +- .../internal/storage/mysql/query_test.go | 66 + .../internal/storage/mysql/repository.go | 54 +- .../internal/domain/ledger/ledger.go | 24 + .../internal/service/wallet/service.go | 28 + .../internal/storage/mysql/repository.go | 176 + .../internal/transport/grpc/server.go | 36 + tools/cumulative-recharge-local-flow/main.go | 505 ++ tools/weekly-star-local-boundary/main.go | 660 ++ tools/weekly-star-local-flow/main.go | 473 ++ 115 files changed, 19375 insertions(+), 1519 deletions(-) create mode 100644 server/admin/internal/integration/userclient/client_test.go create mode 100644 server/admin/internal/modules/cumulativerechargereward/handler.go create mode 100644 server/admin/internal/modules/cumulativerechargereward/routes.go create mode 100644 server/admin/internal/modules/hostorg/service_test.go create mode 100644 server/admin/internal/modules/roomturnoverreward/handler.go create mode 100644 server/admin/internal/modules/roomturnoverreward/routes.go create mode 100644 server/admin/internal/modules/weeklystar/handler.go create mode 100644 server/admin/internal/modules/weeklystar/routes.go create mode 100644 server/admin/migrations/036_room_turnover_reward_navigation.sql create mode 100644 server/admin/migrations/037_weekly_star_navigation.sql create mode 100644 server/admin/migrations/038_cumulative_recharge_reward_navigation.sql create mode 100644 server/admin/migrations/039_admin_parent_menu_order.sql create mode 100644 services/activity-service/internal/app/dependencies.go create mode 100644 services/activity-service/internal/app/grpc_registration.go create mode 100644 services/activity-service/internal/app/health.go create mode 100644 services/activity-service/internal/app/mq.go create mode 100644 services/activity-service/internal/app/services.go create mode 100644 services/activity-service/internal/app/wallet_events.go create mode 100644 services/activity-service/internal/app/workers.go create mode 100644 services/activity-service/internal/domain/cumulativerecharge/cumulative_recharge.go create mode 100644 services/activity-service/internal/domain/roomturnoverreward/room_turnover_reward.go create mode 100644 services/activity-service/internal/domain/weeklystar/weekly_star.go create mode 100644 services/activity-service/internal/service/cumulativerecharge/service.go create mode 100644 services/activity-service/internal/service/roomturnoverreward/service.go create mode 100644 services/activity-service/internal/service/roomturnoverreward/service_test.go create mode 100644 services/activity-service/internal/service/weeklystar/service.go create mode 100644 services/activity-service/internal/storage/mysql/cumulative_recharge_reward_migration.go create mode 100644 services/activity-service/internal/storage/mysql/cumulative_recharge_reward_repository.go create mode 100644 services/activity-service/internal/storage/mysql/room_turnover_reward_migration.go create mode 100644 services/activity-service/internal/storage/mysql/room_turnover_reward_repository.go create mode 100644 services/activity-service/internal/storage/mysql/weekly_star_migration.go create mode 100644 services/activity-service/internal/storage/mysql/weekly_star_repository.go create mode 100644 services/activity-service/internal/transport/grpc/cumulative_recharge_reward_server.go create mode 100644 services/activity-service/internal/transport/grpc/room_turnover_reward_server.go create mode 100644 services/activity-service/internal/transport/grpc/weekly_star_server.go create mode 100644 services/game-service/internal/service/game/vivagames_adapter.go create mode 100644 services/gateway-service/internal/client/cumulative_recharge_reward_client.go create mode 100644 services/gateway-service/internal/client/room_turnover_reward_client.go create mode 100644 services/gateway-service/internal/client/weekly_star_client.go create mode 100644 services/gateway-service/internal/transport/http/activityapi/cumulative_recharge_reward_handler.go create mode 100644 services/gateway-service/internal/transport/http/activityapi/room_turnover_reward_handler.go create mode 100644 services/gateway-service/internal/transport/http/activityapi/weekly_star_handler.go create mode 100644 services/statistics-service/internal/storage/mysql/query_test.go create mode 100644 tools/cumulative-recharge-local-flow/main.go create mode 100644 tools/weekly-star-local-boundary/main.go create mode 100644 tools/weekly-star-local-flow/main.go diff --git a/.gitignore b/.gitignore index 35b9757e..65402c2e 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,7 @@ node_modules/ mysql-data/ redis-data/ -.waylog/ \ No newline at end of file +.waylog/ + +.tmp/ +/tmp/ diff --git a/api/proto/activity/v1/activity.pb.go b/api/proto/activity/v1/activity.pb.go index e4162e8c..cc704a8e 100644 --- a/api/proto/activity/v1/activity.pb.go +++ b/api/proto/activity/v1/activity.pb.go @@ -4524,14 +4524,16 @@ func (x *UpdateRegistrationRewardConfigResponse) GetConfig() *RegistrationReward // ListRegistrationRewardClaimsRequest 是后台领取记录分页筛选;keyword 由 admin-server 结合用户库扩展。 type ListRegistrationRewardClaimsRequest 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 + 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"` + ClaimedStartMs int64 `protobuf:"varint,6,opt,name=claimed_start_ms,json=claimedStartMs,proto3" json:"claimed_start_ms,omitempty"` + ClaimedEndMs int64 `protobuf:"varint,7,opt,name=claimed_end_ms,json=claimedEndMs,proto3" json:"claimed_end_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRegistrationRewardClaimsRequest) Reset() { @@ -4599,12 +4601,27 @@ func (x *ListRegistrationRewardClaimsRequest) GetPageSize() int32 { return 0 } +func (x *ListRegistrationRewardClaimsRequest) GetClaimedStartMs() int64 { + if x != nil { + return x.ClaimedStartMs + } + return 0 +} + +func (x *ListRegistrationRewardClaimsRequest) GetClaimedEndMs() int64 { + if x != nil { + return x.ClaimedEndMs + } + return 0 +} + type ListRegistrationRewardClaimsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Claims []*RegistrationRewardClaim `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 + state protoimpl.MessageState `protogen:"open.v1"` + Claims []*RegistrationRewardClaim `protobuf:"bytes,1,rep,name=claims,proto3" json:"claims,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + TodayClaimedCount int64 `protobuf:"varint,3,opt,name=today_claimed_count,json=todayClaimedCount,proto3" json:"today_claimed_count,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ListRegistrationRewardClaimsResponse) Reset() { @@ -4651,6 +4668,13 @@ func (x *ListRegistrationRewardClaimsResponse) GetTotal() int64 { return 0 } +func (x *ListRegistrationRewardClaimsResponse) GetTodayClaimedCount() int64 { + if x != nil { + return x.TodayClaimedCount + } + return 0 +} + // FirstRechargeRewardTier 是首冲奖励的一个金币充值档位;max_coin_amount=0 表示无上限。 type FirstRechargeRewardTier struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -5712,6 +5736,2276 @@ func (x *ListFirstRechargeRewardClaimsResponse) GetTotal() int64 { return 0 } +// CumulativeRechargeRewardTier 是累充奖励的单个 USD 档位;threshold_usd_minor 以美分存储。 +type CumulativeRechargeRewardTier 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"` + ThresholdUsdMinor int64 `protobuf:"varint,4,opt,name=threshold_usd_minor,json=thresholdUsdMinor,proto3" json:"threshold_usd_minor,omitempty"` + ResourceGroupId int64 `protobuf:"varint,5,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CumulativeRechargeRewardTier) Reset() { + *x = CumulativeRechargeRewardTier{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CumulativeRechargeRewardTier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CumulativeRechargeRewardTier) ProtoMessage() {} + +func (x *CumulativeRechargeRewardTier) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + 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 CumulativeRechargeRewardTier.ProtoReflect.Descriptor instead. +func (*CumulativeRechargeRewardTier) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{76} +} + +func (x *CumulativeRechargeRewardTier) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *CumulativeRechargeRewardTier) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *CumulativeRechargeRewardTier) GetTierName() string { + if x != nil { + return x.TierName + } + return "" +} + +func (x *CumulativeRechargeRewardTier) GetThresholdUsdMinor() int64 { + if x != nil { + return x.ThresholdUsdMinor + } + return 0 +} + +func (x *CumulativeRechargeRewardTier) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +func (x *CumulativeRechargeRewardTier) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CumulativeRechargeRewardTier) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +func (x *CumulativeRechargeRewardTier) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardTier) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// CumulativeRechargeRewardConfig 是当前 App 的累充奖励配置。 +type CumulativeRechargeRewardConfig 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 []*CumulativeRechargeRewardTier `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 *CumulativeRechargeRewardConfig) Reset() { + *x = CumulativeRechargeRewardConfig{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CumulativeRechargeRewardConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CumulativeRechargeRewardConfig) ProtoMessage() {} + +func (x *CumulativeRechargeRewardConfig) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + 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 CumulativeRechargeRewardConfig.ProtoReflect.Descriptor instead. +func (*CumulativeRechargeRewardConfig) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{77} +} + +func (x *CumulativeRechargeRewardConfig) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *CumulativeRechargeRewardConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *CumulativeRechargeRewardConfig) GetTiers() []*CumulativeRechargeRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *CumulativeRechargeRewardConfig) GetUpdatedByAdminId() int64 { + if x != nil { + return x.UpdatedByAdminId + } + return 0 +} + +func (x *CumulativeRechargeRewardConfig) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardConfig) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// CumulativeRechargeRewardGrant 是用户在一个 UTC 自然周内达成某个档位后的发放事实。 +type CumulativeRechargeRewardGrant struct { + state protoimpl.MessageState `protogen:"open.v1"` + GrantId string `protobuf:"bytes,1,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CycleKey string `protobuf:"bytes,3,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + EventId string `protobuf:"bytes,5,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + TransactionId string `protobuf:"bytes,6,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CommandId string `protobuf:"bytes,7,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + TierId int64 `protobuf:"varint,8,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,9,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + ThresholdUsdMinor int64 `protobuf:"varint,10,opt,name=threshold_usd_minor,json=thresholdUsdMinor,proto3" json:"threshold_usd_minor,omitempty"` + ResourceGroupId int64 `protobuf:"varint,11,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + ReachedUsdMinor int64 `protobuf:"varint,12,opt,name=reached_usd_minor,json=reachedUsdMinor,proto3" json:"reached_usd_minor,omitempty"` + QualifyingUsdMinor int64 `protobuf:"varint,13,opt,name=qualifying_usd_minor,json=qualifyingUsdMinor,proto3" json:"qualifying_usd_minor,omitempty"` + RechargeCoinAmount int64 `protobuf:"varint,14,opt,name=recharge_coin_amount,json=rechargeCoinAmount,proto3" json:"recharge_coin_amount,omitempty"` + RechargeType string `protobuf:"bytes,15,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` + Status string `protobuf:"bytes,16,opt,name=status,proto3" json:"status,omitempty"` + WalletCommandId string `protobuf:"bytes,17,opt,name=wallet_command_id,json=walletCommandId,proto3" json:"wallet_command_id,omitempty"` + WalletGrantId string `protobuf:"bytes,18,opt,name=wallet_grant_id,json=walletGrantId,proto3" json:"wallet_grant_id,omitempty"` + FailureReason string `protobuf:"bytes,19,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + GrantedAtMs int64 `protobuf:"varint,20,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` + CreatedAtMs int64 `protobuf:"varint,21,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,22,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CumulativeRechargeRewardGrant) Reset() { + *x = CumulativeRechargeRewardGrant{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CumulativeRechargeRewardGrant) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CumulativeRechargeRewardGrant) ProtoMessage() {} + +func (x *CumulativeRechargeRewardGrant) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + 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 CumulativeRechargeRewardGrant.ProtoReflect.Descriptor instead. +func (*CumulativeRechargeRewardGrant) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{78} +} + +func (x *CumulativeRechargeRewardGrant) GetGrantId() string { + if x != nil { + return x.GrantId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetThresholdUsdMinor() int64 { + if x != nil { + return x.ThresholdUsdMinor + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetReachedUsdMinor() int64 { + if x != nil { + return x.ReachedUsdMinor + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetQualifyingUsdMinor() int64 { + if x != nil { + return x.QualifyingUsdMinor + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetRechargeCoinAmount() int64 { + if x != nil { + return x.RechargeCoinAmount + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetRechargeType() string { + if x != nil { + return x.RechargeType + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetWalletCommandId() string { + if x != nil { + return x.WalletCommandId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetWalletGrantId() string { + if x != nil { + return x.WalletGrantId + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetFailureReason() string { + if x != nil { + return x.FailureReason + } + return "" +} + +func (x *CumulativeRechargeRewardGrant) GetGrantedAtMs() int64 { + if x != nil { + return x.GrantedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardGrant) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// CumulativeRechargeRewardProgress 是用户在当前 UTC 周期内的累充累计投影。 +type CumulativeRechargeRewardProgress struct { + state protoimpl.MessageState `protogen:"open.v1"` + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CycleKey string `protobuf:"bytes,2,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + TotalUsdMinor int64 `protobuf:"varint,4,opt,name=total_usd_minor,json=totalUsdMinor,proto3" json:"total_usd_minor,omitempty"` + TotalCoinAmount int64 `protobuf:"varint,5,opt,name=total_coin_amount,json=totalCoinAmount,proto3" json:"total_coin_amount,omitempty"` + FirstRechargedAtMs int64 `protobuf:"varint,6,opt,name=first_recharged_at_ms,json=firstRechargedAtMs,proto3" json:"first_recharged_at_ms,omitempty"` + LastRechargedAtMs int64 `protobuf:"varint,7,opt,name=last_recharged_at_ms,json=lastRechargedAtMs,proto3" json:"last_recharged_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,8,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CumulativeRechargeRewardProgress) Reset() { + *x = CumulativeRechargeRewardProgress{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CumulativeRechargeRewardProgress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CumulativeRechargeRewardProgress) ProtoMessage() {} + +func (x *CumulativeRechargeRewardProgress) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + 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 CumulativeRechargeRewardProgress.ProtoReflect.Descriptor instead. +func (*CumulativeRechargeRewardProgress) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{79} +} + +func (x *CumulativeRechargeRewardProgress) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *CumulativeRechargeRewardProgress) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *CumulativeRechargeRewardProgress) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *CumulativeRechargeRewardProgress) GetTotalUsdMinor() int64 { + if x != nil { + return x.TotalUsdMinor + } + return 0 +} + +func (x *CumulativeRechargeRewardProgress) GetTotalCoinAmount() int64 { + if x != nil { + return x.TotalCoinAmount + } + return 0 +} + +func (x *CumulativeRechargeRewardProgress) GetFirstRechargedAtMs() int64 { + if x != nil { + return x.FirstRechargedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardProgress) GetLastRechargedAtMs() int64 { + if x != nil { + return x.LastRechargedAtMs + } + return 0 +} + +func (x *CumulativeRechargeRewardProgress) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// CumulativeRechargeRewardStatus 是 App 累充奖励 H5 可直接展示的当前状态。 +type CumulativeRechargeRewardStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *CumulativeRechargeRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + Progress *CumulativeRechargeRewardProgress `protobuf:"bytes,2,opt,name=progress,proto3" json:"progress,omitempty"` + Grants []*CumulativeRechargeRewardGrant `protobuf:"bytes,3,rep,name=grants,proto3" json:"grants,omitempty"` + CycleKey string `protobuf:"bytes,4,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + PeriodStartMs int64 `protobuf:"varint,5,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + PeriodEndMs int64 `protobuf:"varint,6,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` + ServerTimeMs int64 `protobuf:"varint,7,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CumulativeRechargeRewardStatus) Reset() { + *x = CumulativeRechargeRewardStatus{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CumulativeRechargeRewardStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CumulativeRechargeRewardStatus) ProtoMessage() {} + +func (x *CumulativeRechargeRewardStatus) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + 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 CumulativeRechargeRewardStatus.ProtoReflect.Descriptor instead. +func (*CumulativeRechargeRewardStatus) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{80} +} + +func (x *CumulativeRechargeRewardStatus) GetConfig() *CumulativeRechargeRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *CumulativeRechargeRewardStatus) GetProgress() *CumulativeRechargeRewardProgress { + if x != nil { + return x.Progress + } + return nil +} + +func (x *CumulativeRechargeRewardStatus) GetGrants() []*CumulativeRechargeRewardGrant { + if x != nil { + return x.Grants + } + return nil +} + +func (x *CumulativeRechargeRewardStatus) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *CumulativeRechargeRewardStatus) GetPeriodStartMs() int64 { + if x != nil { + return x.PeriodStartMs + } + return 0 +} + +func (x *CumulativeRechargeRewardStatus) GetPeriodEndMs() int64 { + if x != nil { + return x.PeriodEndMs + } + return 0 +} + +func (x *CumulativeRechargeRewardStatus) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type GetCumulativeRechargeRewardStatusRequest 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 *GetCumulativeRechargeRewardStatusRequest) Reset() { + *x = GetCumulativeRechargeRewardStatusRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetCumulativeRechargeRewardStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCumulativeRechargeRewardStatusRequest) ProtoMessage() {} + +func (x *GetCumulativeRechargeRewardStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + 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 GetCumulativeRechargeRewardStatusRequest.ProtoReflect.Descriptor instead. +func (*GetCumulativeRechargeRewardStatusRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{81} +} + +func (x *GetCumulativeRechargeRewardStatusRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetCumulativeRechargeRewardStatusRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +type GetCumulativeRechargeRewardStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Status *CumulativeRechargeRewardStatus `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetCumulativeRechargeRewardStatusResponse) Reset() { + *x = GetCumulativeRechargeRewardStatusResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetCumulativeRechargeRewardStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCumulativeRechargeRewardStatusResponse) ProtoMessage() {} + +func (x *GetCumulativeRechargeRewardStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + 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 GetCumulativeRechargeRewardStatusResponse.ProtoReflect.Descriptor instead. +func (*GetCumulativeRechargeRewardStatusResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{82} +} + +func (x *GetCumulativeRechargeRewardStatusResponse) GetStatus() *CumulativeRechargeRewardStatus { + if x != nil { + return x.Status + } + return nil +} + +// ConsumeCumulativeRechargeRewardRequest 是 wallet 充值事实消费入口;所有成功充值都会按 UTC 周期累计。 +type ConsumeCumulativeRechargeRewardRequest 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"` + QualifyingUsdMinor int64 `protobuf:"varint,9,opt,name=qualifying_usd_minor,json=qualifyingUsdMinor,proto3" json:"qualifying_usd_minor,omitempty"` + PayloadJson string `protobuf:"bytes,10,opt,name=payload_json,json=payloadJson,proto3" json:"payload_json,omitempty"` + OccurredAtMs int64 `protobuf:"varint,11,opt,name=occurred_at_ms,json=occurredAtMs,proto3" json:"occurred_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ConsumeCumulativeRechargeRewardRequest) Reset() { + *x = ConsumeCumulativeRechargeRewardRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsumeCumulativeRechargeRewardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsumeCumulativeRechargeRewardRequest) ProtoMessage() {} + +func (x *ConsumeCumulativeRechargeRewardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + 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 ConsumeCumulativeRechargeRewardRequest.ProtoReflect.Descriptor instead. +func (*ConsumeCumulativeRechargeRewardRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{83} +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetEventId() string { + if x != nil { + return x.EventId + } + return "" +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetRechargeCoinAmount() int64 { + if x != nil { + return x.RechargeCoinAmount + } + return 0 +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetRechargeSequence() int64 { + if x != nil { + return x.RechargeSequence + } + return 0 +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetRechargeType() string { + if x != nil { + return x.RechargeType + } + return "" +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetQualifyingUsdMinor() int64 { + if x != nil { + return x.QualifyingUsdMinor + } + return 0 +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetPayloadJson() string { + if x != nil { + return x.PayloadJson + } + return "" +} + +func (x *ConsumeCumulativeRechargeRewardRequest) GetOccurredAtMs() int64 { + if x != nil { + return x.OccurredAtMs + } + return 0 +} + +type ConsumeCumulativeRechargeRewardResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Grants []*CumulativeRechargeRewardGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,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 *ConsumeCumulativeRechargeRewardResponse) Reset() { + *x = ConsumeCumulativeRechargeRewardResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConsumeCumulativeRechargeRewardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConsumeCumulativeRechargeRewardResponse) ProtoMessage() {} + +func (x *ConsumeCumulativeRechargeRewardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + 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 ConsumeCumulativeRechargeRewardResponse.ProtoReflect.Descriptor instead. +func (*ConsumeCumulativeRechargeRewardResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{84} +} + +func (x *ConsumeCumulativeRechargeRewardResponse) GetGrants() []*CumulativeRechargeRewardGrant { + if x != nil { + return x.Grants + } + return nil +} + +func (x *ConsumeCumulativeRechargeRewardResponse) GetConsumed() bool { + if x != nil { + return x.Consumed + } + return false +} + +func (x *ConsumeCumulativeRechargeRewardResponse) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +type GetCumulativeRechargeRewardConfigRequest 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 *GetCumulativeRechargeRewardConfigRequest) Reset() { + *x = GetCumulativeRechargeRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetCumulativeRechargeRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCumulativeRechargeRewardConfigRequest) ProtoMessage() {} + +func (x *GetCumulativeRechargeRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + 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 GetCumulativeRechargeRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*GetCumulativeRechargeRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{85} +} + +func (x *GetCumulativeRechargeRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +type GetCumulativeRechargeRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *CumulativeRechargeRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetCumulativeRechargeRewardConfigResponse) Reset() { + *x = GetCumulativeRechargeRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetCumulativeRechargeRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetCumulativeRechargeRewardConfigResponse) ProtoMessage() {} + +func (x *GetCumulativeRechargeRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + 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 GetCumulativeRechargeRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*GetCumulativeRechargeRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{86} +} + +func (x *GetCumulativeRechargeRewardConfigResponse) GetConfig() *CumulativeRechargeRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type UpdateCumulativeRechargeRewardConfigRequest 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 []*CumulativeRechargeRewardTier `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 *UpdateCumulativeRechargeRewardConfigRequest) Reset() { + *x = UpdateCumulativeRechargeRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateCumulativeRechargeRewardConfigRequest) ProtoMessage() {} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + 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 UpdateCumulativeRechargeRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*UpdateCumulativeRechargeRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{87} +} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) GetTiers() []*CumulativeRechargeRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *UpdateCumulativeRechargeRewardConfigRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type UpdateCumulativeRechargeRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *CumulativeRechargeRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateCumulativeRechargeRewardConfigResponse) Reset() { + *x = UpdateCumulativeRechargeRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateCumulativeRechargeRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateCumulativeRechargeRewardConfigResponse) ProtoMessage() {} + +func (x *UpdateCumulativeRechargeRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + 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 UpdateCumulativeRechargeRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*UpdateCumulativeRechargeRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{88} +} + +func (x *UpdateCumulativeRechargeRewardConfigResponse) GetConfig() *CumulativeRechargeRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type ListCumulativeRechargeRewardGrantsRequest 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"` + CycleKey string `protobuf:"bytes,4,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) Reset() { + *x = ListCumulativeRechargeRewardGrantsRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCumulativeRechargeRewardGrantsRequest) ProtoMessage() {} + +func (x *ListCumulativeRechargeRewardGrantsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + 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 ListCumulativeRechargeRewardGrantsRequest.ProtoReflect.Descriptor instead. +func (*ListCumulativeRechargeRewardGrantsRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{89} +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetCycleKey() string { + if x != nil { + return x.CycleKey + } + return "" +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListCumulativeRechargeRewardGrantsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListCumulativeRechargeRewardGrantsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Grants []*CumulativeRechargeRewardGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListCumulativeRechargeRewardGrantsResponse) Reset() { + *x = ListCumulativeRechargeRewardGrantsResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListCumulativeRechargeRewardGrantsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListCumulativeRechargeRewardGrantsResponse) ProtoMessage() {} + +func (x *ListCumulativeRechargeRewardGrantsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + 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 ListCumulativeRechargeRewardGrantsResponse.ProtoReflect.Descriptor instead. +func (*ListCumulativeRechargeRewardGrantsResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{90} +} + +func (x *ListCumulativeRechargeRewardGrantsResponse) GetGrants() []*CumulativeRechargeRewardGrant { + if x != nil { + return x.Grants + } + return nil +} + +func (x *ListCumulativeRechargeRewardGrantsResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +// RoomTurnoverRewardTier 是房间流水奖励的单个档位;达到 threshold_coin_spent 后可命中奖励。 +type RoomTurnoverRewardTier 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"` + ThresholdCoinSpent int64 `protobuf:"varint,4,opt,name=threshold_coin_spent,json=thresholdCoinSpent,proto3" json:"threshold_coin_spent,omitempty"` + RewardCoinAmount int64 `protobuf:"varint,5,opt,name=reward_coin_amount,json=rewardCoinAmount,proto3" json:"reward_coin_amount,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoomTurnoverRewardTier) Reset() { + *x = RoomTurnoverRewardTier{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomTurnoverRewardTier) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomTurnoverRewardTier) ProtoMessage() {} + +func (x *RoomTurnoverRewardTier) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + 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 RoomTurnoverRewardTier.ProtoReflect.Descriptor instead. +func (*RoomTurnoverRewardTier) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{91} +} + +func (x *RoomTurnoverRewardTier) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *RoomTurnoverRewardTier) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *RoomTurnoverRewardTier) GetTierName() string { + if x != nil { + return x.TierName + } + return "" +} + +func (x *RoomTurnoverRewardTier) GetThresholdCoinSpent() int64 { + if x != nil { + return x.ThresholdCoinSpent + } + return 0 +} + +func (x *RoomTurnoverRewardTier) GetRewardCoinAmount() int64 { + if x != nil { + return x.RewardCoinAmount + } + return 0 +} + +func (x *RoomTurnoverRewardTier) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *RoomTurnoverRewardTier) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +func (x *RoomTurnoverRewardTier) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *RoomTurnoverRewardTier) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// RoomTurnoverRewardConfig 是当前 App 的房间流水奖励配置;结算只命中最高有效档。 +type RoomTurnoverRewardConfig 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 []*RoomTurnoverRewardTier `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 *RoomTurnoverRewardConfig) Reset() { + *x = RoomTurnoverRewardConfig{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomTurnoverRewardConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomTurnoverRewardConfig) ProtoMessage() {} + +func (x *RoomTurnoverRewardConfig) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + 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 RoomTurnoverRewardConfig.ProtoReflect.Descriptor instead. +func (*RoomTurnoverRewardConfig) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{92} +} + +func (x *RoomTurnoverRewardConfig) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *RoomTurnoverRewardConfig) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *RoomTurnoverRewardConfig) GetTiers() []*RoomTurnoverRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *RoomTurnoverRewardConfig) GetUpdatedByAdminId() int64 { + if x != nil { + return x.UpdatedByAdminId + } + return 0 +} + +func (x *RoomTurnoverRewardConfig) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *RoomTurnoverRewardConfig) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// RoomTurnoverRewardSettlement 是某个房间单个 UTC 周期的结算事实。 +type RoomTurnoverRewardSettlement struct { + state protoimpl.MessageState `protogen:"open.v1"` + SettlementId string `protobuf:"bytes,1,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + PeriodStartMs int64 `protobuf:"varint,5,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + PeriodEndMs int64 `protobuf:"varint,6,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` + CoinSpent int64 `protobuf:"varint,7,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + TierId int64 `protobuf:"varint,8,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,9,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + ThresholdCoinSpent int64 `protobuf:"varint,10,opt,name=threshold_coin_spent,json=thresholdCoinSpent,proto3" json:"threshold_coin_spent,omitempty"` + RewardCoinAmount int64 `protobuf:"varint,11,opt,name=reward_coin_amount,json=rewardCoinAmount,proto3" json:"reward_coin_amount,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"` + WalletTransactionId string `protobuf:"bytes,14,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + FailureReason string `protobuf:"bytes,15,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + SettledAtMs int64 `protobuf:"varint,16,opt,name=settled_at_ms,json=settledAtMs,proto3" json:"settled_at_ms,omitempty"` + CreatedAtMs int64 `protobuf:"varint,17,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,18,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoomTurnoverRewardSettlement) Reset() { + *x = RoomTurnoverRewardSettlement{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomTurnoverRewardSettlement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomTurnoverRewardSettlement) ProtoMessage() {} + +func (x *RoomTurnoverRewardSettlement) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + 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 RoomTurnoverRewardSettlement.ProtoReflect.Descriptor instead. +func (*RoomTurnoverRewardSettlement) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{93} +} + +func (x *RoomTurnoverRewardSettlement) GetSettlementId() string { + if x != nil { + return x.SettlementId + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetOwnerUserId() int64 { + if x != nil { + return x.OwnerUserId + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetPeriodStartMs() int64 { + if x != nil { + return x.PeriodStartMs + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetPeriodEndMs() int64 { + if x != nil { + return x.PeriodEndMs + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetCoinSpent() int64 { + if x != nil { + return x.CoinSpent + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetThresholdCoinSpent() int64 { + if x != nil { + return x.ThresholdCoinSpent + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetRewardCoinAmount() int64 { + if x != nil { + return x.RewardCoinAmount + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetWalletCommandId() string { + if x != nil { + return x.WalletCommandId + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetWalletTransactionId() string { + if x != nil { + return x.WalletTransactionId + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetFailureReason() string { + if x != nil { + return x.FailureReason + } + return "" +} + +func (x *RoomTurnoverRewardSettlement) GetSettledAtMs() int64 { + if x != nil { + return x.SettledAtMs + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *RoomTurnoverRewardSettlement) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +// RoomTurnoverRewardStatus 给 App H5 返回当前 UTC 周期、房间流水、预计奖励和上一期结算。 +type RoomTurnoverRewardStatus struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *RoomTurnoverRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,3,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + PeriodStartMs int64 `protobuf:"varint,4,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + PeriodEndMs int64 `protobuf:"varint,5,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` + CurrentCoinSpent int64 `protobuf:"varint,6,opt,name=current_coin_spent,json=currentCoinSpent,proto3" json:"current_coin_spent,omitempty"` + ExpectedRewardCoinAmount int64 `protobuf:"varint,7,opt,name=expected_reward_coin_amount,json=expectedRewardCoinAmount,proto3" json:"expected_reward_coin_amount,omitempty"` + MatchedTier *RoomTurnoverRewardTier `protobuf:"bytes,8,opt,name=matched_tier,json=matchedTier,proto3" json:"matched_tier,omitempty"` + LatestSettlement *RoomTurnoverRewardSettlement `protobuf:"bytes,9,opt,name=latest_settlement,json=latestSettlement,proto3" json:"latest_settlement,omitempty"` + ServerTimeMs int64 `protobuf:"varint,10,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RoomTurnoverRewardStatus) Reset() { + *x = RoomTurnoverRewardStatus{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RoomTurnoverRewardStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RoomTurnoverRewardStatus) ProtoMessage() {} + +func (x *RoomTurnoverRewardStatus) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + 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 RoomTurnoverRewardStatus.ProtoReflect.Descriptor instead. +func (*RoomTurnoverRewardStatus) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{94} +} + +func (x *RoomTurnoverRewardStatus) GetConfig() *RoomTurnoverRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +func (x *RoomTurnoverRewardStatus) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *RoomTurnoverRewardStatus) GetOwnerUserId() int64 { + if x != nil { + return x.OwnerUserId + } + return 0 +} + +func (x *RoomTurnoverRewardStatus) GetPeriodStartMs() int64 { + if x != nil { + return x.PeriodStartMs + } + return 0 +} + +func (x *RoomTurnoverRewardStatus) GetPeriodEndMs() int64 { + if x != nil { + return x.PeriodEndMs + } + return 0 +} + +func (x *RoomTurnoverRewardStatus) GetCurrentCoinSpent() int64 { + if x != nil { + return x.CurrentCoinSpent + } + return 0 +} + +func (x *RoomTurnoverRewardStatus) GetExpectedRewardCoinAmount() int64 { + if x != nil { + return x.ExpectedRewardCoinAmount + } + return 0 +} + +func (x *RoomTurnoverRewardStatus) GetMatchedTier() *RoomTurnoverRewardTier { + if x != nil { + return x.MatchedTier + } + return nil +} + +func (x *RoomTurnoverRewardStatus) GetLatestSettlement() *RoomTurnoverRewardSettlement { + if x != nil { + return x.LatestSettlement + } + return nil +} + +func (x *RoomTurnoverRewardStatus) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type GetRoomTurnoverRewardStatusRequest 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"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetRoomTurnoverRewardStatusRequest) Reset() { + *x = GetRoomTurnoverRewardStatusRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetRoomTurnoverRewardStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRoomTurnoverRewardStatusRequest) ProtoMessage() {} + +func (x *GetRoomTurnoverRewardStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + 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 GetRoomTurnoverRewardStatusRequest.ProtoReflect.Descriptor instead. +func (*GetRoomTurnoverRewardStatusRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{95} +} + +func (x *GetRoomTurnoverRewardStatusRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetRoomTurnoverRewardStatusRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *GetRoomTurnoverRewardStatusRequest) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *GetRoomTurnoverRewardStatusRequest) GetOwnerUserId() int64 { + if x != nil { + return x.OwnerUserId + } + return 0 +} + +type GetRoomTurnoverRewardStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Status *RoomTurnoverRewardStatus `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetRoomTurnoverRewardStatusResponse) Reset() { + *x = GetRoomTurnoverRewardStatusResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetRoomTurnoverRewardStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRoomTurnoverRewardStatusResponse) ProtoMessage() {} + +func (x *GetRoomTurnoverRewardStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + 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 GetRoomTurnoverRewardStatusResponse.ProtoReflect.Descriptor instead. +func (*GetRoomTurnoverRewardStatusResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{96} +} + +func (x *GetRoomTurnoverRewardStatusResponse) GetStatus() *RoomTurnoverRewardStatus { + if x != nil { + return x.Status + } + return nil +} + +type GetRoomTurnoverRewardConfigRequest 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 *GetRoomTurnoverRewardConfigRequest) Reset() { + *x = GetRoomTurnoverRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetRoomTurnoverRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRoomTurnoverRewardConfigRequest) ProtoMessage() {} + +func (x *GetRoomTurnoverRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + 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 GetRoomTurnoverRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*GetRoomTurnoverRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{97} +} + +func (x *GetRoomTurnoverRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +type GetRoomTurnoverRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *RoomTurnoverRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetRoomTurnoverRewardConfigResponse) Reset() { + *x = GetRoomTurnoverRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetRoomTurnoverRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetRoomTurnoverRewardConfigResponse) ProtoMessage() {} + +func (x *GetRoomTurnoverRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + 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 GetRoomTurnoverRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*GetRoomTurnoverRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{98} +} + +func (x *GetRoomTurnoverRewardConfigResponse) GetConfig() *RoomTurnoverRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type UpdateRoomTurnoverRewardConfigRequest 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 []*RoomTurnoverRewardTier `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 *UpdateRoomTurnoverRewardConfigRequest) Reset() { + *x = UpdateRoomTurnoverRewardConfigRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateRoomTurnoverRewardConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRoomTurnoverRewardConfigRequest) ProtoMessage() {} + +func (x *UpdateRoomTurnoverRewardConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + 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 UpdateRoomTurnoverRewardConfigRequest.ProtoReflect.Descriptor instead. +func (*UpdateRoomTurnoverRewardConfigRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{99} +} + +func (x *UpdateRoomTurnoverRewardConfigRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *UpdateRoomTurnoverRewardConfigRequest) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *UpdateRoomTurnoverRewardConfigRequest) GetTiers() []*RoomTurnoverRewardTier { + if x != nil { + return x.Tiers + } + return nil +} + +func (x *UpdateRoomTurnoverRewardConfigRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type UpdateRoomTurnoverRewardConfigResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Config *RoomTurnoverRewardConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateRoomTurnoverRewardConfigResponse) Reset() { + *x = UpdateRoomTurnoverRewardConfigResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateRoomTurnoverRewardConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRoomTurnoverRewardConfigResponse) ProtoMessage() {} + +func (x *UpdateRoomTurnoverRewardConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + 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 UpdateRoomTurnoverRewardConfigResponse.ProtoReflect.Descriptor instead. +func (*UpdateRoomTurnoverRewardConfigResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{100} +} + +func (x *UpdateRoomTurnoverRewardConfigResponse) GetConfig() *RoomTurnoverRewardConfig { + if x != nil { + return x.Config + } + return nil +} + +type ListRoomTurnoverRewardSettlementsRequest 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"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + PeriodStartMs int64 `protobuf:"varint,5,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) Reset() { + *x = ListRoomTurnoverRewardSettlementsRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRoomTurnoverRewardSettlementsRequest) ProtoMessage() {} + +func (x *ListRoomTurnoverRewardSettlementsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + 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 ListRoomTurnoverRewardSettlementsRequest.ProtoReflect.Descriptor instead. +func (*ListRoomTurnoverRewardSettlementsRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{101} +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetOwnerUserId() int64 { + if x != nil { + return x.OwnerUserId + } + return 0 +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetPeriodStartMs() int64 { + if x != nil { + return x.PeriodStartMs + } + return 0 +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListRoomTurnoverRewardSettlementsRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListRoomTurnoverRewardSettlementsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Settlements []*RoomTurnoverRewardSettlement `protobuf:"bytes,1,rep,name=settlements,proto3" json:"settlements,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListRoomTurnoverRewardSettlementsResponse) Reset() { + *x = ListRoomTurnoverRewardSettlementsResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListRoomTurnoverRewardSettlementsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListRoomTurnoverRewardSettlementsResponse) ProtoMessage() {} + +func (x *ListRoomTurnoverRewardSettlementsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + 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 ListRoomTurnoverRewardSettlementsResponse.ProtoReflect.Descriptor instead. +func (*ListRoomTurnoverRewardSettlementsResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{102} +} + +func (x *ListRoomTurnoverRewardSettlementsResponse) GetSettlements() []*RoomTurnoverRewardSettlement { + if x != nil { + return x.Settlements + } + return nil +} + +func (x *ListRoomTurnoverRewardSettlementsResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +type RetryRoomTurnoverRewardSettlementRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + SettlementId string `protobuf:"bytes,2,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` + OperatorAdminId int64 `protobuf:"varint,3,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RetryRoomTurnoverRewardSettlementRequest) Reset() { + *x = RetryRoomTurnoverRewardSettlementRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RetryRoomTurnoverRewardSettlementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetryRoomTurnoverRewardSettlementRequest) ProtoMessage() {} + +func (x *RetryRoomTurnoverRewardSettlementRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + 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 RetryRoomTurnoverRewardSettlementRequest.ProtoReflect.Descriptor instead. +func (*RetryRoomTurnoverRewardSettlementRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{103} +} + +func (x *RetryRoomTurnoverRewardSettlementRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *RetryRoomTurnoverRewardSettlementRequest) GetSettlementId() string { + if x != nil { + return x.SettlementId + } + return "" +} + +func (x *RetryRoomTurnoverRewardSettlementRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type RetryRoomTurnoverRewardSettlementResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Settlement *RoomTurnoverRewardSettlement `protobuf:"bytes,1,opt,name=settlement,proto3" json:"settlement,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RetryRoomTurnoverRewardSettlementResponse) Reset() { + *x = RetryRoomTurnoverRewardSettlementResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RetryRoomTurnoverRewardSettlementResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RetryRoomTurnoverRewardSettlementResponse) ProtoMessage() {} + +func (x *RetryRoomTurnoverRewardSettlementResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + 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 RetryRoomTurnoverRewardSettlementResponse.ProtoReflect.Descriptor instead. +func (*RetryRoomTurnoverRewardSettlementResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{104} +} + +func (x *RetryRoomTurnoverRewardSettlementResponse) GetSettlement() *RoomTurnoverRewardSettlement { + if x != nil { + return x.Settlement + } + return nil +} + // SevenDayCheckInReward 是七日签到配置中某一天的资源组奖励。 type SevenDayCheckInReward struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -5723,7 +8017,7 @@ type SevenDayCheckInReward struct { func (x *SevenDayCheckInReward) Reset() { *x = SevenDayCheckInReward{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + mi := &file_proto_activity_v1_activity_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5735,7 +8029,7 @@ func (x *SevenDayCheckInReward) String() string { func (*SevenDayCheckInReward) ProtoMessage() {} func (x *SevenDayCheckInReward) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[76] + mi := &file_proto_activity_v1_activity_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5748,7 +8042,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{76} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{105} } func (x *SevenDayCheckInReward) GetDayIndex() int32 { @@ -5781,7 +8075,7 @@ type SevenDayCheckInConfig struct { func (x *SevenDayCheckInConfig) Reset() { *x = SevenDayCheckInConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + mi := &file_proto_activity_v1_activity_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5793,7 +8087,7 @@ func (x *SevenDayCheckInConfig) String() string { func (*SevenDayCheckInConfig) ProtoMessage() {} func (x *SevenDayCheckInConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[77] + mi := &file_proto_activity_v1_activity_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5806,7 +8100,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{77} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{106} } func (x *SevenDayCheckInConfig) GetAppCode() string { @@ -5873,7 +8167,7 @@ type SevenDayCheckInRewardStatus struct { func (x *SevenDayCheckInRewardStatus) Reset() { *x = SevenDayCheckInRewardStatus{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + mi := &file_proto_activity_v1_activity_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5885,7 +8179,7 @@ func (x *SevenDayCheckInRewardStatus) String() string { func (*SevenDayCheckInRewardStatus) ProtoMessage() {} func (x *SevenDayCheckInRewardStatus) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[78] + mi := &file_proto_activity_v1_activity_proto_msgTypes[107] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5898,7 +8192,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{78} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{107} } func (x *SevenDayCheckInRewardStatus) GetDayIndex() int32 { @@ -5953,7 +8247,7 @@ type GetSevenDayCheckInStatusRequest struct { func (x *GetSevenDayCheckInStatusRequest) Reset() { *x = GetSevenDayCheckInStatusRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + mi := &file_proto_activity_v1_activity_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5965,7 +8259,7 @@ func (x *GetSevenDayCheckInStatusRequest) String() string { func (*GetSevenDayCheckInStatusRequest) ProtoMessage() {} func (x *GetSevenDayCheckInStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[79] + mi := &file_proto_activity_v1_activity_proto_msgTypes[108] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5978,7 +8272,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{79} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{108} } func (x *GetSevenDayCheckInStatusRequest) GetMeta() *RequestMeta { @@ -6015,7 +8309,7 @@ type GetSevenDayCheckInStatusResponse struct { func (x *GetSevenDayCheckInStatusResponse) Reset() { *x = GetSevenDayCheckInStatusResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + mi := &file_proto_activity_v1_activity_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6027,7 +8321,7 @@ func (x *GetSevenDayCheckInStatusResponse) String() string { func (*GetSevenDayCheckInStatusResponse) ProtoMessage() {} func (x *GetSevenDayCheckInStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[80] + mi := &file_proto_activity_v1_activity_proto_msgTypes[109] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6040,7 +8334,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{80} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{109} } func (x *GetSevenDayCheckInStatusResponse) GetEnabled() bool { @@ -6138,7 +8432,7 @@ type SignSevenDayCheckInRequest struct { func (x *SignSevenDayCheckInRequest) Reset() { *x = SignSevenDayCheckInRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + mi := &file_proto_activity_v1_activity_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6150,7 +8444,7 @@ func (x *SignSevenDayCheckInRequest) String() string { func (*SignSevenDayCheckInRequest) ProtoMessage() {} func (x *SignSevenDayCheckInRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[81] + mi := &file_proto_activity_v1_activity_proto_msgTypes[110] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6163,7 +8457,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{81} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{110} } func (x *SignSevenDayCheckInRequest) GetMeta() *RequestMeta { @@ -6204,7 +8498,7 @@ type SignSevenDayCheckInResponse struct { func (x *SignSevenDayCheckInResponse) Reset() { *x = SignSevenDayCheckInResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + mi := &file_proto_activity_v1_activity_proto_msgTypes[111] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6216,7 +8510,7 @@ func (x *SignSevenDayCheckInResponse) String() string { func (*SignSevenDayCheckInResponse) ProtoMessage() {} func (x *SignSevenDayCheckInResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[82] + mi := &file_proto_activity_v1_activity_proto_msgTypes[111] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6229,7 +8523,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{82} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{111} } func (x *SignSevenDayCheckInResponse) GetClaimId() string { @@ -6304,7 +8598,7 @@ type GetSevenDayCheckInConfigRequest struct { func (x *GetSevenDayCheckInConfigRequest) Reset() { *x = GetSevenDayCheckInConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + mi := &file_proto_activity_v1_activity_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6316,7 +8610,7 @@ func (x *GetSevenDayCheckInConfigRequest) String() string { func (*GetSevenDayCheckInConfigRequest) ProtoMessage() {} func (x *GetSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[83] + mi := &file_proto_activity_v1_activity_proto_msgTypes[112] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6329,7 +8623,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{83} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{112} } func (x *GetSevenDayCheckInConfigRequest) GetMeta() *RequestMeta { @@ -6348,7 +8642,7 @@ type GetSevenDayCheckInConfigResponse struct { func (x *GetSevenDayCheckInConfigResponse) Reset() { *x = GetSevenDayCheckInConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + mi := &file_proto_activity_v1_activity_proto_msgTypes[113] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6360,7 +8654,7 @@ func (x *GetSevenDayCheckInConfigResponse) String() string { func (*GetSevenDayCheckInConfigResponse) ProtoMessage() {} func (x *GetSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[84] + mi := &file_proto_activity_v1_activity_proto_msgTypes[113] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6373,7 +8667,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{84} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{113} } func (x *GetSevenDayCheckInConfigResponse) GetConfig() *SevenDayCheckInConfig { @@ -6395,7 +8689,7 @@ type UpdateSevenDayCheckInConfigRequest struct { func (x *UpdateSevenDayCheckInConfigRequest) Reset() { *x = UpdateSevenDayCheckInConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + mi := &file_proto_activity_v1_activity_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6407,7 +8701,7 @@ func (x *UpdateSevenDayCheckInConfigRequest) String() string { func (*UpdateSevenDayCheckInConfigRequest) ProtoMessage() {} func (x *UpdateSevenDayCheckInConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[85] + mi := &file_proto_activity_v1_activity_proto_msgTypes[114] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6420,7 +8714,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{85} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{114} } func (x *UpdateSevenDayCheckInConfigRequest) GetMeta() *RequestMeta { @@ -6460,7 +8754,7 @@ type UpdateSevenDayCheckInConfigResponse struct { func (x *UpdateSevenDayCheckInConfigResponse) Reset() { *x = UpdateSevenDayCheckInConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + mi := &file_proto_activity_v1_activity_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6472,7 +8766,7 @@ func (x *UpdateSevenDayCheckInConfigResponse) String() string { func (*UpdateSevenDayCheckInConfigResponse) ProtoMessage() {} func (x *UpdateSevenDayCheckInConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[86] + mi := &file_proto_activity_v1_activity_proto_msgTypes[115] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6485,7 +8779,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{86} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{115} } func (x *UpdateSevenDayCheckInConfigResponse) GetConfig() *SevenDayCheckInConfig { @@ -6520,7 +8814,7 @@ type SevenDayCheckInClaim struct { func (x *SevenDayCheckInClaim) Reset() { *x = SevenDayCheckInClaim{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + mi := &file_proto_activity_v1_activity_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6532,7 +8826,7 @@ func (x *SevenDayCheckInClaim) String() string { func (*SevenDayCheckInClaim) ProtoMessage() {} func (x *SevenDayCheckInClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[87] + mi := &file_proto_activity_v1_activity_proto_msgTypes[116] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6545,7 +8839,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{87} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{116} } func (x *SevenDayCheckInClaim) GetClaimId() string { @@ -6675,7 +8969,7 @@ type ListSevenDayCheckInClaimsRequest struct { func (x *ListSevenDayCheckInClaimsRequest) Reset() { *x = ListSevenDayCheckInClaimsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + mi := &file_proto_activity_v1_activity_proto_msgTypes[117] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6687,7 +8981,7 @@ func (x *ListSevenDayCheckInClaimsRequest) String() string { func (*ListSevenDayCheckInClaimsRequest) ProtoMessage() {} func (x *ListSevenDayCheckInClaimsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[88] + mi := &file_proto_activity_v1_activity_proto_msgTypes[117] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6700,7 +8994,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{88} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{117} } func (x *ListSevenDayCheckInClaimsRequest) GetMeta() *RequestMeta { @@ -6762,7 +9056,7 @@ type ListSevenDayCheckInClaimsResponse struct { func (x *ListSevenDayCheckInClaimsResponse) Reset() { *x = ListSevenDayCheckInClaimsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + mi := &file_proto_activity_v1_activity_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6774,7 +9068,7 @@ func (x *ListSevenDayCheckInClaimsResponse) String() string { func (*ListSevenDayCheckInClaimsResponse) ProtoMessage() {} func (x *ListSevenDayCheckInClaimsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[89] + mi := &file_proto_activity_v1_activity_proto_msgTypes[118] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6787,7 +9081,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{89} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{118} } func (x *ListSevenDayCheckInClaimsResponse) GetClaims() []*SevenDayCheckInClaim { @@ -6820,7 +9114,7 @@ type LevelTrack struct { func (x *LevelTrack) Reset() { *x = LevelTrack{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + mi := &file_proto_activity_v1_activity_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6832,7 +9126,7 @@ func (x *LevelTrack) String() string { func (*LevelTrack) ProtoMessage() {} func (x *LevelTrack) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[90] + mi := &file_proto_activity_v1_activity_proto_msgTypes[119] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6845,7 +9139,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{90} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{119} } func (x *LevelTrack) GetTrack() string { @@ -6918,7 +9212,7 @@ type LevelRule struct { func (x *LevelRule) Reset() { *x = LevelRule{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + mi := &file_proto_activity_v1_activity_proto_msgTypes[120] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6930,7 +9224,7 @@ func (x *LevelRule) String() string { func (*LevelRule) ProtoMessage() {} func (x *LevelRule) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[91] + mi := &file_proto_activity_v1_activity_proto_msgTypes[120] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6943,7 +9237,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{91} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{120} } func (x *LevelRule) GetTrack() string { @@ -7053,7 +9347,7 @@ type LevelTier struct { func (x *LevelTier) Reset() { *x = LevelTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + mi := &file_proto_activity_v1_activity_proto_msgTypes[121] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7065,7 +9359,7 @@ func (x *LevelTier) String() string { func (*LevelTier) ProtoMessage() {} func (x *LevelTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[92] + mi := &file_proto_activity_v1_activity_proto_msgTypes[121] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7078,7 +9372,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{92} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{121} } func (x *LevelTier) GetTierId() int64 { @@ -7201,7 +9495,7 @@ type LevelTrackOverview struct { func (x *LevelTrackOverview) Reset() { *x = LevelTrackOverview{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + mi := &file_proto_activity_v1_activity_proto_msgTypes[122] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7213,7 +9507,7 @@ func (x *LevelTrackOverview) String() string { func (*LevelTrackOverview) ProtoMessage() {} func (x *LevelTrackOverview) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[93] + mi := &file_proto_activity_v1_activity_proto_msgTypes[122] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7226,7 +9520,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{93} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{122} } func (x *LevelTrackOverview) GetTrack() string { @@ -7330,7 +9624,7 @@ type GetMyLevelOverviewRequest struct { func (x *GetMyLevelOverviewRequest) Reset() { *x = GetMyLevelOverviewRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + mi := &file_proto_activity_v1_activity_proto_msgTypes[123] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7342,7 +9636,7 @@ func (x *GetMyLevelOverviewRequest) String() string { func (*GetMyLevelOverviewRequest) ProtoMessage() {} func (x *GetMyLevelOverviewRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[94] + mi := &file_proto_activity_v1_activity_proto_msgTypes[123] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7355,7 +9649,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{94} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{123} } func (x *GetMyLevelOverviewRequest) GetMeta() *RequestMeta { @@ -7382,7 +9676,7 @@ type GetMyLevelOverviewResponse struct { func (x *GetMyLevelOverviewResponse) Reset() { *x = GetMyLevelOverviewResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + mi := &file_proto_activity_v1_activity_proto_msgTypes[124] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7394,7 +9688,7 @@ func (x *GetMyLevelOverviewResponse) String() string { func (*GetMyLevelOverviewResponse) ProtoMessage() {} func (x *GetMyLevelOverviewResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[95] + mi := &file_proto_activity_v1_activity_proto_msgTypes[124] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7407,7 +9701,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{95} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{124} } func (x *GetMyLevelOverviewResponse) GetTracks() []*LevelTrackOverview { @@ -7435,7 +9729,7 @@ type GetLevelTrackRequest struct { func (x *GetLevelTrackRequest) Reset() { *x = GetLevelTrackRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + mi := &file_proto_activity_v1_activity_proto_msgTypes[125] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7447,7 +9741,7 @@ func (x *GetLevelTrackRequest) String() string { func (*GetLevelTrackRequest) ProtoMessage() {} func (x *GetLevelTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[96] + mi := &file_proto_activity_v1_activity_proto_msgTypes[125] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7460,7 +9754,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{96} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{125} } func (x *GetLevelTrackRequest) GetMeta() *RequestMeta { @@ -7496,7 +9790,7 @@ type GetLevelTrackResponse struct { func (x *GetLevelTrackResponse) Reset() { *x = GetLevelTrackResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + mi := &file_proto_activity_v1_activity_proto_msgTypes[126] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7508,7 +9802,7 @@ func (x *GetLevelTrackResponse) String() string { func (*GetLevelTrackResponse) ProtoMessage() {} func (x *GetLevelTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[97] + mi := &file_proto_activity_v1_activity_proto_msgTypes[126] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7521,7 +9815,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{97} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{126} } func (x *GetLevelTrackResponse) GetOverview() *LevelTrackOverview { @@ -7568,7 +9862,7 @@ type LevelDisplayTrackProfile struct { func (x *LevelDisplayTrackProfile) Reset() { *x = LevelDisplayTrackProfile{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + mi := &file_proto_activity_v1_activity_proto_msgTypes[127] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7580,7 +9874,7 @@ func (x *LevelDisplayTrackProfile) String() string { func (*LevelDisplayTrackProfile) ProtoMessage() {} func (x *LevelDisplayTrackProfile) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[98] + mi := &file_proto_activity_v1_activity_proto_msgTypes[127] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7593,7 +9887,7 @@ func (x *LevelDisplayTrackProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use LevelDisplayTrackProfile.ProtoReflect.Descriptor instead. func (*LevelDisplayTrackProfile) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{98} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{127} } func (x *LevelDisplayTrackProfile) GetTrack() string { @@ -7658,7 +9952,7 @@ type UserLevelDisplayProfile struct { func (x *UserLevelDisplayProfile) Reset() { *x = UserLevelDisplayProfile{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + mi := &file_proto_activity_v1_activity_proto_msgTypes[128] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7670,7 +9964,7 @@ func (x *UserLevelDisplayProfile) String() string { func (*UserLevelDisplayProfile) ProtoMessage() {} func (x *UserLevelDisplayProfile) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[99] + mi := &file_proto_activity_v1_activity_proto_msgTypes[128] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7683,7 +9977,7 @@ func (x *UserLevelDisplayProfile) ProtoReflect() protoreflect.Message { // Deprecated: Use UserLevelDisplayProfile.ProtoReflect.Descriptor instead. func (*UserLevelDisplayProfile) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{99} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{128} } func (x *UserLevelDisplayProfile) GetUserId() int64 { @@ -7724,7 +10018,7 @@ type BatchGetUserLevelDisplayProfilesRequest struct { func (x *BatchGetUserLevelDisplayProfilesRequest) Reset() { *x = BatchGetUserLevelDisplayProfilesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + mi := &file_proto_activity_v1_activity_proto_msgTypes[129] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7736,7 +10030,7 @@ func (x *BatchGetUserLevelDisplayProfilesRequest) String() string { func (*BatchGetUserLevelDisplayProfilesRequest) ProtoMessage() {} func (x *BatchGetUserLevelDisplayProfilesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[100] + mi := &file_proto_activity_v1_activity_proto_msgTypes[129] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7749,7 +10043,7 @@ func (x *BatchGetUserLevelDisplayProfilesRequest) ProtoReflect() protoreflect.Me // Deprecated: Use BatchGetUserLevelDisplayProfilesRequest.ProtoReflect.Descriptor instead. func (*BatchGetUserLevelDisplayProfilesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{100} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{129} } func (x *BatchGetUserLevelDisplayProfilesRequest) GetMeta() *RequestMeta { @@ -7776,7 +10070,7 @@ type BatchGetUserLevelDisplayProfilesResponse struct { func (x *BatchGetUserLevelDisplayProfilesResponse) Reset() { *x = BatchGetUserLevelDisplayProfilesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + mi := &file_proto_activity_v1_activity_proto_msgTypes[130] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7788,7 +10082,7 @@ func (x *BatchGetUserLevelDisplayProfilesResponse) String() string { func (*BatchGetUserLevelDisplayProfilesResponse) ProtoMessage() {} func (x *BatchGetUserLevelDisplayProfilesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[101] + mi := &file_proto_activity_v1_activity_proto_msgTypes[130] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7801,7 +10095,7 @@ func (x *BatchGetUserLevelDisplayProfilesResponse) ProtoReflect() protoreflect.M // Deprecated: Use BatchGetUserLevelDisplayProfilesResponse.ProtoReflect.Descriptor instead. func (*BatchGetUserLevelDisplayProfilesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{101} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{130} } func (x *BatchGetUserLevelDisplayProfilesResponse) GetProfiles() []*UserLevelDisplayProfile { @@ -7840,7 +10134,7 @@ type LevelRewardJob struct { func (x *LevelRewardJob) Reset() { *x = LevelRewardJob{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + mi := &file_proto_activity_v1_activity_proto_msgTypes[131] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7852,7 +10146,7 @@ func (x *LevelRewardJob) String() string { func (*LevelRewardJob) ProtoMessage() {} func (x *LevelRewardJob) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[102] + mi := &file_proto_activity_v1_activity_proto_msgTypes[131] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7865,7 +10159,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{102} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{131} } func (x *LevelRewardJob) GetRewardJobId() string { @@ -7973,7 +10267,7 @@ type ListLevelRewardsRequest struct { func (x *ListLevelRewardsRequest) Reset() { *x = ListLevelRewardsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + mi := &file_proto_activity_v1_activity_proto_msgTypes[132] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7985,7 +10279,7 @@ func (x *ListLevelRewardsRequest) String() string { func (*ListLevelRewardsRequest) ProtoMessage() {} func (x *ListLevelRewardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[103] + mi := &file_proto_activity_v1_activity_proto_msgTypes[132] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7998,7 +10292,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{103} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{132} } func (x *ListLevelRewardsRequest) GetMeta() *RequestMeta { @@ -8053,7 +10347,7 @@ type ListLevelRewardsResponse struct { func (x *ListLevelRewardsResponse) Reset() { *x = ListLevelRewardsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + mi := &file_proto_activity_v1_activity_proto_msgTypes[133] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8065,7 +10359,7 @@ func (x *ListLevelRewardsResponse) String() string { func (*ListLevelRewardsResponse) ProtoMessage() {} func (x *ListLevelRewardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[104] + mi := &file_proto_activity_v1_activity_proto_msgTypes[133] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8078,7 +10372,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{104} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{133} } func (x *ListLevelRewardsResponse) GetRewards() []*LevelRewardJob { @@ -8115,7 +10409,7 @@ type ConsumeLevelEventRequest struct { func (x *ConsumeLevelEventRequest) Reset() { *x = ConsumeLevelEventRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[105] + mi := &file_proto_activity_v1_activity_proto_msgTypes[134] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8127,7 +10421,7 @@ func (x *ConsumeLevelEventRequest) String() string { func (*ConsumeLevelEventRequest) ProtoMessage() {} func (x *ConsumeLevelEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[105] + mi := &file_proto_activity_v1_activity_proto_msgTypes[134] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8140,7 +10434,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{105} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{134} } func (x *ConsumeLevelEventRequest) GetMeta() *RequestMeta { @@ -8234,7 +10528,7 @@ type ConsumeLevelEventResponse struct { func (x *ConsumeLevelEventResponse) Reset() { *x = ConsumeLevelEventResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[106] + mi := &file_proto_activity_v1_activity_proto_msgTypes[135] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8246,7 +10540,7 @@ func (x *ConsumeLevelEventResponse) String() string { func (*ConsumeLevelEventResponse) ProtoMessage() {} func (x *ConsumeLevelEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[106] + mi := &file_proto_activity_v1_activity_proto_msgTypes[135] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8259,7 +10553,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{106} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{135} } func (x *ConsumeLevelEventResponse) GetEventId() string { @@ -8316,7 +10610,7 @@ type RegistrationLevelBadgeGrant struct { func (x *RegistrationLevelBadgeGrant) Reset() { *x = RegistrationLevelBadgeGrant{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[107] + mi := &file_proto_activity_v1_activity_proto_msgTypes[136] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8328,7 +10622,7 @@ func (x *RegistrationLevelBadgeGrant) String() string { func (*RegistrationLevelBadgeGrant) ProtoMessage() {} func (x *RegistrationLevelBadgeGrant) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[107] + mi := &file_proto_activity_v1_activity_proto_msgTypes[136] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8341,7 +10635,7 @@ func (x *RegistrationLevelBadgeGrant) ProtoReflect() protoreflect.Message { // Deprecated: Use RegistrationLevelBadgeGrant.ProtoReflect.Descriptor instead. func (*RegistrationLevelBadgeGrant) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{107} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{136} } func (x *RegistrationLevelBadgeGrant) GetTrack() string { @@ -8383,7 +10677,7 @@ type IssueRegistrationLevelBadgesRequest struct { func (x *IssueRegistrationLevelBadgesRequest) Reset() { *x = IssueRegistrationLevelBadgesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[108] + mi := &file_proto_activity_v1_activity_proto_msgTypes[137] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8395,7 +10689,7 @@ func (x *IssueRegistrationLevelBadgesRequest) String() string { func (*IssueRegistrationLevelBadgesRequest) ProtoMessage() {} func (x *IssueRegistrationLevelBadgesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[108] + mi := &file_proto_activity_v1_activity_proto_msgTypes[137] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8408,7 +10702,7 @@ func (x *IssueRegistrationLevelBadgesRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use IssueRegistrationLevelBadgesRequest.ProtoReflect.Descriptor instead. func (*IssueRegistrationLevelBadgesRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{108} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{137} } func (x *IssueRegistrationLevelBadgesRequest) GetMeta() *RequestMeta { @@ -8442,7 +10736,7 @@ type IssueRegistrationLevelBadgesResponse struct { func (x *IssueRegistrationLevelBadgesResponse) Reset() { *x = IssueRegistrationLevelBadgesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[109] + mi := &file_proto_activity_v1_activity_proto_msgTypes[138] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8454,7 +10748,7 @@ func (x *IssueRegistrationLevelBadgesResponse) String() string { func (*IssueRegistrationLevelBadgesResponse) ProtoMessage() {} func (x *IssueRegistrationLevelBadgesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[109] + mi := &file_proto_activity_v1_activity_proto_msgTypes[138] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8467,7 +10761,7 @@ func (x *IssueRegistrationLevelBadgesResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use IssueRegistrationLevelBadgesResponse.ProtoReflect.Descriptor instead. func (*IssueRegistrationLevelBadgesResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{109} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{138} } func (x *IssueRegistrationLevelBadgesResponse) GetGrants() []*RegistrationLevelBadgeGrant { @@ -8498,7 +10792,7 @@ type UpsertLevelTrackRequest struct { func (x *UpsertLevelTrackRequest) Reset() { *x = UpsertLevelTrackRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[110] + mi := &file_proto_activity_v1_activity_proto_msgTypes[139] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8510,7 +10804,7 @@ func (x *UpsertLevelTrackRequest) String() string { func (*UpsertLevelTrackRequest) ProtoMessage() {} func (x *UpsertLevelTrackRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[110] + mi := &file_proto_activity_v1_activity_proto_msgTypes[139] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8523,7 +10817,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{110} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{139} } func (x *UpsertLevelTrackRequest) GetMeta() *RequestMeta { @@ -8578,7 +10872,7 @@ type UpsertLevelTrackResponse struct { func (x *UpsertLevelTrackResponse) Reset() { *x = UpsertLevelTrackResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[111] + mi := &file_proto_activity_v1_activity_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8590,7 +10884,7 @@ func (x *UpsertLevelTrackResponse) String() string { func (*UpsertLevelTrackResponse) ProtoMessage() {} func (x *UpsertLevelTrackResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[111] + mi := &file_proto_activity_v1_activity_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8603,7 +10897,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{111} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{140} } func (x *UpsertLevelTrackResponse) GetTrack() *LevelTrack { @@ -8638,7 +10932,7 @@ type UpsertLevelRuleRequest struct { func (x *UpsertLevelRuleRequest) Reset() { *x = UpsertLevelRuleRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[112] + mi := &file_proto_activity_v1_activity_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8650,7 +10944,7 @@ func (x *UpsertLevelRuleRequest) String() string { func (*UpsertLevelRuleRequest) ProtoMessage() {} func (x *UpsertLevelRuleRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[112] + mi := &file_proto_activity_v1_activity_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8663,7 +10957,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{112} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{141} } func (x *UpsertLevelRuleRequest) GetMeta() *RequestMeta { @@ -8746,7 +11040,7 @@ type UpsertLevelRuleResponse struct { func (x *UpsertLevelRuleResponse) Reset() { *x = UpsertLevelRuleResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[113] + mi := &file_proto_activity_v1_activity_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8758,7 +11052,7 @@ func (x *UpsertLevelRuleResponse) String() string { func (*UpsertLevelRuleResponse) ProtoMessage() {} func (x *UpsertLevelRuleResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[113] + mi := &file_proto_activity_v1_activity_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8771,7 +11065,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{113} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{142} } func (x *UpsertLevelRuleResponse) GetRule() *LevelRule { @@ -8808,7 +11102,7 @@ type UpsertLevelTierRequest struct { func (x *UpsertLevelTierRequest) Reset() { *x = UpsertLevelTierRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[114] + mi := &file_proto_activity_v1_activity_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8820,7 +11114,7 @@ func (x *UpsertLevelTierRequest) String() string { func (*UpsertLevelTierRequest) ProtoMessage() {} func (x *UpsertLevelTierRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[114] + mi := &file_proto_activity_v1_activity_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8833,7 +11127,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{114} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{143} } func (x *UpsertLevelTierRequest) GetMeta() *RequestMeta { @@ -8930,7 +11224,7 @@ type UpsertLevelTierResponse struct { func (x *UpsertLevelTierResponse) Reset() { *x = UpsertLevelTierResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[115] + mi := &file_proto_activity_v1_activity_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8942,7 +11236,7 @@ func (x *UpsertLevelTierResponse) String() string { func (*UpsertLevelTierResponse) ProtoMessage() {} func (x *UpsertLevelTierResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[115] + mi := &file_proto_activity_v1_activity_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8955,7 +11249,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{115} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{144} } func (x *UpsertLevelTierResponse) GetTier() *LevelTier { @@ -8984,7 +11278,7 @@ type ListLevelConfigRequest struct { func (x *ListLevelConfigRequest) Reset() { *x = ListLevelConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[116] + mi := &file_proto_activity_v1_activity_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8996,7 +11290,7 @@ func (x *ListLevelConfigRequest) String() string { func (*ListLevelConfigRequest) ProtoMessage() {} func (x *ListLevelConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[116] + mi := &file_proto_activity_v1_activity_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9009,7 +11303,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{116} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{145} } func (x *ListLevelConfigRequest) GetMeta() *RequestMeta { @@ -9045,7 +11339,7 @@ type ListLevelConfigResponse struct { func (x *ListLevelConfigResponse) Reset() { *x = ListLevelConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[117] + mi := &file_proto_activity_v1_activity_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9057,7 +11351,7 @@ func (x *ListLevelConfigResponse) String() string { func (*ListLevelConfigResponse) ProtoMessage() {} func (x *ListLevelConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[117] + mi := &file_proto_activity_v1_activity_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9070,7 +11364,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{117} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{146} } func (x *ListLevelConfigResponse) GetTracks() []*LevelTrack { @@ -9116,7 +11410,7 @@ type AchievementCondition struct { func (x *AchievementCondition) Reset() { *x = AchievementCondition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[118] + mi := &file_proto_activity_v1_activity_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9128,7 +11422,7 @@ func (x *AchievementCondition) String() string { func (*AchievementCondition) ProtoMessage() {} func (x *AchievementCondition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[118] + mi := &file_proto_activity_v1_activity_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9141,7 +11435,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{118} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{147} } func (x *AchievementCondition) GetConditionId() string { @@ -9222,7 +11516,7 @@ type AchievementDefinition struct { func (x *AchievementDefinition) Reset() { *x = AchievementDefinition{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[119] + mi := &file_proto_activity_v1_activity_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9234,7 +11528,7 @@ func (x *AchievementDefinition) String() string { func (*AchievementDefinition) ProtoMessage() {} func (x *AchievementDefinition) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[119] + mi := &file_proto_activity_v1_activity_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9247,7 +11541,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{119} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{148} } func (x *AchievementDefinition) GetAchievementId() string { @@ -9412,7 +11706,7 @@ type UserAchievement struct { func (x *UserAchievement) Reset() { *x = UserAchievement{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[120] + mi := &file_proto_activity_v1_activity_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9424,7 +11718,7 @@ func (x *UserAchievement) String() string { func (*UserAchievement) ProtoMessage() {} func (x *UserAchievement) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[120] + mi := &file_proto_activity_v1_activity_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9437,7 +11731,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{120} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{149} } func (x *UserAchievement) GetDefinition() *AchievementDefinition { @@ -9503,7 +11797,7 @@ type ListAchievementsRequest struct { func (x *ListAchievementsRequest) Reset() { *x = ListAchievementsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[121] + mi := &file_proto_activity_v1_activity_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9515,7 +11809,7 @@ func (x *ListAchievementsRequest) String() string { func (*ListAchievementsRequest) ProtoMessage() {} func (x *ListAchievementsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[121] + mi := &file_proto_activity_v1_activity_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9528,7 +11822,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{121} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{150} } func (x *ListAchievementsRequest) GetMeta() *RequestMeta { @@ -9584,7 +11878,7 @@ type ListAchievementsResponse struct { func (x *ListAchievementsResponse) Reset() { *x = ListAchievementsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[122] + mi := &file_proto_activity_v1_activity_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9596,7 +11890,7 @@ func (x *ListAchievementsResponse) String() string { func (*ListAchievementsResponse) ProtoMessage() {} func (x *ListAchievementsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[122] + mi := &file_proto_activity_v1_activity_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9609,7 +11903,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{122} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{151} } func (x *ListAchievementsResponse) GetAchievements() []*UserAchievement { @@ -9650,7 +11944,7 @@ type ConsumeAchievementEventRequest struct { func (x *ConsumeAchievementEventRequest) Reset() { *x = ConsumeAchievementEventRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[123] + mi := &file_proto_activity_v1_activity_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9662,7 +11956,7 @@ func (x *ConsumeAchievementEventRequest) String() string { func (*ConsumeAchievementEventRequest) ProtoMessage() {} func (x *ConsumeAchievementEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[123] + mi := &file_proto_activity_v1_activity_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9675,7 +11969,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{123} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{152} } func (x *ConsumeAchievementEventRequest) GetMeta() *RequestMeta { @@ -9754,7 +12048,7 @@ type ConsumeAchievementEventResponse struct { func (x *ConsumeAchievementEventResponse) Reset() { *x = ConsumeAchievementEventResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[124] + mi := &file_proto_activity_v1_activity_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9766,7 +12060,7 @@ func (x *ConsumeAchievementEventResponse) String() string { func (*ConsumeAchievementEventResponse) ProtoMessage() {} func (x *ConsumeAchievementEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[124] + mi := &file_proto_activity_v1_activity_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9779,7 +12073,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{124} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{153} } func (x *ConsumeAchievementEventResponse) GetEventId() string { @@ -9834,7 +12128,7 @@ type BadgeDisplayItem struct { func (x *BadgeDisplayItem) Reset() { *x = BadgeDisplayItem{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[125] + mi := &file_proto_activity_v1_activity_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9846,7 +12140,7 @@ func (x *BadgeDisplayItem) String() string { func (*BadgeDisplayItem) ProtoMessage() {} func (x *BadgeDisplayItem) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[125] + mi := &file_proto_activity_v1_activity_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9859,7 +12153,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{125} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{154} } func (x *BadgeDisplayItem) GetSlot() string { @@ -9935,7 +12229,7 @@ type ListMyBadgesRequest struct { func (x *ListMyBadgesRequest) Reset() { *x = ListMyBadgesRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[126] + mi := &file_proto_activity_v1_activity_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -9947,7 +12241,7 @@ func (x *ListMyBadgesRequest) String() string { func (*ListMyBadgesRequest) ProtoMessage() {} func (x *ListMyBadgesRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[126] + mi := &file_proto_activity_v1_activity_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -9960,7 +12254,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{126} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{155} } func (x *ListMyBadgesRequest) GetMeta() *RequestMeta { @@ -9989,7 +12283,7 @@ type ListMyBadgesResponse struct { func (x *ListMyBadgesResponse) Reset() { *x = ListMyBadgesResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[127] + mi := &file_proto_activity_v1_activity_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10001,7 +12295,7 @@ func (x *ListMyBadgesResponse) String() string { func (*ListMyBadgesResponse) ProtoMessage() {} func (x *ListMyBadgesResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[127] + mi := &file_proto_activity_v1_activity_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10014,7 +12308,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{127} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{156} } func (x *ListMyBadgesResponse) GetStripBadges() []*BadgeDisplayItem { @@ -10058,7 +12352,7 @@ type SetBadgeDisplayRequest struct { func (x *SetBadgeDisplayRequest) Reset() { *x = SetBadgeDisplayRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[128] + mi := &file_proto_activity_v1_activity_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10070,7 +12364,7 @@ func (x *SetBadgeDisplayRequest) String() string { func (*SetBadgeDisplayRequest) ProtoMessage() {} func (x *SetBadgeDisplayRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[128] + mi := &file_proto_activity_v1_activity_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10083,7 +12377,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{128} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{157} } func (x *SetBadgeDisplayRequest) GetMeta() *RequestMeta { @@ -10130,7 +12424,7 @@ type SetBadgeDisplayResponse struct { func (x *SetBadgeDisplayResponse) Reset() { *x = SetBadgeDisplayResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[129] + mi := &file_proto_activity_v1_activity_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10142,7 +12436,7 @@ func (x *SetBadgeDisplayResponse) String() string { func (*SetBadgeDisplayResponse) ProtoMessage() {} func (x *SetBadgeDisplayResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[129] + mi := &file_proto_activity_v1_activity_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10155,7 +12449,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{129} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{158} } func (x *SetBadgeDisplayResponse) GetProfile() *ListMyBadgesResponse { @@ -10191,7 +12485,7 @@ type UpsertAchievementDefinitionRequest struct { func (x *UpsertAchievementDefinitionRequest) Reset() { *x = UpsertAchievementDefinitionRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[130] + mi := &file_proto_activity_v1_activity_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10203,7 +12497,7 @@ func (x *UpsertAchievementDefinitionRequest) String() string { func (*UpsertAchievementDefinitionRequest) ProtoMessage() {} func (x *UpsertAchievementDefinitionRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[130] + mi := &file_proto_activity_v1_activity_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10216,7 +12510,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{130} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{159} } func (x *UpsertAchievementDefinitionRequest) GetMeta() *RequestMeta { @@ -10355,7 +12649,7 @@ type UpsertAchievementDefinitionResponse struct { func (x *UpsertAchievementDefinitionResponse) Reset() { *x = UpsertAchievementDefinitionResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[131] + mi := &file_proto_activity_v1_activity_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10367,7 +12661,7 @@ func (x *UpsertAchievementDefinitionResponse) String() string { func (*UpsertAchievementDefinitionResponse) ProtoMessage() {} func (x *UpsertAchievementDefinitionResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[131] + mi := &file_proto_activity_v1_activity_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10380,7 +12674,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{131} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{160} } func (x *UpsertAchievementDefinitionResponse) GetAchievement() *AchievementDefinition { @@ -10419,7 +12713,7 @@ type LuckyGiftMeta struct { func (x *LuckyGiftMeta) Reset() { *x = LuckyGiftMeta{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[132] + mi := &file_proto_activity_v1_activity_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10431,7 +12725,7 @@ func (x *LuckyGiftMeta) String() string { func (*LuckyGiftMeta) ProtoMessage() {} func (x *LuckyGiftMeta) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[132] + mi := &file_proto_activity_v1_activity_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10444,7 +12738,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{132} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{161} } func (x *LuckyGiftMeta) GetMeta() *RequestMeta { @@ -10553,7 +12847,7 @@ type LuckyGiftTier struct { func (x *LuckyGiftTier) Reset() { *x = LuckyGiftTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[133] + mi := &file_proto_activity_v1_activity_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10565,7 +12859,7 @@ func (x *LuckyGiftTier) String() string { func (*LuckyGiftTier) ProtoMessage() {} func (x *LuckyGiftTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[133] + mi := &file_proto_activity_v1_activity_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10578,7 +12872,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{133} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{162} } func (x *LuckyGiftTier) GetPool() string { @@ -10678,7 +12972,7 @@ type LuckyGiftConfig struct { func (x *LuckyGiftConfig) Reset() { *x = LuckyGiftConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[134] + mi := &file_proto_activity_v1_activity_proto_msgTypes[163] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -10690,7 +12984,7 @@ func (x *LuckyGiftConfig) String() string { func (*LuckyGiftConfig) ProtoMessage() {} func (x *LuckyGiftConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[134] + mi := &file_proto_activity_v1_activity_proto_msgTypes[163] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -10703,7 +12997,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{134} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{163} } func (x *LuckyGiftConfig) GetAppCode() string { @@ -11002,7 +13296,7 @@ type LuckyGiftRuleTier struct { func (x *LuckyGiftRuleTier) Reset() { *x = LuckyGiftRuleTier{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[135] + mi := &file_proto_activity_v1_activity_proto_msgTypes[164] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11014,7 +13308,7 @@ func (x *LuckyGiftRuleTier) String() string { func (*LuckyGiftRuleTier) ProtoMessage() {} func (x *LuckyGiftRuleTier) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[135] + mi := &file_proto_activity_v1_activity_proto_msgTypes[164] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11027,7 +13321,7 @@ func (x *LuckyGiftRuleTier) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftRuleTier.ProtoReflect.Descriptor instead. func (*LuckyGiftRuleTier) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{135} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{164} } func (x *LuckyGiftRuleTier) GetStage() string { @@ -11096,7 +13390,7 @@ type LuckyGiftRuleStage struct { func (x *LuckyGiftRuleStage) Reset() { *x = LuckyGiftRuleStage{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[136] + mi := &file_proto_activity_v1_activity_proto_msgTypes[165] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11108,7 +13402,7 @@ func (x *LuckyGiftRuleStage) String() string { func (*LuckyGiftRuleStage) ProtoMessage() {} func (x *LuckyGiftRuleStage) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[136] + mi := &file_proto_activity_v1_activity_proto_msgTypes[165] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11121,7 +13415,7 @@ func (x *LuckyGiftRuleStage) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftRuleStage.ProtoReflect.Descriptor instead. func (*LuckyGiftRuleStage) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{136} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{165} } func (x *LuckyGiftRuleStage) GetStage() string { @@ -11167,7 +13461,7 @@ type LuckyGiftRuleConfig struct { func (x *LuckyGiftRuleConfig) Reset() { *x = LuckyGiftRuleConfig{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[137] + mi := &file_proto_activity_v1_activity_proto_msgTypes[166] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11179,7 +13473,7 @@ func (x *LuckyGiftRuleConfig) String() string { func (*LuckyGiftRuleConfig) ProtoMessage() {} func (x *LuckyGiftRuleConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[137] + mi := &file_proto_activity_v1_activity_proto_msgTypes[166] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11192,7 +13486,7 @@ func (x *LuckyGiftRuleConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftRuleConfig.ProtoReflect.Descriptor instead. func (*LuckyGiftRuleConfig) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{137} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{166} } func (x *LuckyGiftRuleConfig) GetAppCode() string { @@ -11355,7 +13649,7 @@ type CheckLuckyGiftRequest struct { func (x *CheckLuckyGiftRequest) Reset() { *x = CheckLuckyGiftRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[138] + mi := &file_proto_activity_v1_activity_proto_msgTypes[167] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11367,7 +13661,7 @@ func (x *CheckLuckyGiftRequest) String() string { func (*CheckLuckyGiftRequest) ProtoMessage() {} func (x *CheckLuckyGiftRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[138] + mi := &file_proto_activity_v1_activity_proto_msgTypes[167] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11380,7 +13674,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{138} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{167} } func (x *CheckLuckyGiftRequest) GetMeta() *RequestMeta { @@ -11434,7 +13728,7 @@ type CheckLuckyGiftResponse struct { func (x *CheckLuckyGiftResponse) Reset() { *x = CheckLuckyGiftResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[139] + mi := &file_proto_activity_v1_activity_proto_msgTypes[168] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11446,7 +13740,7 @@ func (x *CheckLuckyGiftResponse) String() string { func (*CheckLuckyGiftResponse) ProtoMessage() {} func (x *CheckLuckyGiftResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[139] + mi := &file_proto_activity_v1_activity_proto_msgTypes[168] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11459,7 +13753,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{139} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{168} } func (x *CheckLuckyGiftResponse) GetEnabled() bool { @@ -11549,7 +13843,7 @@ type LuckyGiftDrawResult struct { func (x *LuckyGiftDrawResult) Reset() { *x = LuckyGiftDrawResult{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[140] + mi := &file_proto_activity_v1_activity_proto_msgTypes[169] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11561,7 +13855,7 @@ func (x *LuckyGiftDrawResult) String() string { func (*LuckyGiftDrawResult) ProtoMessage() {} func (x *LuckyGiftDrawResult) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[140] + mi := &file_proto_activity_v1_activity_proto_msgTypes[169] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11574,7 +13868,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{140} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{169} } func (x *LuckyGiftDrawResult) GetDrawId() string { @@ -11747,7 +14041,7 @@ type ExecuteLuckyGiftDrawRequest struct { func (x *ExecuteLuckyGiftDrawRequest) Reset() { *x = ExecuteLuckyGiftDrawRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[141] + mi := &file_proto_activity_v1_activity_proto_msgTypes[170] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11759,7 +14053,7 @@ func (x *ExecuteLuckyGiftDrawRequest) String() string { func (*ExecuteLuckyGiftDrawRequest) ProtoMessage() {} func (x *ExecuteLuckyGiftDrawRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[141] + mi := &file_proto_activity_v1_activity_proto_msgTypes[170] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11772,7 +14066,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{141} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{170} } func (x *ExecuteLuckyGiftDrawRequest) GetLuckyGift() *LuckyGiftMeta { @@ -11791,7 +14085,7 @@ type ExecuteLuckyGiftDrawResponse struct { func (x *ExecuteLuckyGiftDrawResponse) Reset() { *x = ExecuteLuckyGiftDrawResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[142] + mi := &file_proto_activity_v1_activity_proto_msgTypes[171] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11803,7 +14097,7 @@ func (x *ExecuteLuckyGiftDrawResponse) String() string { func (*ExecuteLuckyGiftDrawResponse) ProtoMessage() {} func (x *ExecuteLuckyGiftDrawResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[142] + mi := &file_proto_activity_v1_activity_proto_msgTypes[171] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11816,7 +14110,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{142} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{171} } func (x *ExecuteLuckyGiftDrawResponse) GetResult() *LuckyGiftDrawResult { @@ -11837,7 +14131,7 @@ type GetLuckyGiftConfigRequest struct { func (x *GetLuckyGiftConfigRequest) Reset() { *x = GetLuckyGiftConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[143] + mi := &file_proto_activity_v1_activity_proto_msgTypes[172] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11849,7 +14143,7 @@ func (x *GetLuckyGiftConfigRequest) String() string { func (*GetLuckyGiftConfigRequest) ProtoMessage() {} func (x *GetLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[143] + mi := &file_proto_activity_v1_activity_proto_msgTypes[172] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11862,7 +14156,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{143} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{172} } func (x *GetLuckyGiftConfigRequest) GetMeta() *RequestMeta { @@ -11895,7 +14189,7 @@ type GetLuckyGiftConfigResponse struct { func (x *GetLuckyGiftConfigResponse) Reset() { *x = GetLuckyGiftConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[144] + mi := &file_proto_activity_v1_activity_proto_msgTypes[173] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11907,7 +14201,7 @@ func (x *GetLuckyGiftConfigResponse) String() string { func (*GetLuckyGiftConfigResponse) ProtoMessage() {} func (x *GetLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[144] + mi := &file_proto_activity_v1_activity_proto_msgTypes[173] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11920,7 +14214,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{144} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{173} } func (x *GetLuckyGiftConfigResponse) GetConfig() *LuckyGiftRuleConfig { @@ -11941,7 +14235,7 @@ type UpsertLuckyGiftConfigRequest struct { func (x *UpsertLuckyGiftConfigRequest) Reset() { *x = UpsertLuckyGiftConfigRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[145] + mi := &file_proto_activity_v1_activity_proto_msgTypes[174] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -11953,7 +14247,7 @@ func (x *UpsertLuckyGiftConfigRequest) String() string { func (*UpsertLuckyGiftConfigRequest) ProtoMessage() {} func (x *UpsertLuckyGiftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[145] + mi := &file_proto_activity_v1_activity_proto_msgTypes[174] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -11966,7 +14260,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{145} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{174} } func (x *UpsertLuckyGiftConfigRequest) GetMeta() *RequestMeta { @@ -11999,7 +14293,7 @@ type UpsertLuckyGiftConfigResponse struct { func (x *UpsertLuckyGiftConfigResponse) Reset() { *x = UpsertLuckyGiftConfigResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[146] + mi := &file_proto_activity_v1_activity_proto_msgTypes[175] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12011,7 +14305,7 @@ func (x *UpsertLuckyGiftConfigResponse) String() string { func (*UpsertLuckyGiftConfigResponse) ProtoMessage() {} func (x *UpsertLuckyGiftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[146] + mi := &file_proto_activity_v1_activity_proto_msgTypes[175] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12024,7 +14318,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{146} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{175} } func (x *UpsertLuckyGiftConfigResponse) GetConfig() *LuckyGiftRuleConfig { @@ -12043,7 +14337,7 @@ type ListLuckyGiftConfigsRequest struct { func (x *ListLuckyGiftConfigsRequest) Reset() { *x = ListLuckyGiftConfigsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[147] + mi := &file_proto_activity_v1_activity_proto_msgTypes[176] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12055,7 +14349,7 @@ func (x *ListLuckyGiftConfigsRequest) String() string { func (*ListLuckyGiftConfigsRequest) ProtoMessage() {} func (x *ListLuckyGiftConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[147] + mi := &file_proto_activity_v1_activity_proto_msgTypes[176] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12068,7 +14362,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{147} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{176} } func (x *ListLuckyGiftConfigsRequest) GetMeta() *RequestMeta { @@ -12087,7 +14381,7 @@ type ListLuckyGiftConfigsResponse struct { func (x *ListLuckyGiftConfigsResponse) Reset() { *x = ListLuckyGiftConfigsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[148] + mi := &file_proto_activity_v1_activity_proto_msgTypes[177] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12099,7 +14393,7 @@ func (x *ListLuckyGiftConfigsResponse) String() string { func (*ListLuckyGiftConfigsResponse) ProtoMessage() {} func (x *ListLuckyGiftConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[148] + mi := &file_proto_activity_v1_activity_proto_msgTypes[177] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12112,7 +14406,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{148} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{177} } func (x *ListLuckyGiftConfigsResponse) GetConfigs() []*LuckyGiftRuleConfig { @@ -12138,7 +14432,7 @@ type ListLuckyGiftDrawsRequest struct { func (x *ListLuckyGiftDrawsRequest) Reset() { *x = ListLuckyGiftDrawsRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[149] + mi := &file_proto_activity_v1_activity_proto_msgTypes[178] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12150,7 +14444,7 @@ func (x *ListLuckyGiftDrawsRequest) String() string { func (*ListLuckyGiftDrawsRequest) ProtoMessage() {} func (x *ListLuckyGiftDrawsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[149] + mi := &file_proto_activity_v1_activity_proto_msgTypes[178] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12163,7 +14457,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{149} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{178} } func (x *ListLuckyGiftDrawsRequest) GetMeta() *RequestMeta { @@ -12232,7 +14526,7 @@ type ListLuckyGiftDrawsResponse struct { func (x *ListLuckyGiftDrawsResponse) Reset() { *x = ListLuckyGiftDrawsResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[150] + mi := &file_proto_activity_v1_activity_proto_msgTypes[179] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12244,7 +14538,7 @@ func (x *ListLuckyGiftDrawsResponse) String() string { func (*ListLuckyGiftDrawsResponse) ProtoMessage() {} func (x *ListLuckyGiftDrawsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[150] + mi := &file_proto_activity_v1_activity_proto_msgTypes[179] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12257,7 +14551,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{150} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{179} } func (x *ListLuckyGiftDrawsResponse) GetDraws() []*LuckyGiftDrawResult { @@ -12295,7 +14589,7 @@ type LuckyGiftDrawSummary struct { func (x *LuckyGiftDrawSummary) Reset() { *x = LuckyGiftDrawSummary{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[151] + mi := &file_proto_activity_v1_activity_proto_msgTypes[180] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12307,7 +14601,7 @@ func (x *LuckyGiftDrawSummary) String() string { func (*LuckyGiftDrawSummary) ProtoMessage() {} func (x *LuckyGiftDrawSummary) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[151] + mi := &file_proto_activity_v1_activity_proto_msgTypes[180] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12320,7 +14614,7 @@ func (x *LuckyGiftDrawSummary) ProtoReflect() protoreflect.Message { // Deprecated: Use LuckyGiftDrawSummary.ProtoReflect.Descriptor instead. func (*LuckyGiftDrawSummary) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{151} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{180} } func (x *LuckyGiftDrawSummary) GetPoolId() string { @@ -12428,7 +14722,7 @@ type GetLuckyGiftDrawSummaryRequest struct { func (x *GetLuckyGiftDrawSummaryRequest) Reset() { *x = GetLuckyGiftDrawSummaryRequest{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[152] + mi := &file_proto_activity_v1_activity_proto_msgTypes[181] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12440,7 +14734,7 @@ func (x *GetLuckyGiftDrawSummaryRequest) String() string { func (*GetLuckyGiftDrawSummaryRequest) ProtoMessage() {} func (x *GetLuckyGiftDrawSummaryRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[152] + mi := &file_proto_activity_v1_activity_proto_msgTypes[181] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12453,7 +14747,7 @@ func (x *GetLuckyGiftDrawSummaryRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLuckyGiftDrawSummaryRequest.ProtoReflect.Descriptor instead. func (*GetLuckyGiftDrawSummaryRequest) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{152} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{181} } func (x *GetLuckyGiftDrawSummaryRequest) GetMeta() *RequestMeta { @@ -12507,7 +14801,7 @@ type GetLuckyGiftDrawSummaryResponse struct { func (x *GetLuckyGiftDrawSummaryResponse) Reset() { *x = GetLuckyGiftDrawSummaryResponse{} - mi := &file_proto_activity_v1_activity_proto_msgTypes[153] + mi := &file_proto_activity_v1_activity_proto_msgTypes[182] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12519,7 +14813,7 @@ func (x *GetLuckyGiftDrawSummaryResponse) String() string { func (*GetLuckyGiftDrawSummaryResponse) ProtoMessage() {} func (x *GetLuckyGiftDrawSummaryResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_activity_v1_activity_proto_msgTypes[153] + mi := &file_proto_activity_v1_activity_proto_msgTypes[182] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12532,7 +14826,7 @@ func (x *GetLuckyGiftDrawSummaryResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetLuckyGiftDrawSummaryResponse.ProtoReflect.Descriptor instead. func (*GetLuckyGiftDrawSummaryResponse) Descriptor() ([]byte, []int) { - return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{153} + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{182} } func (x *GetLuckyGiftDrawSummaryResponse) GetSummary() *LuckyGiftDrawSummary { @@ -12542,6 +14836,1483 @@ func (x *GetLuckyGiftDrawSummaryResponse) GetSummary() *LuckyGiftDrawSummary { return nil } +// WeeklyStarGift 是周星周期内参与积分的指定礼物。 +type WeeklyStarGift struct { + state protoimpl.MessageState `protogen:"open.v1"` + GiftId string `protobuf:"bytes,1,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + SortOrder int32 `protobuf:"varint,2,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarGift) Reset() { + *x = WeeklyStarGift{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[183] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarGift) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarGift) ProtoMessage() {} + +func (x *WeeklyStarGift) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[183] + 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 WeeklyStarGift.ProtoReflect.Descriptor instead. +func (*WeeklyStarGift) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{183} +} + +func (x *WeeklyStarGift) GetGiftId() string { + if x != nil { + return x.GiftId + } + return "" +} + +func (x *WeeklyStarGift) GetSortOrder() int32 { + if x != nil { + return x.SortOrder + } + return 0 +} + +// WeeklyStarReward 是周星 Top 排名对应的资源组奖励。 +type WeeklyStarReward struct { + state protoimpl.MessageState `protogen:"open.v1"` + RankNo int32 `protobuf:"varint,1,opt,name=rank_no,json=rankNo,proto3" json:"rank_no,omitempty"` + ResourceGroupId int64 `protobuf:"varint,2,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarReward) Reset() { + *x = WeeklyStarReward{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[184] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarReward) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarReward) ProtoMessage() {} + +func (x *WeeklyStarReward) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[184] + 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 WeeklyStarReward.ProtoReflect.Descriptor instead. +func (*WeeklyStarReward) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{184} +} + +func (x *WeeklyStarReward) GetRankNo() int32 { + if x != nil { + return x.RankNo + } + return 0 +} + +func (x *WeeklyStarReward) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +// WeeklyStarCycle 是一个按 UTC epoch ms 生效的周星配置周期。 +type WeeklyStarCycle struct { + state protoimpl.MessageState `protogen:"open.v1"` + CycleId string `protobuf:"bytes,1,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + ActivityCode string `protobuf:"bytes,2,opt,name=activity_code,json=activityCode,proto3" json:"activity_code,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Title string `protobuf:"bytes,4,opt,name=title,proto3" json:"title,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + StartMs int64 `protobuf:"varint,6,opt,name=start_ms,json=startMs,proto3" json:"start_ms,omitempty"` + EndMs int64 `protobuf:"varint,7,opt,name=end_ms,json=endMs,proto3" json:"end_ms,omitempty"` + Gifts []*WeeklyStarGift `protobuf:"bytes,8,rep,name=gifts,proto3" json:"gifts,omitempty"` + Rewards []*WeeklyStarReward `protobuf:"bytes,9,rep,name=rewards,proto3" json:"rewards,omitempty"` + CreatedByAdminId int64 `protobuf:"varint,10,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"` + UpdatedByAdminId int64 `protobuf:"varint,11,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,omitempty"` + SettledAtMs int64 `protobuf:"varint,12,opt,name=settled_at_ms,json=settledAtMs,proto3" json:"settled_at_ms,omitempty"` + CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,14,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + AppCode string `protobuf:"bytes,15,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarCycle) Reset() { + *x = WeeklyStarCycle{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[185] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarCycle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarCycle) ProtoMessage() {} + +func (x *WeeklyStarCycle) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[185] + 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 WeeklyStarCycle.ProtoReflect.Descriptor instead. +func (*WeeklyStarCycle) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{185} +} + +func (x *WeeklyStarCycle) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +func (x *WeeklyStarCycle) GetActivityCode() string { + if x != nil { + return x.ActivityCode + } + return "" +} + +func (x *WeeklyStarCycle) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *WeeklyStarCycle) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *WeeklyStarCycle) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *WeeklyStarCycle) GetStartMs() int64 { + if x != nil { + return x.StartMs + } + return 0 +} + +func (x *WeeklyStarCycle) GetEndMs() int64 { + if x != nil { + return x.EndMs + } + return 0 +} + +func (x *WeeklyStarCycle) GetGifts() []*WeeklyStarGift { + if x != nil { + return x.Gifts + } + return nil +} + +func (x *WeeklyStarCycle) GetRewards() []*WeeklyStarReward { + if x != nil { + return x.Rewards + } + return nil +} + +func (x *WeeklyStarCycle) GetCreatedByAdminId() int64 { + if x != nil { + return x.CreatedByAdminId + } + return 0 +} + +func (x *WeeklyStarCycle) GetUpdatedByAdminId() int64 { + if x != nil { + return x.UpdatedByAdminId + } + return 0 +} + +func (x *WeeklyStarCycle) GetSettledAtMs() int64 { + if x != nil { + return x.SettledAtMs + } + return 0 +} + +func (x *WeeklyStarCycle) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *WeeklyStarCycle) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +func (x *WeeklyStarCycle) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +// WeeklyStarLeaderboardEntry 是一个周期内用户维度的积分排名。 +type WeeklyStarLeaderboardEntry struct { + state protoimpl.MessageState `protogen:"open.v1"` + RankNo int32 `protobuf:"varint,1,opt,name=rank_no,json=rankNo,proto3" json:"rank_no,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Score int64 `protobuf:"varint,3,opt,name=score,proto3" json:"score,omitempty"` + FirstScoredAtMs int64 `protobuf:"varint,4,opt,name=first_scored_at_ms,json=firstScoredAtMs,proto3" json:"first_scored_at_ms,omitempty"` + LastScoredAtMs int64 `protobuf:"varint,5,opt,name=last_scored_at_ms,json=lastScoredAtMs,proto3" json:"last_scored_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarLeaderboardEntry) Reset() { + *x = WeeklyStarLeaderboardEntry{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[186] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarLeaderboardEntry) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarLeaderboardEntry) ProtoMessage() {} + +func (x *WeeklyStarLeaderboardEntry) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[186] + 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 WeeklyStarLeaderboardEntry.ProtoReflect.Descriptor instead. +func (*WeeklyStarLeaderboardEntry) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{186} +} + +func (x *WeeklyStarLeaderboardEntry) GetRankNo() int32 { + if x != nil { + return x.RankNo + } + return 0 +} + +func (x *WeeklyStarLeaderboardEntry) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *WeeklyStarLeaderboardEntry) GetScore() int64 { + if x != nil { + return x.Score + } + return 0 +} + +func (x *WeeklyStarLeaderboardEntry) GetFirstScoredAtMs() int64 { + if x != nil { + return x.FirstScoredAtMs + } + return 0 +} + +func (x *WeeklyStarLeaderboardEntry) GetLastScoredAtMs() int64 { + if x != nil { + return x.LastScoredAtMs + } + return 0 +} + +// WeeklyStarSettlement 是周期结束后 Top 奖励发放的幂等记录。 +type WeeklyStarSettlement struct { + state protoimpl.MessageState `protogen:"open.v1"` + SettlementId string `protobuf:"bytes,1,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` + CycleId string `protobuf:"bytes,2,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + RankNo int32 `protobuf:"varint,3,opt,name=rank_no,json=rankNo,proto3" json:"rank_no,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Score int64 `protobuf:"varint,5,opt,name=score,proto3" json:"score,omitempty"` + ResourceGroupId int64 `protobuf:"varint,6,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + WalletCommandId string `protobuf:"bytes,7,opt,name=wallet_command_id,json=walletCommandId,proto3" json:"wallet_command_id,omitempty"` + WalletGrantId string `protobuf:"bytes,8,opt,name=wallet_grant_id,json=walletGrantId,proto3" json:"wallet_grant_id,omitempty"` + Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"` + FailureReason string `protobuf:"bytes,10,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + AttemptCount int32 `protobuf:"varint,11,opt,name=attempt_count,json=attemptCount,proto3" json:"attempt_count,omitempty"` + CreatedAtMs int64 `protobuf:"varint,12,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarSettlement) Reset() { + *x = WeeklyStarSettlement{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[187] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarSettlement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarSettlement) ProtoMessage() {} + +func (x *WeeklyStarSettlement) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[187] + 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 WeeklyStarSettlement.ProtoReflect.Descriptor instead. +func (*WeeklyStarSettlement) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{187} +} + +func (x *WeeklyStarSettlement) GetSettlementId() string { + if x != nil { + return x.SettlementId + } + return "" +} + +func (x *WeeklyStarSettlement) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +func (x *WeeklyStarSettlement) GetRankNo() int32 { + if x != nil { + return x.RankNo + } + return 0 +} + +func (x *WeeklyStarSettlement) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *WeeklyStarSettlement) GetScore() int64 { + if x != nil { + return x.Score + } + return 0 +} + +func (x *WeeklyStarSettlement) GetResourceGroupId() int64 { + if x != nil { + return x.ResourceGroupId + } + return 0 +} + +func (x *WeeklyStarSettlement) GetWalletCommandId() string { + if x != nil { + return x.WalletCommandId + } + return "" +} + +func (x *WeeklyStarSettlement) GetWalletGrantId() string { + if x != nil { + return x.WalletGrantId + } + return "" +} + +func (x *WeeklyStarSettlement) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *WeeklyStarSettlement) GetFailureReason() string { + if x != nil { + return x.FailureReason + } + return "" +} + +func (x *WeeklyStarSettlement) GetAttemptCount() int32 { + if x != nil { + return x.AttemptCount + } + return 0 +} + +func (x *WeeklyStarSettlement) GetCreatedAtMs() int64 { + if x != nil { + return x.CreatedAtMs + } + return 0 +} + +func (x *WeeklyStarSettlement) GetUpdatedAtMs() int64 { + if x != nil { + return x.UpdatedAtMs + } + return 0 +} + +type ListWeeklyStarCyclesRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RegionId int64 `protobuf:"varint,2,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + StartMs int64 `protobuf:"varint,4,opt,name=start_ms,json=startMs,proto3" json:"start_ms,omitempty"` + EndMs int64 `protobuf:"varint,5,opt,name=end_ms,json=endMs,proto3" json:"end_ms,omitempty"` + Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarCyclesRequest) Reset() { + *x = ListWeeklyStarCyclesRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[188] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarCyclesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarCyclesRequest) ProtoMessage() {} + +func (x *ListWeeklyStarCyclesRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[188] + 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 ListWeeklyStarCyclesRequest.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarCyclesRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{188} +} + +func (x *ListWeeklyStarCyclesRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListWeeklyStarCyclesRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *ListWeeklyStarCyclesRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *ListWeeklyStarCyclesRequest) GetStartMs() int64 { + if x != nil { + return x.StartMs + } + return 0 +} + +func (x *ListWeeklyStarCyclesRequest) GetEndMs() int64 { + if x != nil { + return x.EndMs + } + return 0 +} + +func (x *ListWeeklyStarCyclesRequest) GetPage() int32 { + if x != nil { + return x.Page + } + return 0 +} + +func (x *ListWeeklyStarCyclesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +type ListWeeklyStarCyclesResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycles []*WeeklyStarCycle `protobuf:"bytes,1,rep,name=cycles,proto3" json:"cycles,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarCyclesResponse) Reset() { + *x = ListWeeklyStarCyclesResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[189] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarCyclesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarCyclesResponse) ProtoMessage() {} + +func (x *ListWeeklyStarCyclesResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[189] + 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 ListWeeklyStarCyclesResponse.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarCyclesResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{189} +} + +func (x *ListWeeklyStarCyclesResponse) GetCycles() []*WeeklyStarCycle { + if x != nil { + return x.Cycles + } + return nil +} + +func (x *ListWeeklyStarCyclesResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +type GetWeeklyStarCycleRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CycleId string `protobuf:"bytes,2,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWeeklyStarCycleRequest) Reset() { + *x = GetWeeklyStarCycleRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[190] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWeeklyStarCycleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWeeklyStarCycleRequest) ProtoMessage() {} + +func (x *GetWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[190] + 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 GetWeeklyStarCycleRequest.ProtoReflect.Descriptor instead. +func (*GetWeeklyStarCycleRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{190} +} + +func (x *GetWeeklyStarCycleRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetWeeklyStarCycleRequest) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +type GetWeeklyStarCycleResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWeeklyStarCycleResponse) Reset() { + *x = GetWeeklyStarCycleResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[191] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWeeklyStarCycleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWeeklyStarCycleResponse) ProtoMessage() {} + +func (x *GetWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[191] + 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 GetWeeklyStarCycleResponse.ProtoReflect.Descriptor instead. +func (*GetWeeklyStarCycleResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{191} +} + +func (x *GetWeeklyStarCycleResponse) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +type UpsertWeeklyStarCycleRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Cycle *WeeklyStarCycle `protobuf:"bytes,2,opt,name=cycle,proto3" json:"cycle,omitempty"` + OperatorAdminId int64 `protobuf:"varint,3,opt,name=operator_admin_id,json=operatorAdminId,proto3" json:"operator_admin_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpsertWeeklyStarCycleRequest) Reset() { + *x = UpsertWeeklyStarCycleRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[192] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpsertWeeklyStarCycleRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpsertWeeklyStarCycleRequest) ProtoMessage() {} + +func (x *UpsertWeeklyStarCycleRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[192] + 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 UpsertWeeklyStarCycleRequest.ProtoReflect.Descriptor instead. +func (*UpsertWeeklyStarCycleRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{192} +} + +func (x *UpsertWeeklyStarCycleRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *UpsertWeeklyStarCycleRequest) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +func (x *UpsertWeeklyStarCycleRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type UpsertWeeklyStarCycleResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + Created bool `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpsertWeeklyStarCycleResponse) Reset() { + *x = UpsertWeeklyStarCycleResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[193] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpsertWeeklyStarCycleResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpsertWeeklyStarCycleResponse) ProtoMessage() {} + +func (x *UpsertWeeklyStarCycleResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[193] + 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 UpsertWeeklyStarCycleResponse.ProtoReflect.Descriptor instead. +func (*UpsertWeeklyStarCycleResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{193} +} + +func (x *UpsertWeeklyStarCycleResponse) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +func (x *UpsertWeeklyStarCycleResponse) GetCreated() bool { + if x != nil { + return x.Created + } + return false +} + +type SetWeeklyStarCycleStatusRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CycleId string `protobuf:"bytes,2,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,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 *SetWeeklyStarCycleStatusRequest) Reset() { + *x = SetWeeklyStarCycleStatusRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[194] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetWeeklyStarCycleStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetWeeklyStarCycleStatusRequest) ProtoMessage() {} + +func (x *SetWeeklyStarCycleStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[194] + 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 SetWeeklyStarCycleStatusRequest.ProtoReflect.Descriptor instead. +func (*SetWeeklyStarCycleStatusRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{194} +} + +func (x *SetWeeklyStarCycleStatusRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *SetWeeklyStarCycleStatusRequest) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +func (x *SetWeeklyStarCycleStatusRequest) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *SetWeeklyStarCycleStatusRequest) GetOperatorAdminId() int64 { + if x != nil { + return x.OperatorAdminId + } + return 0 +} + +type SetWeeklyStarCycleStatusResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetWeeklyStarCycleStatusResponse) Reset() { + *x = SetWeeklyStarCycleStatusResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[195] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetWeeklyStarCycleStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetWeeklyStarCycleStatusResponse) ProtoMessage() {} + +func (x *SetWeeklyStarCycleStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[195] + 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 SetWeeklyStarCycleStatusResponse.ProtoReflect.Descriptor instead. +func (*SetWeeklyStarCycleStatusResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{195} +} + +func (x *SetWeeklyStarCycleStatusResponse) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +type ListWeeklyStarLeaderboardRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CycleId string `protobuf:"bytes,2,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + PageToken string `protobuf:"bytes,5,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarLeaderboardRequest) Reset() { + *x = ListWeeklyStarLeaderboardRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[196] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarLeaderboardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarLeaderboardRequest) ProtoMessage() {} + +func (x *ListWeeklyStarLeaderboardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[196] + 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 ListWeeklyStarLeaderboardRequest.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarLeaderboardRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{196} +} + +func (x *ListWeeklyStarLeaderboardRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListWeeklyStarLeaderboardRequest) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +func (x *ListWeeklyStarLeaderboardRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *ListWeeklyStarLeaderboardRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListWeeklyStarLeaderboardRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +type ListWeeklyStarLeaderboardResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + Entries []*WeeklyStarLeaderboardEntry `protobuf:"bytes,2,rep,name=entries,proto3" json:"entries,omitempty"` + NextPageToken string `protobuf:"bytes,3,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` + Total int64 `protobuf:"varint,4,opt,name=total,proto3" json:"total,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarLeaderboardResponse) Reset() { + *x = ListWeeklyStarLeaderboardResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[197] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarLeaderboardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarLeaderboardResponse) ProtoMessage() {} + +func (x *ListWeeklyStarLeaderboardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[197] + 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 ListWeeklyStarLeaderboardResponse.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarLeaderboardResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{197} +} + +func (x *ListWeeklyStarLeaderboardResponse) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +func (x *ListWeeklyStarLeaderboardResponse) GetEntries() []*WeeklyStarLeaderboardEntry { + if x != nil { + return x.Entries + } + return nil +} + +func (x *ListWeeklyStarLeaderboardResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +func (x *ListWeeklyStarLeaderboardResponse) GetTotal() int64 { + if x != nil { + return x.Total + } + return 0 +} + +type ListWeeklyStarSettlementsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + CycleId string `protobuf:"bytes,2,opt,name=cycle_id,json=cycleId,proto3" json:"cycle_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarSettlementsRequest) Reset() { + *x = ListWeeklyStarSettlementsRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[198] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarSettlementsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarSettlementsRequest) ProtoMessage() {} + +func (x *ListWeeklyStarSettlementsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[198] + 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 ListWeeklyStarSettlementsRequest.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarSettlementsRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{198} +} + +func (x *ListWeeklyStarSettlementsRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListWeeklyStarSettlementsRequest) GetCycleId() string { + if x != nil { + return x.CycleId + } + return "" +} + +type ListWeeklyStarSettlementsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Settlements []*WeeklyStarSettlement `protobuf:"bytes,1,rep,name=settlements,proto3" json:"settlements,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarSettlementsResponse) Reset() { + *x = ListWeeklyStarSettlementsResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[199] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarSettlementsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarSettlementsResponse) ProtoMessage() {} + +func (x *ListWeeklyStarSettlementsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[199] + 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 ListWeeklyStarSettlementsResponse.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarSettlementsResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{199} +} + +func (x *ListWeeklyStarSettlementsResponse) GetSettlements() []*WeeklyStarSettlement { + if x != nil { + return x.Settlements + } + return nil +} + +type GetWeeklyStarCurrentRequest 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"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWeeklyStarCurrentRequest) Reset() { + *x = GetWeeklyStarCurrentRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[200] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWeeklyStarCurrentRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWeeklyStarCurrentRequest) ProtoMessage() {} + +func (x *GetWeeklyStarCurrentRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[200] + 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 GetWeeklyStarCurrentRequest.ProtoReflect.Descriptor instead. +func (*GetWeeklyStarCurrentRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{200} +} + +func (x *GetWeeklyStarCurrentRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *GetWeeklyStarCurrentRequest) GetUserId() int64 { + if x != nil { + return x.UserId + } + return 0 +} + +func (x *GetWeeklyStarCurrentRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +type GetWeeklyStarCurrentResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + TopEntries []*WeeklyStarLeaderboardEntry `protobuf:"bytes,2,rep,name=top_entries,json=topEntries,proto3" json:"top_entries,omitempty"` + MyEntry *WeeklyStarLeaderboardEntry `protobuf:"bytes,3,opt,name=my_entry,json=myEntry,proto3" json:"my_entry,omitempty"` + ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetWeeklyStarCurrentResponse) Reset() { + *x = GetWeeklyStarCurrentResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[201] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetWeeklyStarCurrentResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetWeeklyStarCurrentResponse) ProtoMessage() {} + +func (x *GetWeeklyStarCurrentResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[201] + 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 GetWeeklyStarCurrentResponse.ProtoReflect.Descriptor instead. +func (*GetWeeklyStarCurrentResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{201} +} + +func (x *GetWeeklyStarCurrentResponse) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +func (x *GetWeeklyStarCurrentResponse) GetTopEntries() []*WeeklyStarLeaderboardEntry { + if x != nil { + return x.TopEntries + } + return nil +} + +func (x *GetWeeklyStarCurrentResponse) GetMyEntry() *WeeklyStarLeaderboardEntry { + if x != nil { + return x.MyEntry + } + return nil +} + +func (x *GetWeeklyStarCurrentResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + +type ListWeeklyStarHistoryRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RegionId int64 `protobuf:"varint,2,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarHistoryRequest) Reset() { + *x = ListWeeklyStarHistoryRequest{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[202] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarHistoryRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarHistoryRequest) ProtoMessage() {} + +func (x *ListWeeklyStarHistoryRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[202] + 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 ListWeeklyStarHistoryRequest.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarHistoryRequest) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{202} +} + +func (x *ListWeeklyStarHistoryRequest) GetMeta() *RequestMeta { + if x != nil { + return x.Meta + } + return nil +} + +func (x *ListWeeklyStarHistoryRequest) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + +func (x *ListWeeklyStarHistoryRequest) GetLimit() int32 { + if x != nil { + return x.Limit + } + return 0 +} + +type WeeklyStarHistoryCycle struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycle *WeeklyStarCycle `protobuf:"bytes,1,opt,name=cycle,proto3" json:"cycle,omitempty"` + TopEntries []*WeeklyStarLeaderboardEntry `protobuf:"bytes,2,rep,name=top_entries,json=topEntries,proto3" json:"top_entries,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *WeeklyStarHistoryCycle) Reset() { + *x = WeeklyStarHistoryCycle{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[203] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *WeeklyStarHistoryCycle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WeeklyStarHistoryCycle) ProtoMessage() {} + +func (x *WeeklyStarHistoryCycle) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[203] + 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 WeeklyStarHistoryCycle.ProtoReflect.Descriptor instead. +func (*WeeklyStarHistoryCycle) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{203} +} + +func (x *WeeklyStarHistoryCycle) GetCycle() *WeeklyStarCycle { + if x != nil { + return x.Cycle + } + return nil +} + +func (x *WeeklyStarHistoryCycle) GetTopEntries() []*WeeklyStarLeaderboardEntry { + if x != nil { + return x.TopEntries + } + return nil +} + +type ListWeeklyStarHistoryResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Cycles []*WeeklyStarHistoryCycle `protobuf:"bytes,1,rep,name=cycles,proto3" json:"cycles,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListWeeklyStarHistoryResponse) Reset() { + *x = ListWeeklyStarHistoryResponse{} + mi := &file_proto_activity_v1_activity_proto_msgTypes[204] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListWeeklyStarHistoryResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListWeeklyStarHistoryResponse) ProtoMessage() {} + +func (x *ListWeeklyStarHistoryResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_activity_v1_activity_proto_msgTypes[204] + 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 ListWeeklyStarHistoryResponse.ProtoReflect.Descriptor instead. +func (*ListWeeklyStarHistoryResponse) Descriptor() ([]byte, []int) { + return file_proto_activity_v1_activity_proto_rawDescGZIP(), []int{204} +} + +func (x *ListWeeklyStarHistoryResponse) GetCycles() []*WeeklyStarHistoryCycle { + if x != nil { + return x.Cycles + } + return nil +} + +func (x *ListWeeklyStarHistoryResponse) GetServerTimeMs() int64 { + if x != nil { + return x.ServerTimeMs + } + return 0 +} + var File_proto_activity_v1_activity_proto protoreflect.FileDescriptor const file_proto_activity_v1_activity_proto_rawDesc = "" + @@ -12952,16 +16723,19 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "dailyLimit\x12*\n" + "\x11operator_admin_id\x18\a \x01(\x03R\x0foperatorAdminId\"m\n" + "&UpdateRegistrationRewardConfigResponse\x12C\n" + - "\x06config\x18\x01 \x01(\v2+.hyapp.activity.v1.RegistrationRewardConfigR\x06config\"\xbb\x01\n" + + "\x06config\x18\x01 \x01(\v2+.hyapp.activity.v1.RegistrationRewardConfigR\x06config\"\x8b\x02\n" + "#ListRegistrationRewardClaimsRequest\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\"\x80\x01\n" + + "\tpage_size\x18\x05 \x01(\x05R\bpageSize\x12(\n" + + "\x10claimed_start_ms\x18\x06 \x01(\x03R\x0eclaimedStartMs\x12$\n" + + "\x0eclaimed_end_ms\x18\a \x01(\x03R\fclaimedEndMs\"\xb0\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" + + "\x05total\x18\x02 \x01(\x03R\x05total\x12.\n" + + "\x13today_claimed_count\x18\x03 \x01(\x03R\x11todayClaimedCount\"\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" + @@ -13049,7 +16823,199 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\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" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xcc\x02\n" + + "\x1cCumulativeRechargeRewardTier\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" + + "\x13threshold_usd_minor\x18\x04 \x01(\x03R\x11thresholdUsdMinor\x12*\n" + + "\x11resource_group_id\x18\x05 \x01(\x03R\x0fresourceGroupId\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\a \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\"\x93\x02\n" + + "\x1eCumulativeRechargeRewardConfig\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\x12E\n" + + "\x05tiers\x18\x03 \x03(\v2/.hyapp.activity.v1.CumulativeRechargeRewardTierR\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\"\xb2\x06\n" + + "\x1dCumulativeRechargeRewardGrant\x12\x19\n" + + "\bgrant_id\x18\x01 \x01(\tR\agrantId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + + "\tcycle_key\x18\x03 \x01(\tR\bcycleKey\x12\x17\n" + + "\auser_id\x18\x04 \x01(\x03R\x06userId\x12\x19\n" + + "\bevent_id\x18\x05 \x01(\tR\aeventId\x12%\n" + + "\x0etransaction_id\x18\x06 \x01(\tR\rtransactionId\x12\x1d\n" + + "\n" + + "command_id\x18\a \x01(\tR\tcommandId\x12\x17\n" + + "\atier_id\x18\b \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\t \x01(\tR\btierCode\x12.\n" + + "\x13threshold_usd_minor\x18\n" + + " \x01(\x03R\x11thresholdUsdMinor\x12*\n" + + "\x11resource_group_id\x18\v \x01(\x03R\x0fresourceGroupId\x12*\n" + + "\x11reached_usd_minor\x18\f \x01(\x03R\x0freachedUsdMinor\x120\n" + + "\x14qualifying_usd_minor\x18\r \x01(\x03R\x12qualifyingUsdMinor\x120\n" + + "\x14recharge_coin_amount\x18\x0e \x01(\x03R\x12rechargeCoinAmount\x12#\n" + + "\rrecharge_type\x18\x0f \x01(\tR\frechargeType\x12\x16\n" + + "\x06status\x18\x10 \x01(\tR\x06status\x12*\n" + + "\x11wallet_command_id\x18\x11 \x01(\tR\x0fwalletCommandId\x12&\n" + + "\x0fwallet_grant_id\x18\x12 \x01(\tR\rwalletGrantId\x12%\n" + + "\x0efailure_reason\x18\x13 \x01(\tR\rfailureReason\x12\"\n" + + "\rgranted_at_ms\x18\x14 \x01(\x03R\vgrantedAtMs\x12\"\n" + + "\rcreated_at_ms\x18\x15 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x16 \x01(\x03R\vupdatedAtMs\"\xcf\x02\n" + + " CumulativeRechargeRewardProgress\x12\x19\n" + + "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1b\n" + + "\tcycle_key\x18\x02 \x01(\tR\bcycleKey\x12\x17\n" + + "\auser_id\x18\x03 \x01(\x03R\x06userId\x12&\n" + + "\x0ftotal_usd_minor\x18\x04 \x01(\x03R\rtotalUsdMinor\x12*\n" + + "\x11total_coin_amount\x18\x05 \x01(\x03R\x0ftotalCoinAmount\x121\n" + + "\x15first_recharged_at_ms\x18\x06 \x01(\x03R\x12firstRechargedAtMs\x12/\n" + + "\x14last_recharged_at_ms\x18\a \x01(\x03R\x11lastRechargedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\b \x01(\x03R\vupdatedAtMs\"\x95\x03\n" + + "\x1eCumulativeRechargeRewardStatus\x12I\n" + + "\x06config\x18\x01 \x01(\v21.hyapp.activity.v1.CumulativeRechargeRewardConfigR\x06config\x12O\n" + + "\bprogress\x18\x02 \x01(\v23.hyapp.activity.v1.CumulativeRechargeRewardProgressR\bprogress\x12H\n" + + "\x06grants\x18\x03 \x03(\v20.hyapp.activity.v1.CumulativeRechargeRewardGrantR\x06grants\x12\x1b\n" + + "\tcycle_key\x18\x04 \x01(\tR\bcycleKey\x12&\n" + + "\x0fperiod_start_ms\x18\x05 \x01(\x03R\rperiodStartMs\x12\"\n" + + "\rperiod_end_ms\x18\x06 \x01(\x03R\vperiodEndMs\x12$\n" + + "\x0eserver_time_ms\x18\a \x01(\x03R\fserverTimeMs\"w\n" + + "(GetCumulativeRechargeRewardStatusRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\"v\n" + + ")GetCumulativeRechargeRewardStatusResponse\x12I\n" + + "\x06status\x18\x01 \x01(\v21.hyapp.activity.v1.CumulativeRechargeRewardStatusR\x06status\"\xd5\x03\n" + + "&ConsumeCumulativeRechargeRewardRequest\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\x120\n" + + "\x14qualifying_usd_minor\x18\t \x01(\x03R\x12qualifyingUsdMinor\x12!\n" + + "\fpayload_json\x18\n" + + " \x01(\tR\vpayloadJson\x12$\n" + + "\x0eoccurred_at_ms\x18\v \x01(\x03R\foccurredAtMs\"\xa7\x01\n" + + "'ConsumeCumulativeRechargeRewardResponse\x12H\n" + + "\x06grants\x18\x01 \x03(\v20.hyapp.activity.v1.CumulativeRechargeRewardGrantR\x06grants\x12\x1a\n" + + "\bconsumed\x18\x02 \x01(\bR\bconsumed\x12\x16\n" + + "\x06reason\x18\x03 \x01(\tR\x06reason\"^\n" + + "(GetCumulativeRechargeRewardConfigRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\"v\n" + + ")GetCumulativeRechargeRewardConfigResponse\x12I\n" + + "\x06config\x18\x01 \x01(\v21.hyapp.activity.v1.CumulativeRechargeRewardConfigR\x06config\"\xee\x01\n" + + "+UpdateCumulativeRechargeRewardConfigRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x18\n" + + "\aenabled\x18\x02 \x01(\bR\aenabled\x12E\n" + + "\x05tiers\x18\x03 \x03(\v2/.hyapp.activity.v1.CumulativeRechargeRewardTierR\x05tiers\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\"y\n" + + ",UpdateCumulativeRechargeRewardConfigResponse\x12I\n" + + "\x06config\x18\x01 \x01(\v21.hyapp.activity.v1.CumulativeRechargeRewardConfigR\x06config\"\xde\x01\n" + + ")ListCumulativeRechargeRewardGrantsRequest\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\x1b\n" + + "\tcycle_key\x18\x04 \x01(\tR\bcycleKey\x12\x12\n" + + "\x04page\x18\x05 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\x06 \x01(\x05R\bpageSize\"\x8c\x01\n" + + "*ListCumulativeRechargeRewardGrantsResponse\x12H\n" + + "\x06grants\x18\x01 \x03(\v20.hyapp.activity.v1.CumulativeRechargeRewardGrantR\x06grants\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xca\x02\n" + + "\x16RoomTurnoverRewardTier\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\x120\n" + + "\x14threshold_coin_spent\x18\x04 \x01(\x03R\x12thresholdCoinSpent\x12,\n" + + "\x12reward_coin_amount\x18\x05 \x01(\x03R\x10rewardCoinAmount\x12\x16\n" + + "\x06status\x18\x06 \x01(\tR\x06status\x12\x1d\n" + + "\n" + + "sort_order\x18\a \x01(\x05R\tsortOrder\x12\"\n" + + "\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\"\x87\x02\n" + + "\x18RoomTurnoverRewardConfig\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.RoomTurnoverRewardTierR\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\"\xa7\x05\n" + + "\x1cRoomTurnoverRewardSettlement\x12#\n" + + "\rsettlement_id\x18\x01 \x01(\tR\fsettlementId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + + "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12\"\n" + + "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\x12&\n" + + "\x0fperiod_start_ms\x18\x05 \x01(\x03R\rperiodStartMs\x12\"\n" + + "\rperiod_end_ms\x18\x06 \x01(\x03R\vperiodEndMs\x12\x1d\n" + + "\n" + + "coin_spent\x18\a \x01(\x03R\tcoinSpent\x12\x17\n" + + "\atier_id\x18\b \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\t \x01(\tR\btierCode\x120\n" + + "\x14threshold_coin_spent\x18\n" + + " \x01(\x03R\x12thresholdCoinSpent\x12,\n" + + "\x12reward_coin_amount\x18\v \x01(\x03R\x10rewardCoinAmount\x12\x16\n" + + "\x06status\x18\f \x01(\tR\x06status\x12*\n" + + "\x11wallet_command_id\x18\r \x01(\tR\x0fwalletCommandId\x122\n" + + "\x15wallet_transaction_id\x18\x0e \x01(\tR\x13walletTransactionId\x12%\n" + + "\x0efailure_reason\x18\x0f \x01(\tR\rfailureReason\x12\"\n" + + "\rsettled_at_ms\x18\x10 \x01(\x03R\vsettledAtMs\x12\"\n" + + "\rcreated_at_ms\x18\x11 \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x12 \x01(\x03R\vupdatedAtMs\"\xa7\x04\n" + + "\x18RoomTurnoverRewardStatus\x12C\n" + + "\x06config\x18\x01 \x01(\v2+.hyapp.activity.v1.RoomTurnoverRewardConfigR\x06config\x12\x17\n" + + "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\"\n" + + "\rowner_user_id\x18\x03 \x01(\x03R\vownerUserId\x12&\n" + + "\x0fperiod_start_ms\x18\x04 \x01(\x03R\rperiodStartMs\x12\"\n" + + "\rperiod_end_ms\x18\x05 \x01(\x03R\vperiodEndMs\x12,\n" + + "\x12current_coin_spent\x18\x06 \x01(\x03R\x10currentCoinSpent\x12=\n" + + "\x1bexpected_reward_coin_amount\x18\a \x01(\x03R\x18expectedRewardCoinAmount\x12L\n" + + "\fmatched_tier\x18\b \x01(\v2).hyapp.activity.v1.RoomTurnoverRewardTierR\vmatchedTier\x12\\\n" + + "\x11latest_settlement\x18\t \x01(\v2/.hyapp.activity.v1.RoomTurnoverRewardSettlementR\x10latestSettlement\x12$\n" + + "\x0eserver_time_ms\x18\n" + + " \x01(\x03R\fserverTimeMs\"\xae\x01\n" + + "\"GetRoomTurnoverRewardStatusRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x17\n" + + "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12\"\n" + + "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\"j\n" + + "#GetRoomTurnoverRewardStatusResponse\x12C\n" + + "\x06status\x18\x01 \x01(\v2+.hyapp.activity.v1.RoomTurnoverRewardStatusR\x06status\"X\n" + + "\"GetRoomTurnoverRewardConfigRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\"j\n" + + "#GetRoomTurnoverRewardConfigResponse\x12C\n" + + "\x06config\x18\x01 \x01(\v2+.hyapp.activity.v1.RoomTurnoverRewardConfigR\x06config\"\xe2\x01\n" + + "%UpdateRoomTurnoverRewardConfigRequest\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.RoomTurnoverRewardTierR\x05tiers\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\"m\n" + + "&UpdateRoomTurnoverRewardConfigResponse\x12C\n" + + "\x06config\x18\x01 \x01(\v2+.hyapp.activity.v1.RoomTurnoverRewardConfigR\x06config\"\x8c\x02\n" + + "(ListRoomTurnoverRewardSettlementsRequest\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" + + "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12\"\n" + + "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\x12&\n" + + "\x0fperiod_start_ms\x18\x05 \x01(\x03R\rperiodStartMs\x12\x12\n" + + "\x04page\x18\x06 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\a \x01(\x05R\bpageSize\"\x94\x01\n" + + ")ListRoomTurnoverRewardSettlementsResponse\x12Q\n" + + "\vsettlements\x18\x01 \x03(\v2/.hyapp.activity.v1.RoomTurnoverRewardSettlementR\vsettlements\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"\xaf\x01\n" + + "(RetryRoomTurnoverRewardSettlementRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12#\n" + + "\rsettlement_id\x18\x02 \x01(\tR\fsettlementId\x12*\n" + + "\x11operator_admin_id\x18\x03 \x01(\x03R\x0foperatorAdminId\"|\n" + + ")RetryRoomTurnoverRewardSettlementResponse\x12O\n" + + "\n" + + "settlement\x18\x01 \x01(\v2/.hyapp.activity.v1.RoomTurnoverRewardSettlementR\n" + + "settlement\"`\n" + "\x15SevenDayCheckInReward\x12\x1b\n" + "\tday_index\x18\x01 \x01(\x05R\bdayIndex\x12*\n" + "\x11resource_group_id\x18\x02 \x01(\x03R\x0fresourceGroupId\"\xae\x02\n" + @@ -13689,7 +17655,120 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\x06status\x18\x05 \x01(\tR\x06status\x12\x17\n" + "\apool_id\x18\x06 \x01(\tR\x06poolId\"d\n" + "\x1fGetLuckyGiftDrawSummaryResponse\x12A\n" + - "\asummary\x18\x01 \x01(\v2'.hyapp.activity.v1.LuckyGiftDrawSummaryR\asummary2\xe2\x01\n" + + "\asummary\x18\x01 \x01(\v2'.hyapp.activity.v1.LuckyGiftDrawSummaryR\asummary\"H\n" + + "\x0eWeeklyStarGift\x12\x17\n" + + "\agift_id\x18\x01 \x01(\tR\x06giftId\x12\x1d\n" + + "\n" + + "sort_order\x18\x02 \x01(\x05R\tsortOrder\"W\n" + + "\x10WeeklyStarReward\x12\x17\n" + + "\arank_no\x18\x01 \x01(\x05R\x06rankNo\x12*\n" + + "\x11resource_group_id\x18\x02 \x01(\x03R\x0fresourceGroupId\"\xab\x04\n" + + "\x0fWeeklyStarCycle\x12\x19\n" + + "\bcycle_id\x18\x01 \x01(\tR\acycleId\x12#\n" + + "\ractivity_code\x18\x02 \x01(\tR\factivityCode\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12\x14\n" + + "\x05title\x18\x04 \x01(\tR\x05title\x12\x16\n" + + "\x06status\x18\x05 \x01(\tR\x06status\x12\x19\n" + + "\bstart_ms\x18\x06 \x01(\x03R\astartMs\x12\x15\n" + + "\x06end_ms\x18\a \x01(\x03R\x05endMs\x127\n" + + "\x05gifts\x18\b \x03(\v2!.hyapp.activity.v1.WeeklyStarGiftR\x05gifts\x12=\n" + + "\arewards\x18\t \x03(\v2#.hyapp.activity.v1.WeeklyStarRewardR\arewards\x12-\n" + + "\x13created_by_admin_id\x18\n" + + " \x01(\x03R\x10createdByAdminId\x12-\n" + + "\x13updated_by_admin_id\x18\v \x01(\x03R\x10updatedByAdminId\x12\"\n" + + "\rsettled_at_ms\x18\f \x01(\x03R\vsettledAtMs\x12\"\n" + + "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\x12\x19\n" + + "\bapp_code\x18\x0f \x01(\tR\aappCode\"\xbc\x01\n" + + "\x1aWeeklyStarLeaderboardEntry\x12\x17\n" + + "\arank_no\x18\x01 \x01(\x05R\x06rankNo\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x14\n" + + "\x05score\x18\x03 \x01(\x03R\x05score\x12+\n" + + "\x12first_scored_at_ms\x18\x04 \x01(\x03R\x0ffirstScoredAtMs\x12)\n" + + "\x11last_scored_at_ms\x18\x05 \x01(\x03R\x0elastScoredAtMs\"\xca\x03\n" + + "\x14WeeklyStarSettlement\x12#\n" + + "\rsettlement_id\x18\x01 \x01(\tR\fsettlementId\x12\x19\n" + + "\bcycle_id\x18\x02 \x01(\tR\acycleId\x12\x17\n" + + "\arank_no\x18\x03 \x01(\x05R\x06rankNo\x12\x17\n" + + "\auser_id\x18\x04 \x01(\x03R\x06userId\x12\x14\n" + + "\x05score\x18\x05 \x01(\x03R\x05score\x12*\n" + + "\x11resource_group_id\x18\x06 \x01(\x03R\x0fresourceGroupId\x12*\n" + + "\x11wallet_command_id\x18\a \x01(\tR\x0fwalletCommandId\x12&\n" + + "\x0fwallet_grant_id\x18\b \x01(\tR\rwalletGrantId\x12\x16\n" + + "\x06status\x18\t \x01(\tR\x06status\x12%\n" + + "\x0efailure_reason\x18\n" + + " \x01(\tR\rfailureReason\x12#\n" + + "\rattempt_count\x18\v \x01(\x05R\fattemptCount\x12\"\n" + + "\rcreated_at_ms\x18\f \x01(\x03R\vcreatedAtMs\x12\"\n" + + "\rupdated_at_ms\x18\r \x01(\x03R\vupdatedAtMs\"\xe9\x01\n" + + "\x1bListWeeklyStarCyclesRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tregion_id\x18\x02 \x01(\x03R\bregionId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12\x19\n" + + "\bstart_ms\x18\x04 \x01(\x03R\astartMs\x12\x15\n" + + "\x06end_ms\x18\x05 \x01(\x03R\x05endMs\x12\x12\n" + + "\x04page\x18\x06 \x01(\x05R\x04page\x12\x1b\n" + + "\tpage_size\x18\a \x01(\x05R\bpageSize\"p\n" + + "\x1cListWeeklyStarCyclesResponse\x12:\n" + + "\x06cycles\x18\x01 \x03(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x06cycles\x12\x14\n" + + "\x05total\x18\x02 \x01(\x03R\x05total\"j\n" + + "\x19GetWeeklyStarCycleRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bcycle_id\x18\x02 \x01(\tR\acycleId\"V\n" + + "\x1aGetWeeklyStarCycleResponse\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\"\xb8\x01\n" + + "\x1cUpsertWeeklyStarCycleRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x128\n" + + "\x05cycle\x18\x02 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\x12*\n" + + "\x11operator_admin_id\x18\x03 \x01(\x03R\x0foperatorAdminId\"s\n" + + "\x1dUpsertWeeklyStarCycleResponse\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\x12\x18\n" + + "\acreated\x18\x02 \x01(\bR\acreated\"\xb4\x01\n" + + "\x1fSetWeeklyStarCycleStatusRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bcycle_id\x18\x02 \x01(\tR\acycleId\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12*\n" + + "\x11operator_admin_id\x18\x04 \x01(\x03R\x0foperatorAdminId\"\\\n" + + " SetWeeklyStarCycleStatusResponse\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\"\xca\x01\n" + + " ListWeeklyStarLeaderboardRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bcycle_id\x18\x02 \x01(\tR\acycleId\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12\x1b\n" + + "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12\x1d\n" + + "\n" + + "page_token\x18\x05 \x01(\tR\tpageToken\"\xe4\x01\n" + + "!ListWeeklyStarLeaderboardResponse\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\x12G\n" + + "\aentries\x18\x02 \x03(\v2-.hyapp.activity.v1.WeeklyStarLeaderboardEntryR\aentries\x12&\n" + + "\x0fnext_page_token\x18\x03 \x01(\tR\rnextPageToken\x12\x14\n" + + "\x05total\x18\x04 \x01(\x03R\x05total\"q\n" + + " ListWeeklyStarSettlementsRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x19\n" + + "\bcycle_id\x18\x02 \x01(\tR\acycleId\"n\n" + + "!ListWeeklyStarSettlementsResponse\x12I\n" + + "\vsettlements\x18\x01 \x03(\v2'.hyapp.activity.v1.WeeklyStarSettlementR\vsettlements\"\x87\x01\n" + + "\x1bGetWeeklyStarCurrentRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x17\n" + + "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1b\n" + + "\tregion_id\x18\x03 \x01(\x03R\bregionId\"\x98\x02\n" + + "\x1cGetWeeklyStarCurrentResponse\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\x12N\n" + + "\vtop_entries\x18\x02 \x03(\v2-.hyapp.activity.v1.WeeklyStarLeaderboardEntryR\n" + + "topEntries\x12H\n" + + "\bmy_entry\x18\x03 \x01(\v2-.hyapp.activity.v1.WeeklyStarLeaderboardEntryR\amyEntry\x12$\n" + + "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\"\x85\x01\n" + + "\x1cListWeeklyStarHistoryRequest\x122\n" + + "\x04meta\x18\x01 \x01(\v2\x1e.hyapp.activity.v1.RequestMetaR\x04meta\x12\x1b\n" + + "\tregion_id\x18\x02 \x01(\x03R\bregionId\x12\x14\n" + + "\x05limit\x18\x03 \x01(\x05R\x05limit\"\xa2\x01\n" + + "\x16WeeklyStarHistoryCycle\x128\n" + + "\x05cycle\x18\x01 \x01(\v2\".hyapp.activity.v1.WeeklyStarCycleR\x05cycle\x12N\n" + + "\vtop_entries\x18\x02 \x03(\v2-.hyapp.activity.v1.WeeklyStarLeaderboardEntryR\n" + + "topEntries\"\x88\x01\n" + + "\x1dListWeeklyStarHistoryResponse\x12A\n" + + "\x06cycles\x18\x01 \x03(\v2).hyapp.activity.v1.WeeklyStarHistoryCycleR\x06cycles\x12$\n" + + "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs2\xe2\x01\n" + "\x0fActivityService\x12_\n" + "\fPingActivity\x12&.hyapp.activity.v1.PingActivityRequest\x1a'.hyapp.activity.v1.PingActivityResponse\x12n\n" + "\x11GetActivityStatus\x12+.hyapp.activity.v1.GetActivityStatusRequest\x1a,.hyapp.activity.v1.GetActivityStatusResponse2\xb1\x06\n" + @@ -13700,11 +17779,13 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\x14MarkInboxSectionRead\x12..hyapp.activity.v1.MarkInboxSectionReadRequest\x1a/.hyapp.activity.v1.MarkInboxSectionReadResponse\x12q\n" + "\x12DeleteInboxMessage\x12,.hyapp.activity.v1.DeleteInboxMessageRequest\x1a-.hyapp.activity.v1.DeleteInboxMessageResponse\x12q\n" + "\x12CreateInboxMessage\x12,.hyapp.activity.v1.CreateInboxMessageRequest\x1a-.hyapp.activity.v1.CreateInboxMessageResponse\x12h\n" + - "\x0fCreateFanoutJob\x12).hyapp.activity.v1.CreateFanoutJobRequest\x1a*.hyapp.activity.v1.CreateFanoutJobResponse2\xcf\x02\n" + + "\x0fCreateFanoutJob\x12).hyapp.activity.v1.CreateFanoutJobRequest\x1a*.hyapp.activity.v1.CreateFanoutJobResponse2\xb5\x04\n" + "\x13ActivityCronService\x12f\n" + "\x19ProcessMessageFanoutBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse\x12d\n" + "\x17ProcessLevelRewardBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse\x12j\n" + - "\x1dProcessAchievementRewardBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse2\xc8\x02\n" + + "\x1dProcessAchievementRewardBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse\x12u\n" + + "(ProcessRoomTurnoverRewardSettlementBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse\x12m\n" + + " ProcessWeeklyStarSettlementBatch\x12#.hyapp.activity.v1.CronBatchRequest\x1a$.hyapp.activity.v1.CronBatchResponse2\xc8\x02\n" + "\vTaskService\x12b\n" + "\rListUserTasks\x12'.hyapp.activity.v1.ListUserTasksRequest\x1a(.hyapp.activity.v1.ListUserTasksResponse\x12h\n" + "\x0fClaimTaskReward\x12).hyapp.activity.v1.ClaimTaskRewardRequest\x1a*.hyapp.activity.v1.ClaimTaskRewardResponse\x12k\n" + @@ -13723,7 +17804,13 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\x0fSetBadgeDisplay\x12).hyapp.activity.v1.SetBadgeDisplayRequest\x1a*.hyapp.activity.v1.SetBadgeDisplayResponse2\xf2\x01\n" + "\x10LuckyGiftService\x12e\n" + "\x0eCheckLuckyGift\x12(.hyapp.activity.v1.CheckLuckyGiftRequest\x1a).hyapp.activity.v1.CheckLuckyGiftResponse\x12w\n" + - "\x14ExecuteLuckyGiftDraw\x12..hyapp.activity.v1.ExecuteLuckyGiftDrawRequest\x1a/.hyapp.activity.v1.ExecuteLuckyGiftDrawResponse2\x8b\x05\n" + + "\x14ExecuteLuckyGiftDraw\x12..hyapp.activity.v1.ExecuteLuckyGiftDrawRequest\x1a/.hyapp.activity.v1.ExecuteLuckyGiftDrawResponse2\xaa\x01\n" + + "\x19RoomTurnoverRewardService\x12\x8c\x01\n" + + "\x1bGetRoomTurnoverRewardStatus\x125.hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest\x1a6.hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse2\x91\x03\n" + + "\x11WeeklyStarService\x12w\n" + + "\x14GetWeeklyStarCurrent\x12..hyapp.activity.v1.GetWeeklyStarCurrentRequest\x1a/.hyapp.activity.v1.GetWeeklyStarCurrentResponse\x12\x86\x01\n" + + "\x19ListWeeklyStarLeaderboard\x123.hyapp.activity.v1.ListWeeklyStarLeaderboardRequest\x1a4.hyapp.activity.v1.ListWeeklyStarLeaderboardResponse\x12z\n" + + "\x15ListWeeklyStarHistory\x12/.hyapp.activity.v1.ListWeeklyStarHistoryRequest\x1a0.hyapp.activity.v1.ListWeeklyStarHistoryResponse2\x8b\x05\n" + "\x10BroadcastService\x12z\n" + "\x15EnsureBroadcastGroups\x12/.hyapp.activity.v1.EnsureBroadcastGroupsRequest\x1a0.hyapp.activity.v1.EnsureBroadcastGroupsResponse\x12w\n" + "\x16PublishRegionBroadcast\x120.hyapp.activity.v1.PublishRegionBroadcastRequest\x1a+.hyapp.activity.v1.PublishBroadcastResponse\x12w\n" + @@ -13749,7 +17836,27 @@ const file_proto_activity_v1_activity_proto_rawDesc = "" + "\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" + + "\x1dListFirstRechargeRewardClaims\x127.hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest\x1a8.hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse2\xdd\x02\n" + + "\x1fCumulativeRechargeRewardService\x12\x9e\x01\n" + + "!GetCumulativeRechargeRewardStatus\x12;.hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest\x1a<.hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse\x12\x98\x01\n" + + "\x1fConsumeCumulativeRechargeReward\x129.hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest\x1a:.hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse2\x95\x04\n" + + "$AdminCumulativeRechargeRewardService\x12\x9e\x01\n" + + "!GetCumulativeRechargeRewardConfig\x12;.hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest\x1a<.hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse\x12\xa7\x01\n" + + "$UpdateCumulativeRechargeRewardConfig\x12>.hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest\x1a?.hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse\x12\xa1\x01\n" + + "\"ListCumulativeRechargeRewardGrants\x12<.hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest\x1a=.hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse2\x89\x05\n" + + "\x1eAdminRoomTurnoverRewardService\x12\x8c\x01\n" + + "\x1bGetRoomTurnoverRewardConfig\x125.hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest\x1a6.hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse\x12\x95\x01\n" + + "\x1eUpdateRoomTurnoverRewardConfig\x128.hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest\x1a9.hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse\x12\x9e\x01\n" + + "!ListRoomTurnoverRewardSettlements\x12;.hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest\x1a<.hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse\x12\x9e\x01\n" + + "!RetryRoomTurnoverRewardSettlement\x12;.hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest\x1a<.hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse2\x94\a\n" + + "\x16AdminWeeklyStarService\x12w\n" + + "\x14ListWeeklyStarCycles\x12..hyapp.activity.v1.ListWeeklyStarCyclesRequest\x1a/.hyapp.activity.v1.ListWeeklyStarCyclesResponse\x12z\n" + + "\x15CreateWeeklyStarCycle\x12/.hyapp.activity.v1.UpsertWeeklyStarCycleRequest\x1a0.hyapp.activity.v1.UpsertWeeklyStarCycleResponse\x12q\n" + + "\x12GetWeeklyStarCycle\x12,.hyapp.activity.v1.GetWeeklyStarCycleRequest\x1a-.hyapp.activity.v1.GetWeeklyStarCycleResponse\x12z\n" + + "\x15UpdateWeeklyStarCycle\x12/.hyapp.activity.v1.UpsertWeeklyStarCycleRequest\x1a0.hyapp.activity.v1.UpsertWeeklyStarCycleResponse\x12\x83\x01\n" + + "\x18SetWeeklyStarCycleStatus\x122.hyapp.activity.v1.SetWeeklyStarCycleStatusRequest\x1a3.hyapp.activity.v1.SetWeeklyStarCycleStatusResponse\x12\x86\x01\n" + + "\x19ListWeeklyStarLeaderboard\x123.hyapp.activity.v1.ListWeeklyStarLeaderboardRequest\x1a4.hyapp.activity.v1.ListWeeklyStarLeaderboardResponse\x12\x86\x01\n" + + "\x19ListWeeklyStarSettlements\x123.hyapp.activity.v1.ListWeeklyStarSettlementsRequest\x1a4.hyapp.activity.v1.ListWeeklyStarSettlementsResponse2\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" + @@ -13784,163 +17891,214 @@ 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, 154) +var file_proto_activity_v1_activity_proto_msgTypes = make([]protoimpl.MessageInfo, 205) var file_proto_activity_v1_activity_proto_goTypes = []any{ - (*RequestMeta)(nil), // 0: hyapp.activity.v1.RequestMeta - (*PingActivityRequest)(nil), // 1: hyapp.activity.v1.PingActivityRequest - (*PingActivityResponse)(nil), // 2: hyapp.activity.v1.PingActivityResponse - (*GetActivityStatusRequest)(nil), // 3: hyapp.activity.v1.GetActivityStatusRequest - (*GetActivityStatusResponse)(nil), // 4: hyapp.activity.v1.GetActivityStatusResponse - (*MessageTabSection)(nil), // 5: hyapp.activity.v1.MessageTabSection - (*ListMessageTabsRequest)(nil), // 6: hyapp.activity.v1.ListMessageTabsRequest - (*ListMessageTabsResponse)(nil), // 7: hyapp.activity.v1.ListMessageTabsResponse - (*InboxMessage)(nil), // 8: hyapp.activity.v1.InboxMessage - (*ListInboxMessagesRequest)(nil), // 9: hyapp.activity.v1.ListInboxMessagesRequest - (*ListInboxMessagesResponse)(nil), // 10: hyapp.activity.v1.ListInboxMessagesResponse - (*MarkInboxMessageReadRequest)(nil), // 11: hyapp.activity.v1.MarkInboxMessageReadRequest - (*MarkInboxMessageReadResponse)(nil), // 12: hyapp.activity.v1.MarkInboxMessageReadResponse - (*MarkInboxSectionReadRequest)(nil), // 13: hyapp.activity.v1.MarkInboxSectionReadRequest - (*MarkInboxSectionReadResponse)(nil), // 14: hyapp.activity.v1.MarkInboxSectionReadResponse - (*DeleteInboxMessageRequest)(nil), // 15: hyapp.activity.v1.DeleteInboxMessageRequest - (*DeleteInboxMessageResponse)(nil), // 16: hyapp.activity.v1.DeleteInboxMessageResponse - (*CreateInboxMessageRequest)(nil), // 17: hyapp.activity.v1.CreateInboxMessageRequest - (*CreateInboxMessageResponse)(nil), // 18: hyapp.activity.v1.CreateInboxMessageResponse - (*CreateFanoutJobRequest)(nil), // 19: hyapp.activity.v1.CreateFanoutJobRequest - (*CreateFanoutJobResponse)(nil), // 20: hyapp.activity.v1.CreateFanoutJobResponse - (*CronBatchRequest)(nil), // 21: hyapp.activity.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 22: hyapp.activity.v1.CronBatchResponse - (*TaskItem)(nil), // 23: hyapp.activity.v1.TaskItem - (*TaskSection)(nil), // 24: hyapp.activity.v1.TaskSection - (*ListUserTasksRequest)(nil), // 25: hyapp.activity.v1.ListUserTasksRequest - (*ListUserTasksResponse)(nil), // 26: hyapp.activity.v1.ListUserTasksResponse - (*ClaimTaskRewardRequest)(nil), // 27: hyapp.activity.v1.ClaimTaskRewardRequest - (*ClaimTaskRewardResponse)(nil), // 28: hyapp.activity.v1.ClaimTaskRewardResponse - (*ConsumeTaskEventRequest)(nil), // 29: hyapp.activity.v1.ConsumeTaskEventRequest - (*ConsumeTaskEventResponse)(nil), // 30: hyapp.activity.v1.ConsumeTaskEventResponse - (*BroadcastJoinGroup)(nil), // 31: hyapp.activity.v1.BroadcastJoinGroup - (*EnsureBroadcastGroupsRequest)(nil), // 32: hyapp.activity.v1.EnsureBroadcastGroupsRequest - (*EnsureBroadcastGroupsResponse)(nil), // 33: hyapp.activity.v1.EnsureBroadcastGroupsResponse - (*PublishRegionBroadcastRequest)(nil), // 34: hyapp.activity.v1.PublishRegionBroadcastRequest - (*PublishGlobalBroadcastRequest)(nil), // 35: hyapp.activity.v1.PublishGlobalBroadcastRequest - (*PublishBroadcastResponse)(nil), // 36: hyapp.activity.v1.PublishBroadcastResponse - (*RemoveRegionBroadcastMemberRequest)(nil), // 37: hyapp.activity.v1.RemoveRegionBroadcastMemberRequest - (*RemoveRegionBroadcastMemberResponse)(nil), // 38: hyapp.activity.v1.RemoveRegionBroadcastMemberResponse - (*ProcessBroadcastOutboxBatchResponse)(nil), // 39: hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse - (*ConsumeRoomEventRequest)(nil), // 40: hyapp.activity.v1.ConsumeRoomEventRequest - (*ConsumeRoomEventResponse)(nil), // 41: hyapp.activity.v1.ConsumeRoomEventResponse - (*TaskDefinition)(nil), // 42: hyapp.activity.v1.TaskDefinition - (*ListTaskDefinitionsRequest)(nil), // 43: hyapp.activity.v1.ListTaskDefinitionsRequest - (*ListTaskDefinitionsResponse)(nil), // 44: hyapp.activity.v1.ListTaskDefinitionsResponse - (*UpsertTaskDefinitionRequest)(nil), // 45: hyapp.activity.v1.UpsertTaskDefinitionRequest - (*UpsertTaskDefinitionResponse)(nil), // 46: hyapp.activity.v1.UpsertTaskDefinitionResponse - (*SetTaskDefinitionStatusRequest)(nil), // 47: hyapp.activity.v1.SetTaskDefinitionStatusRequest - (*SetTaskDefinitionStatusResponse)(nil), // 48: hyapp.activity.v1.SetTaskDefinitionStatusResponse - (*RegistrationRewardConfig)(nil), // 49: hyapp.activity.v1.RegistrationRewardConfig - (*RegistrationRewardClaim)(nil), // 50: hyapp.activity.v1.RegistrationRewardClaim - (*RegistrationRewardEligibility)(nil), // 51: hyapp.activity.v1.RegistrationRewardEligibility - (*GetRegistrationRewardEligibilityRequest)(nil), // 52: hyapp.activity.v1.GetRegistrationRewardEligibilityRequest - (*GetRegistrationRewardEligibilityResponse)(nil), // 53: hyapp.activity.v1.GetRegistrationRewardEligibilityResponse - (*IssueRegistrationRewardRequest)(nil), // 54: hyapp.activity.v1.IssueRegistrationRewardRequest - (*IssueRegistrationRewardResponse)(nil), // 55: hyapp.activity.v1.IssueRegistrationRewardResponse - (*GetRegistrationRewardConfigRequest)(nil), // 56: hyapp.activity.v1.GetRegistrationRewardConfigRequest - (*GetRegistrationRewardConfigResponse)(nil), // 57: hyapp.activity.v1.GetRegistrationRewardConfigResponse - (*UpdateRegistrationRewardConfigRequest)(nil), // 58: hyapp.activity.v1.UpdateRegistrationRewardConfigRequest - (*UpdateRegistrationRewardConfigResponse)(nil), // 59: hyapp.activity.v1.UpdateRegistrationRewardConfigResponse - (*ListRegistrationRewardClaimsRequest)(nil), // 60: hyapp.activity.v1.ListRegistrationRewardClaimsRequest - (*ListRegistrationRewardClaimsResponse)(nil), // 61: hyapp.activity.v1.ListRegistrationRewardClaimsResponse - (*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 - (*LevelDisplayTrackProfile)(nil), // 98: hyapp.activity.v1.LevelDisplayTrackProfile - (*UserLevelDisplayProfile)(nil), // 99: hyapp.activity.v1.UserLevelDisplayProfile - (*BatchGetUserLevelDisplayProfilesRequest)(nil), // 100: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest - (*BatchGetUserLevelDisplayProfilesResponse)(nil), // 101: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse - (*LevelRewardJob)(nil), // 102: hyapp.activity.v1.LevelRewardJob - (*ListLevelRewardsRequest)(nil), // 103: hyapp.activity.v1.ListLevelRewardsRequest - (*ListLevelRewardsResponse)(nil), // 104: hyapp.activity.v1.ListLevelRewardsResponse - (*ConsumeLevelEventRequest)(nil), // 105: hyapp.activity.v1.ConsumeLevelEventRequest - (*ConsumeLevelEventResponse)(nil), // 106: hyapp.activity.v1.ConsumeLevelEventResponse - (*RegistrationLevelBadgeGrant)(nil), // 107: hyapp.activity.v1.RegistrationLevelBadgeGrant - (*IssueRegistrationLevelBadgesRequest)(nil), // 108: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest - (*IssueRegistrationLevelBadgesResponse)(nil), // 109: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse - (*UpsertLevelTrackRequest)(nil), // 110: hyapp.activity.v1.UpsertLevelTrackRequest - (*UpsertLevelTrackResponse)(nil), // 111: hyapp.activity.v1.UpsertLevelTrackResponse - (*UpsertLevelRuleRequest)(nil), // 112: hyapp.activity.v1.UpsertLevelRuleRequest - (*UpsertLevelRuleResponse)(nil), // 113: hyapp.activity.v1.UpsertLevelRuleResponse - (*UpsertLevelTierRequest)(nil), // 114: hyapp.activity.v1.UpsertLevelTierRequest - (*UpsertLevelTierResponse)(nil), // 115: hyapp.activity.v1.UpsertLevelTierResponse - (*ListLevelConfigRequest)(nil), // 116: hyapp.activity.v1.ListLevelConfigRequest - (*ListLevelConfigResponse)(nil), // 117: hyapp.activity.v1.ListLevelConfigResponse - (*AchievementCondition)(nil), // 118: hyapp.activity.v1.AchievementCondition - (*AchievementDefinition)(nil), // 119: hyapp.activity.v1.AchievementDefinition - (*UserAchievement)(nil), // 120: hyapp.activity.v1.UserAchievement - (*ListAchievementsRequest)(nil), // 121: hyapp.activity.v1.ListAchievementsRequest - (*ListAchievementsResponse)(nil), // 122: hyapp.activity.v1.ListAchievementsResponse - (*ConsumeAchievementEventRequest)(nil), // 123: hyapp.activity.v1.ConsumeAchievementEventRequest - (*ConsumeAchievementEventResponse)(nil), // 124: hyapp.activity.v1.ConsumeAchievementEventResponse - (*BadgeDisplayItem)(nil), // 125: hyapp.activity.v1.BadgeDisplayItem - (*ListMyBadgesRequest)(nil), // 126: hyapp.activity.v1.ListMyBadgesRequest - (*ListMyBadgesResponse)(nil), // 127: hyapp.activity.v1.ListMyBadgesResponse - (*SetBadgeDisplayRequest)(nil), // 128: hyapp.activity.v1.SetBadgeDisplayRequest - (*SetBadgeDisplayResponse)(nil), // 129: hyapp.activity.v1.SetBadgeDisplayResponse - (*UpsertAchievementDefinitionRequest)(nil), // 130: hyapp.activity.v1.UpsertAchievementDefinitionRequest - (*UpsertAchievementDefinitionResponse)(nil), // 131: hyapp.activity.v1.UpsertAchievementDefinitionResponse - (*LuckyGiftMeta)(nil), // 132: hyapp.activity.v1.LuckyGiftMeta - (*LuckyGiftTier)(nil), // 133: hyapp.activity.v1.LuckyGiftTier - (*LuckyGiftConfig)(nil), // 134: hyapp.activity.v1.LuckyGiftConfig - (*LuckyGiftRuleTier)(nil), // 135: hyapp.activity.v1.LuckyGiftRuleTier - (*LuckyGiftRuleStage)(nil), // 136: hyapp.activity.v1.LuckyGiftRuleStage - (*LuckyGiftRuleConfig)(nil), // 137: hyapp.activity.v1.LuckyGiftRuleConfig - (*CheckLuckyGiftRequest)(nil), // 138: hyapp.activity.v1.CheckLuckyGiftRequest - (*CheckLuckyGiftResponse)(nil), // 139: hyapp.activity.v1.CheckLuckyGiftResponse - (*LuckyGiftDrawResult)(nil), // 140: hyapp.activity.v1.LuckyGiftDrawResult - (*ExecuteLuckyGiftDrawRequest)(nil), // 141: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest - (*ExecuteLuckyGiftDrawResponse)(nil), // 142: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse - (*GetLuckyGiftConfigRequest)(nil), // 143: hyapp.activity.v1.GetLuckyGiftConfigRequest - (*GetLuckyGiftConfigResponse)(nil), // 144: hyapp.activity.v1.GetLuckyGiftConfigResponse - (*UpsertLuckyGiftConfigRequest)(nil), // 145: hyapp.activity.v1.UpsertLuckyGiftConfigRequest - (*UpsertLuckyGiftConfigResponse)(nil), // 146: hyapp.activity.v1.UpsertLuckyGiftConfigResponse - (*ListLuckyGiftConfigsRequest)(nil), // 147: hyapp.activity.v1.ListLuckyGiftConfigsRequest - (*ListLuckyGiftConfigsResponse)(nil), // 148: hyapp.activity.v1.ListLuckyGiftConfigsResponse - (*ListLuckyGiftDrawsRequest)(nil), // 149: hyapp.activity.v1.ListLuckyGiftDrawsRequest - (*ListLuckyGiftDrawsResponse)(nil), // 150: hyapp.activity.v1.ListLuckyGiftDrawsResponse - (*LuckyGiftDrawSummary)(nil), // 151: hyapp.activity.v1.LuckyGiftDrawSummary - (*GetLuckyGiftDrawSummaryRequest)(nil), // 152: hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest - (*GetLuckyGiftDrawSummaryResponse)(nil), // 153: hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse - (*v1.EventEnvelope)(nil), // 154: hyapp.events.room.v1.EventEnvelope + (*RequestMeta)(nil), // 0: hyapp.activity.v1.RequestMeta + (*PingActivityRequest)(nil), // 1: hyapp.activity.v1.PingActivityRequest + (*PingActivityResponse)(nil), // 2: hyapp.activity.v1.PingActivityResponse + (*GetActivityStatusRequest)(nil), // 3: hyapp.activity.v1.GetActivityStatusRequest + (*GetActivityStatusResponse)(nil), // 4: hyapp.activity.v1.GetActivityStatusResponse + (*MessageTabSection)(nil), // 5: hyapp.activity.v1.MessageTabSection + (*ListMessageTabsRequest)(nil), // 6: hyapp.activity.v1.ListMessageTabsRequest + (*ListMessageTabsResponse)(nil), // 7: hyapp.activity.v1.ListMessageTabsResponse + (*InboxMessage)(nil), // 8: hyapp.activity.v1.InboxMessage + (*ListInboxMessagesRequest)(nil), // 9: hyapp.activity.v1.ListInboxMessagesRequest + (*ListInboxMessagesResponse)(nil), // 10: hyapp.activity.v1.ListInboxMessagesResponse + (*MarkInboxMessageReadRequest)(nil), // 11: hyapp.activity.v1.MarkInboxMessageReadRequest + (*MarkInboxMessageReadResponse)(nil), // 12: hyapp.activity.v1.MarkInboxMessageReadResponse + (*MarkInboxSectionReadRequest)(nil), // 13: hyapp.activity.v1.MarkInboxSectionReadRequest + (*MarkInboxSectionReadResponse)(nil), // 14: hyapp.activity.v1.MarkInboxSectionReadResponse + (*DeleteInboxMessageRequest)(nil), // 15: hyapp.activity.v1.DeleteInboxMessageRequest + (*DeleteInboxMessageResponse)(nil), // 16: hyapp.activity.v1.DeleteInboxMessageResponse + (*CreateInboxMessageRequest)(nil), // 17: hyapp.activity.v1.CreateInboxMessageRequest + (*CreateInboxMessageResponse)(nil), // 18: hyapp.activity.v1.CreateInboxMessageResponse + (*CreateFanoutJobRequest)(nil), // 19: hyapp.activity.v1.CreateFanoutJobRequest + (*CreateFanoutJobResponse)(nil), // 20: hyapp.activity.v1.CreateFanoutJobResponse + (*CronBatchRequest)(nil), // 21: hyapp.activity.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 22: hyapp.activity.v1.CronBatchResponse + (*TaskItem)(nil), // 23: hyapp.activity.v1.TaskItem + (*TaskSection)(nil), // 24: hyapp.activity.v1.TaskSection + (*ListUserTasksRequest)(nil), // 25: hyapp.activity.v1.ListUserTasksRequest + (*ListUserTasksResponse)(nil), // 26: hyapp.activity.v1.ListUserTasksResponse + (*ClaimTaskRewardRequest)(nil), // 27: hyapp.activity.v1.ClaimTaskRewardRequest + (*ClaimTaskRewardResponse)(nil), // 28: hyapp.activity.v1.ClaimTaskRewardResponse + (*ConsumeTaskEventRequest)(nil), // 29: hyapp.activity.v1.ConsumeTaskEventRequest + (*ConsumeTaskEventResponse)(nil), // 30: hyapp.activity.v1.ConsumeTaskEventResponse + (*BroadcastJoinGroup)(nil), // 31: hyapp.activity.v1.BroadcastJoinGroup + (*EnsureBroadcastGroupsRequest)(nil), // 32: hyapp.activity.v1.EnsureBroadcastGroupsRequest + (*EnsureBroadcastGroupsResponse)(nil), // 33: hyapp.activity.v1.EnsureBroadcastGroupsResponse + (*PublishRegionBroadcastRequest)(nil), // 34: hyapp.activity.v1.PublishRegionBroadcastRequest + (*PublishGlobalBroadcastRequest)(nil), // 35: hyapp.activity.v1.PublishGlobalBroadcastRequest + (*PublishBroadcastResponse)(nil), // 36: hyapp.activity.v1.PublishBroadcastResponse + (*RemoveRegionBroadcastMemberRequest)(nil), // 37: hyapp.activity.v1.RemoveRegionBroadcastMemberRequest + (*RemoveRegionBroadcastMemberResponse)(nil), // 38: hyapp.activity.v1.RemoveRegionBroadcastMemberResponse + (*ProcessBroadcastOutboxBatchResponse)(nil), // 39: hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse + (*ConsumeRoomEventRequest)(nil), // 40: hyapp.activity.v1.ConsumeRoomEventRequest + (*ConsumeRoomEventResponse)(nil), // 41: hyapp.activity.v1.ConsumeRoomEventResponse + (*TaskDefinition)(nil), // 42: hyapp.activity.v1.TaskDefinition + (*ListTaskDefinitionsRequest)(nil), // 43: hyapp.activity.v1.ListTaskDefinitionsRequest + (*ListTaskDefinitionsResponse)(nil), // 44: hyapp.activity.v1.ListTaskDefinitionsResponse + (*UpsertTaskDefinitionRequest)(nil), // 45: hyapp.activity.v1.UpsertTaskDefinitionRequest + (*UpsertTaskDefinitionResponse)(nil), // 46: hyapp.activity.v1.UpsertTaskDefinitionResponse + (*SetTaskDefinitionStatusRequest)(nil), // 47: hyapp.activity.v1.SetTaskDefinitionStatusRequest + (*SetTaskDefinitionStatusResponse)(nil), // 48: hyapp.activity.v1.SetTaskDefinitionStatusResponse + (*RegistrationRewardConfig)(nil), // 49: hyapp.activity.v1.RegistrationRewardConfig + (*RegistrationRewardClaim)(nil), // 50: hyapp.activity.v1.RegistrationRewardClaim + (*RegistrationRewardEligibility)(nil), // 51: hyapp.activity.v1.RegistrationRewardEligibility + (*GetRegistrationRewardEligibilityRequest)(nil), // 52: hyapp.activity.v1.GetRegistrationRewardEligibilityRequest + (*GetRegistrationRewardEligibilityResponse)(nil), // 53: hyapp.activity.v1.GetRegistrationRewardEligibilityResponse + (*IssueRegistrationRewardRequest)(nil), // 54: hyapp.activity.v1.IssueRegistrationRewardRequest + (*IssueRegistrationRewardResponse)(nil), // 55: hyapp.activity.v1.IssueRegistrationRewardResponse + (*GetRegistrationRewardConfigRequest)(nil), // 56: hyapp.activity.v1.GetRegistrationRewardConfigRequest + (*GetRegistrationRewardConfigResponse)(nil), // 57: hyapp.activity.v1.GetRegistrationRewardConfigResponse + (*UpdateRegistrationRewardConfigRequest)(nil), // 58: hyapp.activity.v1.UpdateRegistrationRewardConfigRequest + (*UpdateRegistrationRewardConfigResponse)(nil), // 59: hyapp.activity.v1.UpdateRegistrationRewardConfigResponse + (*ListRegistrationRewardClaimsRequest)(nil), // 60: hyapp.activity.v1.ListRegistrationRewardClaimsRequest + (*ListRegistrationRewardClaimsResponse)(nil), // 61: hyapp.activity.v1.ListRegistrationRewardClaimsResponse + (*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 + (*CumulativeRechargeRewardTier)(nil), // 76: hyapp.activity.v1.CumulativeRechargeRewardTier + (*CumulativeRechargeRewardConfig)(nil), // 77: hyapp.activity.v1.CumulativeRechargeRewardConfig + (*CumulativeRechargeRewardGrant)(nil), // 78: hyapp.activity.v1.CumulativeRechargeRewardGrant + (*CumulativeRechargeRewardProgress)(nil), // 79: hyapp.activity.v1.CumulativeRechargeRewardProgress + (*CumulativeRechargeRewardStatus)(nil), // 80: hyapp.activity.v1.CumulativeRechargeRewardStatus + (*GetCumulativeRechargeRewardStatusRequest)(nil), // 81: hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest + (*GetCumulativeRechargeRewardStatusResponse)(nil), // 82: hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse + (*ConsumeCumulativeRechargeRewardRequest)(nil), // 83: hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest + (*ConsumeCumulativeRechargeRewardResponse)(nil), // 84: hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse + (*GetCumulativeRechargeRewardConfigRequest)(nil), // 85: hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest + (*GetCumulativeRechargeRewardConfigResponse)(nil), // 86: hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse + (*UpdateCumulativeRechargeRewardConfigRequest)(nil), // 87: hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest + (*UpdateCumulativeRechargeRewardConfigResponse)(nil), // 88: hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse + (*ListCumulativeRechargeRewardGrantsRequest)(nil), // 89: hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest + (*ListCumulativeRechargeRewardGrantsResponse)(nil), // 90: hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse + (*RoomTurnoverRewardTier)(nil), // 91: hyapp.activity.v1.RoomTurnoverRewardTier + (*RoomTurnoverRewardConfig)(nil), // 92: hyapp.activity.v1.RoomTurnoverRewardConfig + (*RoomTurnoverRewardSettlement)(nil), // 93: hyapp.activity.v1.RoomTurnoverRewardSettlement + (*RoomTurnoverRewardStatus)(nil), // 94: hyapp.activity.v1.RoomTurnoverRewardStatus + (*GetRoomTurnoverRewardStatusRequest)(nil), // 95: hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest + (*GetRoomTurnoverRewardStatusResponse)(nil), // 96: hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse + (*GetRoomTurnoverRewardConfigRequest)(nil), // 97: hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest + (*GetRoomTurnoverRewardConfigResponse)(nil), // 98: hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse + (*UpdateRoomTurnoverRewardConfigRequest)(nil), // 99: hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest + (*UpdateRoomTurnoverRewardConfigResponse)(nil), // 100: hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse + (*ListRoomTurnoverRewardSettlementsRequest)(nil), // 101: hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest + (*ListRoomTurnoverRewardSettlementsResponse)(nil), // 102: hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse + (*RetryRoomTurnoverRewardSettlementRequest)(nil), // 103: hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest + (*RetryRoomTurnoverRewardSettlementResponse)(nil), // 104: hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse + (*SevenDayCheckInReward)(nil), // 105: hyapp.activity.v1.SevenDayCheckInReward + (*SevenDayCheckInConfig)(nil), // 106: hyapp.activity.v1.SevenDayCheckInConfig + (*SevenDayCheckInRewardStatus)(nil), // 107: hyapp.activity.v1.SevenDayCheckInRewardStatus + (*GetSevenDayCheckInStatusRequest)(nil), // 108: hyapp.activity.v1.GetSevenDayCheckInStatusRequest + (*GetSevenDayCheckInStatusResponse)(nil), // 109: hyapp.activity.v1.GetSevenDayCheckInStatusResponse + (*SignSevenDayCheckInRequest)(nil), // 110: hyapp.activity.v1.SignSevenDayCheckInRequest + (*SignSevenDayCheckInResponse)(nil), // 111: hyapp.activity.v1.SignSevenDayCheckInResponse + (*GetSevenDayCheckInConfigRequest)(nil), // 112: hyapp.activity.v1.GetSevenDayCheckInConfigRequest + (*GetSevenDayCheckInConfigResponse)(nil), // 113: hyapp.activity.v1.GetSevenDayCheckInConfigResponse + (*UpdateSevenDayCheckInConfigRequest)(nil), // 114: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest + (*UpdateSevenDayCheckInConfigResponse)(nil), // 115: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse + (*SevenDayCheckInClaim)(nil), // 116: hyapp.activity.v1.SevenDayCheckInClaim + (*ListSevenDayCheckInClaimsRequest)(nil), // 117: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest + (*ListSevenDayCheckInClaimsResponse)(nil), // 118: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse + (*LevelTrack)(nil), // 119: hyapp.activity.v1.LevelTrack + (*LevelRule)(nil), // 120: hyapp.activity.v1.LevelRule + (*LevelTier)(nil), // 121: hyapp.activity.v1.LevelTier + (*LevelTrackOverview)(nil), // 122: hyapp.activity.v1.LevelTrackOverview + (*GetMyLevelOverviewRequest)(nil), // 123: hyapp.activity.v1.GetMyLevelOverviewRequest + (*GetMyLevelOverviewResponse)(nil), // 124: hyapp.activity.v1.GetMyLevelOverviewResponse + (*GetLevelTrackRequest)(nil), // 125: hyapp.activity.v1.GetLevelTrackRequest + (*GetLevelTrackResponse)(nil), // 126: hyapp.activity.v1.GetLevelTrackResponse + (*LevelDisplayTrackProfile)(nil), // 127: hyapp.activity.v1.LevelDisplayTrackProfile + (*UserLevelDisplayProfile)(nil), // 128: hyapp.activity.v1.UserLevelDisplayProfile + (*BatchGetUserLevelDisplayProfilesRequest)(nil), // 129: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest + (*BatchGetUserLevelDisplayProfilesResponse)(nil), // 130: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse + (*LevelRewardJob)(nil), // 131: hyapp.activity.v1.LevelRewardJob + (*ListLevelRewardsRequest)(nil), // 132: hyapp.activity.v1.ListLevelRewardsRequest + (*ListLevelRewardsResponse)(nil), // 133: hyapp.activity.v1.ListLevelRewardsResponse + (*ConsumeLevelEventRequest)(nil), // 134: hyapp.activity.v1.ConsumeLevelEventRequest + (*ConsumeLevelEventResponse)(nil), // 135: hyapp.activity.v1.ConsumeLevelEventResponse + (*RegistrationLevelBadgeGrant)(nil), // 136: hyapp.activity.v1.RegistrationLevelBadgeGrant + (*IssueRegistrationLevelBadgesRequest)(nil), // 137: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest + (*IssueRegistrationLevelBadgesResponse)(nil), // 138: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse + (*UpsertLevelTrackRequest)(nil), // 139: hyapp.activity.v1.UpsertLevelTrackRequest + (*UpsertLevelTrackResponse)(nil), // 140: hyapp.activity.v1.UpsertLevelTrackResponse + (*UpsertLevelRuleRequest)(nil), // 141: hyapp.activity.v1.UpsertLevelRuleRequest + (*UpsertLevelRuleResponse)(nil), // 142: hyapp.activity.v1.UpsertLevelRuleResponse + (*UpsertLevelTierRequest)(nil), // 143: hyapp.activity.v1.UpsertLevelTierRequest + (*UpsertLevelTierResponse)(nil), // 144: hyapp.activity.v1.UpsertLevelTierResponse + (*ListLevelConfigRequest)(nil), // 145: hyapp.activity.v1.ListLevelConfigRequest + (*ListLevelConfigResponse)(nil), // 146: hyapp.activity.v1.ListLevelConfigResponse + (*AchievementCondition)(nil), // 147: hyapp.activity.v1.AchievementCondition + (*AchievementDefinition)(nil), // 148: hyapp.activity.v1.AchievementDefinition + (*UserAchievement)(nil), // 149: hyapp.activity.v1.UserAchievement + (*ListAchievementsRequest)(nil), // 150: hyapp.activity.v1.ListAchievementsRequest + (*ListAchievementsResponse)(nil), // 151: hyapp.activity.v1.ListAchievementsResponse + (*ConsumeAchievementEventRequest)(nil), // 152: hyapp.activity.v1.ConsumeAchievementEventRequest + (*ConsumeAchievementEventResponse)(nil), // 153: hyapp.activity.v1.ConsumeAchievementEventResponse + (*BadgeDisplayItem)(nil), // 154: hyapp.activity.v1.BadgeDisplayItem + (*ListMyBadgesRequest)(nil), // 155: hyapp.activity.v1.ListMyBadgesRequest + (*ListMyBadgesResponse)(nil), // 156: hyapp.activity.v1.ListMyBadgesResponse + (*SetBadgeDisplayRequest)(nil), // 157: hyapp.activity.v1.SetBadgeDisplayRequest + (*SetBadgeDisplayResponse)(nil), // 158: hyapp.activity.v1.SetBadgeDisplayResponse + (*UpsertAchievementDefinitionRequest)(nil), // 159: hyapp.activity.v1.UpsertAchievementDefinitionRequest + (*UpsertAchievementDefinitionResponse)(nil), // 160: hyapp.activity.v1.UpsertAchievementDefinitionResponse + (*LuckyGiftMeta)(nil), // 161: hyapp.activity.v1.LuckyGiftMeta + (*LuckyGiftTier)(nil), // 162: hyapp.activity.v1.LuckyGiftTier + (*LuckyGiftConfig)(nil), // 163: hyapp.activity.v1.LuckyGiftConfig + (*LuckyGiftRuleTier)(nil), // 164: hyapp.activity.v1.LuckyGiftRuleTier + (*LuckyGiftRuleStage)(nil), // 165: hyapp.activity.v1.LuckyGiftRuleStage + (*LuckyGiftRuleConfig)(nil), // 166: hyapp.activity.v1.LuckyGiftRuleConfig + (*CheckLuckyGiftRequest)(nil), // 167: hyapp.activity.v1.CheckLuckyGiftRequest + (*CheckLuckyGiftResponse)(nil), // 168: hyapp.activity.v1.CheckLuckyGiftResponse + (*LuckyGiftDrawResult)(nil), // 169: hyapp.activity.v1.LuckyGiftDrawResult + (*ExecuteLuckyGiftDrawRequest)(nil), // 170: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest + (*ExecuteLuckyGiftDrawResponse)(nil), // 171: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse + (*GetLuckyGiftConfigRequest)(nil), // 172: hyapp.activity.v1.GetLuckyGiftConfigRequest + (*GetLuckyGiftConfigResponse)(nil), // 173: hyapp.activity.v1.GetLuckyGiftConfigResponse + (*UpsertLuckyGiftConfigRequest)(nil), // 174: hyapp.activity.v1.UpsertLuckyGiftConfigRequest + (*UpsertLuckyGiftConfigResponse)(nil), // 175: hyapp.activity.v1.UpsertLuckyGiftConfigResponse + (*ListLuckyGiftConfigsRequest)(nil), // 176: hyapp.activity.v1.ListLuckyGiftConfigsRequest + (*ListLuckyGiftConfigsResponse)(nil), // 177: hyapp.activity.v1.ListLuckyGiftConfigsResponse + (*ListLuckyGiftDrawsRequest)(nil), // 178: hyapp.activity.v1.ListLuckyGiftDrawsRequest + (*ListLuckyGiftDrawsResponse)(nil), // 179: hyapp.activity.v1.ListLuckyGiftDrawsResponse + (*LuckyGiftDrawSummary)(nil), // 180: hyapp.activity.v1.LuckyGiftDrawSummary + (*GetLuckyGiftDrawSummaryRequest)(nil), // 181: hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest + (*GetLuckyGiftDrawSummaryResponse)(nil), // 182: hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse + (*WeeklyStarGift)(nil), // 183: hyapp.activity.v1.WeeklyStarGift + (*WeeklyStarReward)(nil), // 184: hyapp.activity.v1.WeeklyStarReward + (*WeeklyStarCycle)(nil), // 185: hyapp.activity.v1.WeeklyStarCycle + (*WeeklyStarLeaderboardEntry)(nil), // 186: hyapp.activity.v1.WeeklyStarLeaderboardEntry + (*WeeklyStarSettlement)(nil), // 187: hyapp.activity.v1.WeeklyStarSettlement + (*ListWeeklyStarCyclesRequest)(nil), // 188: hyapp.activity.v1.ListWeeklyStarCyclesRequest + (*ListWeeklyStarCyclesResponse)(nil), // 189: hyapp.activity.v1.ListWeeklyStarCyclesResponse + (*GetWeeklyStarCycleRequest)(nil), // 190: hyapp.activity.v1.GetWeeklyStarCycleRequest + (*GetWeeklyStarCycleResponse)(nil), // 191: hyapp.activity.v1.GetWeeklyStarCycleResponse + (*UpsertWeeklyStarCycleRequest)(nil), // 192: hyapp.activity.v1.UpsertWeeklyStarCycleRequest + (*UpsertWeeklyStarCycleResponse)(nil), // 193: hyapp.activity.v1.UpsertWeeklyStarCycleResponse + (*SetWeeklyStarCycleStatusRequest)(nil), // 194: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest + (*SetWeeklyStarCycleStatusResponse)(nil), // 195: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse + (*ListWeeklyStarLeaderboardRequest)(nil), // 196: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + (*ListWeeklyStarLeaderboardResponse)(nil), // 197: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + (*ListWeeklyStarSettlementsRequest)(nil), // 198: hyapp.activity.v1.ListWeeklyStarSettlementsRequest + (*ListWeeklyStarSettlementsResponse)(nil), // 199: hyapp.activity.v1.ListWeeklyStarSettlementsResponse + (*GetWeeklyStarCurrentRequest)(nil), // 200: hyapp.activity.v1.GetWeeklyStarCurrentRequest + (*GetWeeklyStarCurrentResponse)(nil), // 201: hyapp.activity.v1.GetWeeklyStarCurrentResponse + (*ListWeeklyStarHistoryRequest)(nil), // 202: hyapp.activity.v1.ListWeeklyStarHistoryRequest + (*WeeklyStarHistoryCycle)(nil), // 203: hyapp.activity.v1.WeeklyStarHistoryCycle + (*ListWeeklyStarHistoryResponse)(nil), // 204: hyapp.activity.v1.ListWeeklyStarHistoryResponse + (*v1.EventEnvelope)(nil), // 205: 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 @@ -13965,7 +18123,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 - 154, // 22: hyapp.activity.v1.ConsumeRoomEventRequest.envelope:type_name -> hyapp.events.room.v1.EventEnvelope + 205, // 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 @@ -13997,205 +18155,303 @@ var file_proto_activity_v1_activity_proto_depIdxs = []int32{ 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 - 98, // 71: hyapp.activity.v1.UserLevelDisplayProfile.wealth:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile - 98, // 72: hyapp.activity.v1.UserLevelDisplayProfile.game:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile - 98, // 73: hyapp.activity.v1.UserLevelDisplayProfile.charm:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile - 0, // 74: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 99, // 75: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse.profiles:type_name -> hyapp.activity.v1.UserLevelDisplayProfile - 0, // 76: hyapp.activity.v1.ListLevelRewardsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 102, // 77: hyapp.activity.v1.ListLevelRewardsResponse.rewards:type_name -> hyapp.activity.v1.LevelRewardJob - 0, // 78: hyapp.activity.v1.ConsumeLevelEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 79: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 107, // 80: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse.grants:type_name -> hyapp.activity.v1.RegistrationLevelBadgeGrant - 0, // 81: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 90, // 82: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack - 0, // 83: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 91, // 84: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule - 0, // 85: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 92, // 86: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier - 0, // 87: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 90, // 88: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack - 91, // 89: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule - 92, // 90: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier - 118, // 91: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 119, // 92: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 93: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 120, // 94: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement - 0, // 95: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 0, // 96: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 125, // 97: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 125, // 98: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 125, // 99: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem - 0, // 100: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 125, // 101: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem - 127, // 102: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse - 0, // 103: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 118, // 104: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition - 119, // 105: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition - 0, // 106: hyapp.activity.v1.LuckyGiftMeta.meta:type_name -> hyapp.activity.v1.RequestMeta - 133, // 107: hyapp.activity.v1.LuckyGiftConfig.tiers:type_name -> hyapp.activity.v1.LuckyGiftTier - 135, // 108: hyapp.activity.v1.LuckyGiftRuleStage.tiers:type_name -> hyapp.activity.v1.LuckyGiftRuleTier - 136, // 109: hyapp.activity.v1.LuckyGiftRuleConfig.stages:type_name -> hyapp.activity.v1.LuckyGiftRuleStage - 0, // 110: hyapp.activity.v1.CheckLuckyGiftRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 132, // 111: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest.lucky_gift:type_name -> hyapp.activity.v1.LuckyGiftMeta - 140, // 112: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse.result:type_name -> hyapp.activity.v1.LuckyGiftDrawResult - 0, // 113: hyapp.activity.v1.GetLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 137, // 114: hyapp.activity.v1.GetLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig - 0, // 115: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 137, // 116: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig - 137, // 117: hyapp.activity.v1.UpsertLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig - 0, // 118: hyapp.activity.v1.ListLuckyGiftConfigsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 137, // 119: hyapp.activity.v1.ListLuckyGiftConfigsResponse.configs:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig - 0, // 120: hyapp.activity.v1.ListLuckyGiftDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 140, // 121: hyapp.activity.v1.ListLuckyGiftDrawsResponse.draws:type_name -> hyapp.activity.v1.LuckyGiftDrawResult - 0, // 122: hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta - 151, // 123: hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse.summary:type_name -> hyapp.activity.v1.LuckyGiftDrawSummary - 1, // 124: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest - 3, // 125: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest - 6, // 126: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest - 9, // 127: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest - 11, // 128: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest - 13, // 129: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest - 15, // 130: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest - 17, // 131: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest - 19, // 132: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest - 21, // 133: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 21, // 134: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 21, // 135: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 25, // 136: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest - 27, // 137: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest - 29, // 138: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest - 94, // 139: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest - 96, // 140: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest - 100, // 141: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:input_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest - 103, // 142: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest - 105, // 143: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest - 108, // 144: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:input_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesRequest - 121, // 145: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest - 123, // 146: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest - 126, // 147: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest - 128, // 148: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest - 138, // 149: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:input_type -> hyapp.activity.v1.CheckLuckyGiftRequest - 141, // 150: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:input_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawRequest - 32, // 151: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest - 34, // 152: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest - 35, // 153: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest - 37, // 154: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest - 21, // 155: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest - 40, // 156: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest - 43, // 157: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest - 45, // 158: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest - 47, // 159: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest - 52, // 160: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest - 54, // 161: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest - 56, // 162: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest - 58, // 163: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest - 60, // 164: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest - 66, // 165: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:input_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusRequest - 68, // 166: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:input_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardRequest - 70, // 167: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigRequest - 72, // 168: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest - 74, // 169: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:input_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest - 79, // 170: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest - 81, // 171: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest - 83, // 172: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest - 85, // 173: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest - 88, // 174: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest - 116, // 175: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest - 110, // 176: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest - 112, // 177: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest - 114, // 178: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest - 121, // 179: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest - 130, // 180: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest - 143, // 181: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:input_type -> hyapp.activity.v1.GetLuckyGiftConfigRequest - 145, // 182: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:input_type -> hyapp.activity.v1.UpsertLuckyGiftConfigRequest - 147, // 183: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:input_type -> hyapp.activity.v1.ListLuckyGiftConfigsRequest - 149, // 184: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:input_type -> hyapp.activity.v1.ListLuckyGiftDrawsRequest - 152, // 185: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftDrawSummary:input_type -> hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest - 2, // 186: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse - 4, // 187: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse - 7, // 188: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse - 10, // 189: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse - 12, // 190: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse - 14, // 191: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse - 16, // 192: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse - 18, // 193: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse - 20, // 194: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse - 22, // 195: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 22, // 196: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 22, // 197: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse - 26, // 198: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse - 28, // 199: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse - 30, // 200: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse - 95, // 201: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse - 97, // 202: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse - 101, // 203: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:output_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse - 104, // 204: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse - 106, // 205: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse - 109, // 206: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:output_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesResponse - 122, // 207: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse - 124, // 208: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse - 127, // 209: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse - 129, // 210: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse - 139, // 211: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:output_type -> hyapp.activity.v1.CheckLuckyGiftResponse - 142, // 212: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:output_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawResponse - 33, // 213: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse - 36, // 214: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 36, // 215: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse - 38, // 216: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse - 39, // 217: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse - 41, // 218: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse - 44, // 219: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse - 46, // 220: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse - 48, // 221: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse - 53, // 222: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse - 55, // 223: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse - 57, // 224: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse - 59, // 225: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse - 61, // 226: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse - 67, // 227: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:output_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusResponse - 69, // 228: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:output_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardResponse - 71, // 229: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigResponse - 73, // 230: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse - 75, // 231: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:output_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse - 80, // 232: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse - 82, // 233: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse - 84, // 234: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse - 86, // 235: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse - 89, // 236: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse - 117, // 237: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse - 111, // 238: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse - 113, // 239: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse - 115, // 240: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse - 122, // 241: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse - 131, // 242: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse - 144, // 243: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:output_type -> hyapp.activity.v1.GetLuckyGiftConfigResponse - 146, // 244: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:output_type -> hyapp.activity.v1.UpsertLuckyGiftConfigResponse - 148, // 245: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:output_type -> hyapp.activity.v1.ListLuckyGiftConfigsResponse - 150, // 246: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:output_type -> hyapp.activity.v1.ListLuckyGiftDrawsResponse - 153, // 247: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftDrawSummary:output_type -> hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse - 186, // [186:248] is the sub-list for method output_type - 124, // [124:186] is the sub-list for method input_type - 124, // [124:124] is the sub-list for extension type_name - 124, // [124:124] is the sub-list for extension extendee - 0, // [0:124] is the sub-list for field type_name + 76, // 54: hyapp.activity.v1.CumulativeRechargeRewardConfig.tiers:type_name -> hyapp.activity.v1.CumulativeRechargeRewardTier + 77, // 55: hyapp.activity.v1.CumulativeRechargeRewardStatus.config:type_name -> hyapp.activity.v1.CumulativeRechargeRewardConfig + 79, // 56: hyapp.activity.v1.CumulativeRechargeRewardStatus.progress:type_name -> hyapp.activity.v1.CumulativeRechargeRewardProgress + 78, // 57: hyapp.activity.v1.CumulativeRechargeRewardStatus.grants:type_name -> hyapp.activity.v1.CumulativeRechargeRewardGrant + 0, // 58: hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 80, // 59: hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse.status:type_name -> hyapp.activity.v1.CumulativeRechargeRewardStatus + 0, // 60: hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 78, // 61: hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse.grants:type_name -> hyapp.activity.v1.CumulativeRechargeRewardGrant + 0, // 62: hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 77, // 63: hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse.config:type_name -> hyapp.activity.v1.CumulativeRechargeRewardConfig + 0, // 64: hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 76, // 65: hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest.tiers:type_name -> hyapp.activity.v1.CumulativeRechargeRewardTier + 77, // 66: hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse.config:type_name -> hyapp.activity.v1.CumulativeRechargeRewardConfig + 0, // 67: hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 78, // 68: hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse.grants:type_name -> hyapp.activity.v1.CumulativeRechargeRewardGrant + 91, // 69: hyapp.activity.v1.RoomTurnoverRewardConfig.tiers:type_name -> hyapp.activity.v1.RoomTurnoverRewardTier + 92, // 70: hyapp.activity.v1.RoomTurnoverRewardStatus.config:type_name -> hyapp.activity.v1.RoomTurnoverRewardConfig + 91, // 71: hyapp.activity.v1.RoomTurnoverRewardStatus.matched_tier:type_name -> hyapp.activity.v1.RoomTurnoverRewardTier + 93, // 72: hyapp.activity.v1.RoomTurnoverRewardStatus.latest_settlement:type_name -> hyapp.activity.v1.RoomTurnoverRewardSettlement + 0, // 73: hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 94, // 74: hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse.status:type_name -> hyapp.activity.v1.RoomTurnoverRewardStatus + 0, // 75: hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 92, // 76: hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse.config:type_name -> hyapp.activity.v1.RoomTurnoverRewardConfig + 0, // 77: hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 91, // 78: hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest.tiers:type_name -> hyapp.activity.v1.RoomTurnoverRewardTier + 92, // 79: hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse.config:type_name -> hyapp.activity.v1.RoomTurnoverRewardConfig + 0, // 80: hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 93, // 81: hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse.settlements:type_name -> hyapp.activity.v1.RoomTurnoverRewardSettlement + 0, // 82: hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 93, // 83: hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse.settlement:type_name -> hyapp.activity.v1.RoomTurnoverRewardSettlement + 105, // 84: hyapp.activity.v1.SevenDayCheckInConfig.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward + 0, // 85: hyapp.activity.v1.GetSevenDayCheckInStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 107, // 86: hyapp.activity.v1.GetSevenDayCheckInStatusResponse.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInRewardStatus + 0, // 87: hyapp.activity.v1.SignSevenDayCheckInRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 88: hyapp.activity.v1.GetSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 106, // 89: hyapp.activity.v1.GetSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig + 0, // 90: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 105, // 91: hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest.rewards:type_name -> hyapp.activity.v1.SevenDayCheckInReward + 106, // 92: hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse.config:type_name -> hyapp.activity.v1.SevenDayCheckInConfig + 0, // 93: hyapp.activity.v1.ListSevenDayCheckInClaimsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 116, // 94: hyapp.activity.v1.ListSevenDayCheckInClaimsResponse.claims:type_name -> hyapp.activity.v1.SevenDayCheckInClaim + 0, // 95: hyapp.activity.v1.GetMyLevelOverviewRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 122, // 96: hyapp.activity.v1.GetMyLevelOverviewResponse.tracks:type_name -> hyapp.activity.v1.LevelTrackOverview + 0, // 97: hyapp.activity.v1.GetLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 122, // 98: hyapp.activity.v1.GetLevelTrackResponse.overview:type_name -> hyapp.activity.v1.LevelTrackOverview + 120, // 99: hyapp.activity.v1.GetLevelTrackResponse.rules:type_name -> hyapp.activity.v1.LevelRule + 121, // 100: hyapp.activity.v1.GetLevelTrackResponse.tiers:type_name -> hyapp.activity.v1.LevelTier + 127, // 101: hyapp.activity.v1.UserLevelDisplayProfile.wealth:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile + 127, // 102: hyapp.activity.v1.UserLevelDisplayProfile.game:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile + 127, // 103: hyapp.activity.v1.UserLevelDisplayProfile.charm:type_name -> hyapp.activity.v1.LevelDisplayTrackProfile + 0, // 104: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 128, // 105: hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse.profiles:type_name -> hyapp.activity.v1.UserLevelDisplayProfile + 0, // 106: hyapp.activity.v1.ListLevelRewardsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 131, // 107: hyapp.activity.v1.ListLevelRewardsResponse.rewards:type_name -> hyapp.activity.v1.LevelRewardJob + 0, // 108: hyapp.activity.v1.ConsumeLevelEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 109: hyapp.activity.v1.IssueRegistrationLevelBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 136, // 110: hyapp.activity.v1.IssueRegistrationLevelBadgesResponse.grants:type_name -> hyapp.activity.v1.RegistrationLevelBadgeGrant + 0, // 111: hyapp.activity.v1.UpsertLevelTrackRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 119, // 112: hyapp.activity.v1.UpsertLevelTrackResponse.track:type_name -> hyapp.activity.v1.LevelTrack + 0, // 113: hyapp.activity.v1.UpsertLevelRuleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 120, // 114: hyapp.activity.v1.UpsertLevelRuleResponse.rule:type_name -> hyapp.activity.v1.LevelRule + 0, // 115: hyapp.activity.v1.UpsertLevelTierRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 121, // 116: hyapp.activity.v1.UpsertLevelTierResponse.tier:type_name -> hyapp.activity.v1.LevelTier + 0, // 117: hyapp.activity.v1.ListLevelConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 119, // 118: hyapp.activity.v1.ListLevelConfigResponse.tracks:type_name -> hyapp.activity.v1.LevelTrack + 120, // 119: hyapp.activity.v1.ListLevelConfigResponse.rules:type_name -> hyapp.activity.v1.LevelRule + 121, // 120: hyapp.activity.v1.ListLevelConfigResponse.tiers:type_name -> hyapp.activity.v1.LevelTier + 147, // 121: hyapp.activity.v1.AchievementDefinition.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 148, // 122: hyapp.activity.v1.UserAchievement.definition:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 123: hyapp.activity.v1.ListAchievementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 149, // 124: hyapp.activity.v1.ListAchievementsResponse.achievements:type_name -> hyapp.activity.v1.UserAchievement + 0, // 125: hyapp.activity.v1.ConsumeAchievementEventRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 0, // 126: hyapp.activity.v1.ListMyBadgesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 154, // 127: hyapp.activity.v1.ListMyBadgesResponse.strip_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 154, // 128: hyapp.activity.v1.ListMyBadgesResponse.profile_tile_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 154, // 129: hyapp.activity.v1.ListMyBadgesResponse.honor_badges:type_name -> hyapp.activity.v1.BadgeDisplayItem + 0, // 130: hyapp.activity.v1.SetBadgeDisplayRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 154, // 131: hyapp.activity.v1.SetBadgeDisplayRequest.items:type_name -> hyapp.activity.v1.BadgeDisplayItem + 156, // 132: hyapp.activity.v1.SetBadgeDisplayResponse.profile:type_name -> hyapp.activity.v1.ListMyBadgesResponse + 0, // 133: hyapp.activity.v1.UpsertAchievementDefinitionRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 147, // 134: hyapp.activity.v1.UpsertAchievementDefinitionRequest.conditions:type_name -> hyapp.activity.v1.AchievementCondition + 148, // 135: hyapp.activity.v1.UpsertAchievementDefinitionResponse.achievement:type_name -> hyapp.activity.v1.AchievementDefinition + 0, // 136: hyapp.activity.v1.LuckyGiftMeta.meta:type_name -> hyapp.activity.v1.RequestMeta + 162, // 137: hyapp.activity.v1.LuckyGiftConfig.tiers:type_name -> hyapp.activity.v1.LuckyGiftTier + 164, // 138: hyapp.activity.v1.LuckyGiftRuleStage.tiers:type_name -> hyapp.activity.v1.LuckyGiftRuleTier + 165, // 139: hyapp.activity.v1.LuckyGiftRuleConfig.stages:type_name -> hyapp.activity.v1.LuckyGiftRuleStage + 0, // 140: hyapp.activity.v1.CheckLuckyGiftRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 161, // 141: hyapp.activity.v1.ExecuteLuckyGiftDrawRequest.lucky_gift:type_name -> hyapp.activity.v1.LuckyGiftMeta + 169, // 142: hyapp.activity.v1.ExecuteLuckyGiftDrawResponse.result:type_name -> hyapp.activity.v1.LuckyGiftDrawResult + 0, // 143: hyapp.activity.v1.GetLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 166, // 144: hyapp.activity.v1.GetLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig + 0, // 145: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 166, // 146: hyapp.activity.v1.UpsertLuckyGiftConfigRequest.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig + 166, // 147: hyapp.activity.v1.UpsertLuckyGiftConfigResponse.config:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig + 0, // 148: hyapp.activity.v1.ListLuckyGiftConfigsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 166, // 149: hyapp.activity.v1.ListLuckyGiftConfigsResponse.configs:type_name -> hyapp.activity.v1.LuckyGiftRuleConfig + 0, // 150: hyapp.activity.v1.ListLuckyGiftDrawsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 169, // 151: hyapp.activity.v1.ListLuckyGiftDrawsResponse.draws:type_name -> hyapp.activity.v1.LuckyGiftDrawResult + 0, // 152: hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 180, // 153: hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse.summary:type_name -> hyapp.activity.v1.LuckyGiftDrawSummary + 183, // 154: hyapp.activity.v1.WeeklyStarCycle.gifts:type_name -> hyapp.activity.v1.WeeklyStarGift + 184, // 155: hyapp.activity.v1.WeeklyStarCycle.rewards:type_name -> hyapp.activity.v1.WeeklyStarReward + 0, // 156: hyapp.activity.v1.ListWeeklyStarCyclesRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 157: hyapp.activity.v1.ListWeeklyStarCyclesResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 158: hyapp.activity.v1.GetWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 159: hyapp.activity.v1.GetWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 160: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 161: hyapp.activity.v1.UpsertWeeklyStarCycleRequest.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 185, // 162: hyapp.activity.v1.UpsertWeeklyStarCycleResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 163: hyapp.activity.v1.SetWeeklyStarCycleStatusRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 164: hyapp.activity.v1.SetWeeklyStarCycleStatusResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 0, // 165: hyapp.activity.v1.ListWeeklyStarLeaderboardRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 166: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 186, // 167: hyapp.activity.v1.ListWeeklyStarLeaderboardResponse.entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 0, // 168: hyapp.activity.v1.ListWeeklyStarSettlementsRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 187, // 169: hyapp.activity.v1.ListWeeklyStarSettlementsResponse.settlements:type_name -> hyapp.activity.v1.WeeklyStarSettlement + 0, // 170: hyapp.activity.v1.GetWeeklyStarCurrentRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 171: hyapp.activity.v1.GetWeeklyStarCurrentResponse.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 186, // 172: hyapp.activity.v1.GetWeeklyStarCurrentResponse.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 186, // 173: hyapp.activity.v1.GetWeeklyStarCurrentResponse.my_entry:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 0, // 174: hyapp.activity.v1.ListWeeklyStarHistoryRequest.meta:type_name -> hyapp.activity.v1.RequestMeta + 185, // 175: hyapp.activity.v1.WeeklyStarHistoryCycle.cycle:type_name -> hyapp.activity.v1.WeeklyStarCycle + 186, // 176: hyapp.activity.v1.WeeklyStarHistoryCycle.top_entries:type_name -> hyapp.activity.v1.WeeklyStarLeaderboardEntry + 203, // 177: hyapp.activity.v1.ListWeeklyStarHistoryResponse.cycles:type_name -> hyapp.activity.v1.WeeklyStarHistoryCycle + 1, // 178: hyapp.activity.v1.ActivityService.PingActivity:input_type -> hyapp.activity.v1.PingActivityRequest + 3, // 179: hyapp.activity.v1.ActivityService.GetActivityStatus:input_type -> hyapp.activity.v1.GetActivityStatusRequest + 6, // 180: hyapp.activity.v1.MessageInboxService.ListMessageTabs:input_type -> hyapp.activity.v1.ListMessageTabsRequest + 9, // 181: hyapp.activity.v1.MessageInboxService.ListInboxMessages:input_type -> hyapp.activity.v1.ListInboxMessagesRequest + 11, // 182: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:input_type -> hyapp.activity.v1.MarkInboxMessageReadRequest + 13, // 183: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:input_type -> hyapp.activity.v1.MarkInboxSectionReadRequest + 15, // 184: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:input_type -> hyapp.activity.v1.DeleteInboxMessageRequest + 17, // 185: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:input_type -> hyapp.activity.v1.CreateInboxMessageRequest + 19, // 186: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:input_type -> hyapp.activity.v1.CreateFanoutJobRequest + 21, // 187: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 188: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 189: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 190: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 21, // 191: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 25, // 192: hyapp.activity.v1.TaskService.ListUserTasks:input_type -> hyapp.activity.v1.ListUserTasksRequest + 27, // 193: hyapp.activity.v1.TaskService.ClaimTaskReward:input_type -> hyapp.activity.v1.ClaimTaskRewardRequest + 29, // 194: hyapp.activity.v1.TaskService.ConsumeTaskEvent:input_type -> hyapp.activity.v1.ConsumeTaskEventRequest + 123, // 195: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:input_type -> hyapp.activity.v1.GetMyLevelOverviewRequest + 125, // 196: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:input_type -> hyapp.activity.v1.GetLevelTrackRequest + 129, // 197: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:input_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesRequest + 132, // 198: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:input_type -> hyapp.activity.v1.ListLevelRewardsRequest + 134, // 199: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:input_type -> hyapp.activity.v1.ConsumeLevelEventRequest + 137, // 200: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:input_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesRequest + 150, // 201: hyapp.activity.v1.AchievementService.ListAchievements:input_type -> hyapp.activity.v1.ListAchievementsRequest + 152, // 202: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:input_type -> hyapp.activity.v1.ConsumeAchievementEventRequest + 155, // 203: hyapp.activity.v1.AchievementService.ListMyBadges:input_type -> hyapp.activity.v1.ListMyBadgesRequest + 157, // 204: hyapp.activity.v1.AchievementService.SetBadgeDisplay:input_type -> hyapp.activity.v1.SetBadgeDisplayRequest + 167, // 205: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:input_type -> hyapp.activity.v1.CheckLuckyGiftRequest + 170, // 206: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:input_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawRequest + 95, // 207: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusRequest + 200, // 208: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:input_type -> hyapp.activity.v1.GetWeeklyStarCurrentRequest + 196, // 209: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + 202, // 210: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:input_type -> hyapp.activity.v1.ListWeeklyStarHistoryRequest + 32, // 211: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:input_type -> hyapp.activity.v1.EnsureBroadcastGroupsRequest + 34, // 212: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:input_type -> hyapp.activity.v1.PublishRegionBroadcastRequest + 35, // 213: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:input_type -> hyapp.activity.v1.PublishGlobalBroadcastRequest + 37, // 214: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:input_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberRequest + 21, // 215: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:input_type -> hyapp.activity.v1.CronBatchRequest + 40, // 216: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:input_type -> hyapp.activity.v1.ConsumeRoomEventRequest + 43, // 217: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:input_type -> hyapp.activity.v1.ListTaskDefinitionsRequest + 45, // 218: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:input_type -> hyapp.activity.v1.UpsertTaskDefinitionRequest + 47, // 219: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:input_type -> hyapp.activity.v1.SetTaskDefinitionStatusRequest + 52, // 220: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:input_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityRequest + 54, // 221: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:input_type -> hyapp.activity.v1.IssueRegistrationRewardRequest + 56, // 222: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:input_type -> hyapp.activity.v1.GetRegistrationRewardConfigRequest + 58, // 223: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:input_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigRequest + 60, // 224: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:input_type -> hyapp.activity.v1.ListRegistrationRewardClaimsRequest + 66, // 225: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:input_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusRequest + 68, // 226: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:input_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardRequest + 70, // 227: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigRequest + 72, // 228: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigRequest + 74, // 229: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:input_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsRequest + 81, // 230: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusRequest + 83, // 231: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:input_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardRequest + 85, // 232: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigRequest + 87, // 233: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:input_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigRequest + 89, // 234: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:input_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsRequest + 97, // 235: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigRequest + 99, // 236: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:input_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigRequest + 101, // 237: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:input_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsRequest + 103, // 238: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:input_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementRequest + 188, // 239: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:input_type -> hyapp.activity.v1.ListWeeklyStarCyclesRequest + 192, // 240: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest + 190, // 241: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:input_type -> hyapp.activity.v1.GetWeeklyStarCycleRequest + 192, // 242: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:input_type -> hyapp.activity.v1.UpsertWeeklyStarCycleRequest + 194, // 243: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:input_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusRequest + 196, // 244: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:input_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardRequest + 198, // 245: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:input_type -> hyapp.activity.v1.ListWeeklyStarSettlementsRequest + 108, // 246: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:input_type -> hyapp.activity.v1.GetSevenDayCheckInStatusRequest + 110, // 247: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:input_type -> hyapp.activity.v1.SignSevenDayCheckInRequest + 112, // 248: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:input_type -> hyapp.activity.v1.GetSevenDayCheckInConfigRequest + 114, // 249: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:input_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigRequest + 117, // 250: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:input_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsRequest + 145, // 251: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:input_type -> hyapp.activity.v1.ListLevelConfigRequest + 139, // 252: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:input_type -> hyapp.activity.v1.UpsertLevelTrackRequest + 141, // 253: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:input_type -> hyapp.activity.v1.UpsertLevelRuleRequest + 143, // 254: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:input_type -> hyapp.activity.v1.UpsertLevelTierRequest + 150, // 255: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:input_type -> hyapp.activity.v1.ListAchievementsRequest + 159, // 256: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:input_type -> hyapp.activity.v1.UpsertAchievementDefinitionRequest + 172, // 257: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:input_type -> hyapp.activity.v1.GetLuckyGiftConfigRequest + 174, // 258: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:input_type -> hyapp.activity.v1.UpsertLuckyGiftConfigRequest + 176, // 259: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:input_type -> hyapp.activity.v1.ListLuckyGiftConfigsRequest + 178, // 260: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:input_type -> hyapp.activity.v1.ListLuckyGiftDrawsRequest + 181, // 261: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftDrawSummary:input_type -> hyapp.activity.v1.GetLuckyGiftDrawSummaryRequest + 2, // 262: hyapp.activity.v1.ActivityService.PingActivity:output_type -> hyapp.activity.v1.PingActivityResponse + 4, // 263: hyapp.activity.v1.ActivityService.GetActivityStatus:output_type -> hyapp.activity.v1.GetActivityStatusResponse + 7, // 264: hyapp.activity.v1.MessageInboxService.ListMessageTabs:output_type -> hyapp.activity.v1.ListMessageTabsResponse + 10, // 265: hyapp.activity.v1.MessageInboxService.ListInboxMessages:output_type -> hyapp.activity.v1.ListInboxMessagesResponse + 12, // 266: hyapp.activity.v1.MessageInboxService.MarkInboxMessageRead:output_type -> hyapp.activity.v1.MarkInboxMessageReadResponse + 14, // 267: hyapp.activity.v1.MessageInboxService.MarkInboxSectionRead:output_type -> hyapp.activity.v1.MarkInboxSectionReadResponse + 16, // 268: hyapp.activity.v1.MessageInboxService.DeleteInboxMessage:output_type -> hyapp.activity.v1.DeleteInboxMessageResponse + 18, // 269: hyapp.activity.v1.MessageInboxService.CreateInboxMessage:output_type -> hyapp.activity.v1.CreateInboxMessageResponse + 20, // 270: hyapp.activity.v1.MessageInboxService.CreateFanoutJob:output_type -> hyapp.activity.v1.CreateFanoutJobResponse + 22, // 271: hyapp.activity.v1.ActivityCronService.ProcessMessageFanoutBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 272: hyapp.activity.v1.ActivityCronService.ProcessLevelRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 273: hyapp.activity.v1.ActivityCronService.ProcessAchievementRewardBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 274: hyapp.activity.v1.ActivityCronService.ProcessRoomTurnoverRewardSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 22, // 275: hyapp.activity.v1.ActivityCronService.ProcessWeeklyStarSettlementBatch:output_type -> hyapp.activity.v1.CronBatchResponse + 26, // 276: hyapp.activity.v1.TaskService.ListUserTasks:output_type -> hyapp.activity.v1.ListUserTasksResponse + 28, // 277: hyapp.activity.v1.TaskService.ClaimTaskReward:output_type -> hyapp.activity.v1.ClaimTaskRewardResponse + 30, // 278: hyapp.activity.v1.TaskService.ConsumeTaskEvent:output_type -> hyapp.activity.v1.ConsumeTaskEventResponse + 124, // 279: hyapp.activity.v1.GrowthLevelService.GetMyLevelOverview:output_type -> hyapp.activity.v1.GetMyLevelOverviewResponse + 126, // 280: hyapp.activity.v1.GrowthLevelService.GetLevelTrack:output_type -> hyapp.activity.v1.GetLevelTrackResponse + 130, // 281: hyapp.activity.v1.GrowthLevelService.BatchGetUserLevelDisplayProfiles:output_type -> hyapp.activity.v1.BatchGetUserLevelDisplayProfilesResponse + 133, // 282: hyapp.activity.v1.GrowthLevelService.ListLevelRewards:output_type -> hyapp.activity.v1.ListLevelRewardsResponse + 135, // 283: hyapp.activity.v1.GrowthLevelService.ConsumeLevelEvent:output_type -> hyapp.activity.v1.ConsumeLevelEventResponse + 138, // 284: hyapp.activity.v1.GrowthLevelService.IssueRegistrationLevelBadges:output_type -> hyapp.activity.v1.IssueRegistrationLevelBadgesResponse + 151, // 285: hyapp.activity.v1.AchievementService.ListAchievements:output_type -> hyapp.activity.v1.ListAchievementsResponse + 153, // 286: hyapp.activity.v1.AchievementService.ConsumeAchievementEvent:output_type -> hyapp.activity.v1.ConsumeAchievementEventResponse + 156, // 287: hyapp.activity.v1.AchievementService.ListMyBadges:output_type -> hyapp.activity.v1.ListMyBadgesResponse + 158, // 288: hyapp.activity.v1.AchievementService.SetBadgeDisplay:output_type -> hyapp.activity.v1.SetBadgeDisplayResponse + 168, // 289: hyapp.activity.v1.LuckyGiftService.CheckLuckyGift:output_type -> hyapp.activity.v1.CheckLuckyGiftResponse + 171, // 290: hyapp.activity.v1.LuckyGiftService.ExecuteLuckyGiftDraw:output_type -> hyapp.activity.v1.ExecuteLuckyGiftDrawResponse + 96, // 291: hyapp.activity.v1.RoomTurnoverRewardService.GetRoomTurnoverRewardStatus:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardStatusResponse + 201, // 292: hyapp.activity.v1.WeeklyStarService.GetWeeklyStarCurrent:output_type -> hyapp.activity.v1.GetWeeklyStarCurrentResponse + 197, // 293: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + 204, // 294: hyapp.activity.v1.WeeklyStarService.ListWeeklyStarHistory:output_type -> hyapp.activity.v1.ListWeeklyStarHistoryResponse + 33, // 295: hyapp.activity.v1.BroadcastService.EnsureBroadcastGroups:output_type -> hyapp.activity.v1.EnsureBroadcastGroupsResponse + 36, // 296: hyapp.activity.v1.BroadcastService.PublishRegionBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 36, // 297: hyapp.activity.v1.BroadcastService.PublishGlobalBroadcast:output_type -> hyapp.activity.v1.PublishBroadcastResponse + 38, // 298: hyapp.activity.v1.BroadcastService.RemoveRegionBroadcastMember:output_type -> hyapp.activity.v1.RemoveRegionBroadcastMemberResponse + 39, // 299: hyapp.activity.v1.BroadcastService.ProcessBroadcastOutboxBatch:output_type -> hyapp.activity.v1.ProcessBroadcastOutboxBatchResponse + 41, // 300: hyapp.activity.v1.RoomEventConsumerService.ConsumeRoomEvent:output_type -> hyapp.activity.v1.ConsumeRoomEventResponse + 44, // 301: hyapp.activity.v1.AdminTaskService.ListTaskDefinitions:output_type -> hyapp.activity.v1.ListTaskDefinitionsResponse + 46, // 302: hyapp.activity.v1.AdminTaskService.UpsertTaskDefinition:output_type -> hyapp.activity.v1.UpsertTaskDefinitionResponse + 48, // 303: hyapp.activity.v1.AdminTaskService.SetTaskDefinitionStatus:output_type -> hyapp.activity.v1.SetTaskDefinitionStatusResponse + 53, // 304: hyapp.activity.v1.RegistrationRewardService.GetRegistrationRewardEligibility:output_type -> hyapp.activity.v1.GetRegistrationRewardEligibilityResponse + 55, // 305: hyapp.activity.v1.RegistrationRewardService.IssueRegistrationReward:output_type -> hyapp.activity.v1.IssueRegistrationRewardResponse + 57, // 306: hyapp.activity.v1.AdminRegistrationRewardService.GetRegistrationRewardConfig:output_type -> hyapp.activity.v1.GetRegistrationRewardConfigResponse + 59, // 307: hyapp.activity.v1.AdminRegistrationRewardService.UpdateRegistrationRewardConfig:output_type -> hyapp.activity.v1.UpdateRegistrationRewardConfigResponse + 61, // 308: hyapp.activity.v1.AdminRegistrationRewardService.ListRegistrationRewardClaims:output_type -> hyapp.activity.v1.ListRegistrationRewardClaimsResponse + 67, // 309: hyapp.activity.v1.FirstRechargeRewardService.GetFirstRechargeRewardStatus:output_type -> hyapp.activity.v1.GetFirstRechargeRewardStatusResponse + 69, // 310: hyapp.activity.v1.FirstRechargeRewardService.ConsumeFirstRechargeReward:output_type -> hyapp.activity.v1.ConsumeFirstRechargeRewardResponse + 71, // 311: hyapp.activity.v1.AdminFirstRechargeRewardService.GetFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.GetFirstRechargeRewardConfigResponse + 73, // 312: hyapp.activity.v1.AdminFirstRechargeRewardService.UpdateFirstRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateFirstRechargeRewardConfigResponse + 75, // 313: hyapp.activity.v1.AdminFirstRechargeRewardService.ListFirstRechargeRewardClaims:output_type -> hyapp.activity.v1.ListFirstRechargeRewardClaimsResponse + 82, // 314: hyapp.activity.v1.CumulativeRechargeRewardService.GetCumulativeRechargeRewardStatus:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardStatusResponse + 84, // 315: hyapp.activity.v1.CumulativeRechargeRewardService.ConsumeCumulativeRechargeReward:output_type -> hyapp.activity.v1.ConsumeCumulativeRechargeRewardResponse + 86, // 316: hyapp.activity.v1.AdminCumulativeRechargeRewardService.GetCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.GetCumulativeRechargeRewardConfigResponse + 88, // 317: hyapp.activity.v1.AdminCumulativeRechargeRewardService.UpdateCumulativeRechargeRewardConfig:output_type -> hyapp.activity.v1.UpdateCumulativeRechargeRewardConfigResponse + 90, // 318: hyapp.activity.v1.AdminCumulativeRechargeRewardService.ListCumulativeRechargeRewardGrants:output_type -> hyapp.activity.v1.ListCumulativeRechargeRewardGrantsResponse + 98, // 319: hyapp.activity.v1.AdminRoomTurnoverRewardService.GetRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.GetRoomTurnoverRewardConfigResponse + 100, // 320: hyapp.activity.v1.AdminRoomTurnoverRewardService.UpdateRoomTurnoverRewardConfig:output_type -> hyapp.activity.v1.UpdateRoomTurnoverRewardConfigResponse + 102, // 321: hyapp.activity.v1.AdminRoomTurnoverRewardService.ListRoomTurnoverRewardSettlements:output_type -> hyapp.activity.v1.ListRoomTurnoverRewardSettlementsResponse + 104, // 322: hyapp.activity.v1.AdminRoomTurnoverRewardService.RetryRoomTurnoverRewardSettlement:output_type -> hyapp.activity.v1.RetryRoomTurnoverRewardSettlementResponse + 189, // 323: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarCycles:output_type -> hyapp.activity.v1.ListWeeklyStarCyclesResponse + 193, // 324: hyapp.activity.v1.AdminWeeklyStarService.CreateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse + 191, // 325: hyapp.activity.v1.AdminWeeklyStarService.GetWeeklyStarCycle:output_type -> hyapp.activity.v1.GetWeeklyStarCycleResponse + 193, // 326: hyapp.activity.v1.AdminWeeklyStarService.UpdateWeeklyStarCycle:output_type -> hyapp.activity.v1.UpsertWeeklyStarCycleResponse + 195, // 327: hyapp.activity.v1.AdminWeeklyStarService.SetWeeklyStarCycleStatus:output_type -> hyapp.activity.v1.SetWeeklyStarCycleStatusResponse + 197, // 328: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarLeaderboard:output_type -> hyapp.activity.v1.ListWeeklyStarLeaderboardResponse + 199, // 329: hyapp.activity.v1.AdminWeeklyStarService.ListWeeklyStarSettlements:output_type -> hyapp.activity.v1.ListWeeklyStarSettlementsResponse + 109, // 330: hyapp.activity.v1.SevenDayCheckInService.GetSevenDayCheckInStatus:output_type -> hyapp.activity.v1.GetSevenDayCheckInStatusResponse + 111, // 331: hyapp.activity.v1.SevenDayCheckInService.SignSevenDayCheckIn:output_type -> hyapp.activity.v1.SignSevenDayCheckInResponse + 113, // 332: hyapp.activity.v1.AdminSevenDayCheckInService.GetSevenDayCheckInConfig:output_type -> hyapp.activity.v1.GetSevenDayCheckInConfigResponse + 115, // 333: hyapp.activity.v1.AdminSevenDayCheckInService.UpdateSevenDayCheckInConfig:output_type -> hyapp.activity.v1.UpdateSevenDayCheckInConfigResponse + 118, // 334: hyapp.activity.v1.AdminSevenDayCheckInService.ListSevenDayCheckInClaims:output_type -> hyapp.activity.v1.ListSevenDayCheckInClaimsResponse + 146, // 335: hyapp.activity.v1.AdminGrowthLevelService.ListLevelConfig:output_type -> hyapp.activity.v1.ListLevelConfigResponse + 140, // 336: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTrack:output_type -> hyapp.activity.v1.UpsertLevelTrackResponse + 142, // 337: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelRule:output_type -> hyapp.activity.v1.UpsertLevelRuleResponse + 144, // 338: hyapp.activity.v1.AdminGrowthLevelService.UpsertLevelTier:output_type -> hyapp.activity.v1.UpsertLevelTierResponse + 151, // 339: hyapp.activity.v1.AdminAchievementService.ListAchievementDefinitions:output_type -> hyapp.activity.v1.ListAchievementsResponse + 160, // 340: hyapp.activity.v1.AdminAchievementService.UpsertAchievementDefinition:output_type -> hyapp.activity.v1.UpsertAchievementDefinitionResponse + 173, // 341: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftConfig:output_type -> hyapp.activity.v1.GetLuckyGiftConfigResponse + 175, // 342: hyapp.activity.v1.AdminLuckyGiftService.UpsertLuckyGiftConfig:output_type -> hyapp.activity.v1.UpsertLuckyGiftConfigResponse + 177, // 343: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftConfigs:output_type -> hyapp.activity.v1.ListLuckyGiftConfigsResponse + 179, // 344: hyapp.activity.v1.AdminLuckyGiftService.ListLuckyGiftDraws:output_type -> hyapp.activity.v1.ListLuckyGiftDrawsResponse + 182, // 345: hyapp.activity.v1.AdminLuckyGiftService.GetLuckyGiftDrawSummary:output_type -> hyapp.activity.v1.GetLuckyGiftDrawSummaryResponse + 262, // [262:346] is the sub-list for method output_type + 178, // [178:262] is the sub-list for method input_type + 178, // [178:178] is the sub-list for extension type_name + 178, // [178:178] is the sub-list for extension extendee + 0, // [0:178] is the sub-list for field type_name } func init() { file_proto_activity_v1_activity_proto_init() } @@ -14209,9 +18465,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: 154, + NumMessages: 205, NumExtensions: 0, - NumServices: 19, + NumServices: 25, }, 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 50d6e5c3..a0990557 100644 --- a/api/proto/activity/v1/activity.proto +++ b/api/proto/activity/v1/activity.proto @@ -524,11 +524,14 @@ message ListRegistrationRewardClaimsRequest { int64 user_id = 3; int32 page = 4; int32 page_size = 5; + int64 claimed_start_ms = 6; + int64 claimed_end_ms = 7; } message ListRegistrationRewardClaimsResponse { repeated RegistrationRewardClaim claims = 1; int64 total = 2; + int64 today_claimed_count = 3; } // FirstRechargeRewardTier 是首冲奖励的一个金币充值档位;max_coin_amount=0 表示无上限。 @@ -647,6 +650,255 @@ message ListFirstRechargeRewardClaimsResponse { int64 total = 2; } +// CumulativeRechargeRewardTier 是累充奖励的单个 USD 档位;threshold_usd_minor 以美分存储。 +message CumulativeRechargeRewardTier { + int64 tier_id = 1; + string tier_code = 2; + string tier_name = 3; + int64 threshold_usd_minor = 4; + int64 resource_group_id = 5; + string status = 6; + int32 sort_order = 7; + int64 created_at_ms = 8; + int64 updated_at_ms = 9; +} + +// CumulativeRechargeRewardConfig 是当前 App 的累充奖励配置。 +message CumulativeRechargeRewardConfig { + string app_code = 1; + bool enabled = 2; + repeated CumulativeRechargeRewardTier tiers = 3; + int64 updated_by_admin_id = 4; + int64 created_at_ms = 5; + int64 updated_at_ms = 6; +} + +// CumulativeRechargeRewardGrant 是用户在一个 UTC 自然周内达成某个档位后的发放事实。 +message CumulativeRechargeRewardGrant { + string grant_id = 1; + string app_code = 2; + string cycle_key = 3; + int64 user_id = 4; + string event_id = 5; + string transaction_id = 6; + string command_id = 7; + int64 tier_id = 8; + string tier_code = 9; + int64 threshold_usd_minor = 10; + int64 resource_group_id = 11; + int64 reached_usd_minor = 12; + int64 qualifying_usd_minor = 13; + int64 recharge_coin_amount = 14; + string recharge_type = 15; + string status = 16; + string wallet_command_id = 17; + string wallet_grant_id = 18; + string failure_reason = 19; + int64 granted_at_ms = 20; + int64 created_at_ms = 21; + int64 updated_at_ms = 22; +} + +// CumulativeRechargeRewardProgress 是用户在当前 UTC 周期内的累充累计投影。 +message CumulativeRechargeRewardProgress { + string app_code = 1; + string cycle_key = 2; + int64 user_id = 3; + int64 total_usd_minor = 4; + int64 total_coin_amount = 5; + int64 first_recharged_at_ms = 6; + int64 last_recharged_at_ms = 7; + int64 updated_at_ms = 8; +} + +// CumulativeRechargeRewardStatus 是 App 累充奖励 H5 可直接展示的当前状态。 +message CumulativeRechargeRewardStatus { + CumulativeRechargeRewardConfig config = 1; + CumulativeRechargeRewardProgress progress = 2; + repeated CumulativeRechargeRewardGrant grants = 3; + string cycle_key = 4; + int64 period_start_ms = 5; + int64 period_end_ms = 6; + int64 server_time_ms = 7; +} + +message GetCumulativeRechargeRewardStatusRequest { + RequestMeta meta = 1; + int64 user_id = 2; +} + +message GetCumulativeRechargeRewardStatusResponse { + CumulativeRechargeRewardStatus status = 1; +} + +// ConsumeCumulativeRechargeRewardRequest 是 wallet 充值事实消费入口;所有成功充值都会按 UTC 周期累计。 +message ConsumeCumulativeRechargeRewardRequest { + 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 qualifying_usd_minor = 9; + string payload_json = 10; + int64 occurred_at_ms = 11; +} + +message ConsumeCumulativeRechargeRewardResponse { + repeated CumulativeRechargeRewardGrant grants = 1; + bool consumed = 2; + string reason = 3; +} + +message GetCumulativeRechargeRewardConfigRequest { + RequestMeta meta = 1; +} + +message GetCumulativeRechargeRewardConfigResponse { + CumulativeRechargeRewardConfig config = 1; +} + +message UpdateCumulativeRechargeRewardConfigRequest { + RequestMeta meta = 1; + bool enabled = 2; + repeated CumulativeRechargeRewardTier tiers = 3; + int64 operator_admin_id = 4; +} + +message UpdateCumulativeRechargeRewardConfigResponse { + CumulativeRechargeRewardConfig config = 1; +} + +message ListCumulativeRechargeRewardGrantsRequest { + RequestMeta meta = 1; + string status = 2; + int64 user_id = 3; + string cycle_key = 4; + int32 page = 5; + int32 page_size = 6; +} + +message ListCumulativeRechargeRewardGrantsResponse { + repeated CumulativeRechargeRewardGrant grants = 1; + int64 total = 2; +} + +// RoomTurnoverRewardTier 是房间流水奖励的单个档位;达到 threshold_coin_spent 后可命中奖励。 +message RoomTurnoverRewardTier { + int64 tier_id = 1; + string tier_code = 2; + string tier_name = 3; + int64 threshold_coin_spent = 4; + int64 reward_coin_amount = 5; + string status = 6; + int32 sort_order = 7; + int64 created_at_ms = 8; + int64 updated_at_ms = 9; +} + +// RoomTurnoverRewardConfig 是当前 App 的房间流水奖励配置;结算只命中最高有效档。 +message RoomTurnoverRewardConfig { + string app_code = 1; + bool enabled = 2; + repeated RoomTurnoverRewardTier tiers = 3; + int64 updated_by_admin_id = 4; + int64 created_at_ms = 5; + int64 updated_at_ms = 6; +} + +// RoomTurnoverRewardSettlement 是某个房间单个 UTC 周期的结算事实。 +message RoomTurnoverRewardSettlement { + string settlement_id = 1; + string app_code = 2; + string room_id = 3; + int64 owner_user_id = 4; + int64 period_start_ms = 5; + int64 period_end_ms = 6; + int64 coin_spent = 7; + int64 tier_id = 8; + string tier_code = 9; + int64 threshold_coin_spent = 10; + int64 reward_coin_amount = 11; + string status = 12; + string wallet_command_id = 13; + string wallet_transaction_id = 14; + string failure_reason = 15; + int64 settled_at_ms = 16; + int64 created_at_ms = 17; + int64 updated_at_ms = 18; +} + +// RoomTurnoverRewardStatus 给 App H5 返回当前 UTC 周期、房间流水、预计奖励和上一期结算。 +message RoomTurnoverRewardStatus { + RoomTurnoverRewardConfig config = 1; + string room_id = 2; + int64 owner_user_id = 3; + int64 period_start_ms = 4; + int64 period_end_ms = 5; + int64 current_coin_spent = 6; + int64 expected_reward_coin_amount = 7; + RoomTurnoverRewardTier matched_tier = 8; + RoomTurnoverRewardSettlement latest_settlement = 9; + int64 server_time_ms = 10; +} + +message GetRoomTurnoverRewardStatusRequest { + RequestMeta meta = 1; + int64 user_id = 2; + string room_id = 3; + int64 owner_user_id = 4; +} + +message GetRoomTurnoverRewardStatusResponse { + RoomTurnoverRewardStatus status = 1; +} + +message GetRoomTurnoverRewardConfigRequest { + RequestMeta meta = 1; +} + +message GetRoomTurnoverRewardConfigResponse { + RoomTurnoverRewardConfig config = 1; +} + +message UpdateRoomTurnoverRewardConfigRequest { + RequestMeta meta = 1; + bool enabled = 2; + repeated RoomTurnoverRewardTier tiers = 3; + int64 operator_admin_id = 4; +} + +message UpdateRoomTurnoverRewardConfigResponse { + RoomTurnoverRewardConfig config = 1; +} + +message ListRoomTurnoverRewardSettlementsRequest { + RequestMeta meta = 1; + string status = 2; + string room_id = 3; + int64 owner_user_id = 4; + int64 period_start_ms = 5; + int32 page = 6; + int32 page_size = 7; +} + +message ListRoomTurnoverRewardSettlementsResponse { + repeated RoomTurnoverRewardSettlement settlements = 1; + int64 total = 2; +} + +message RetryRoomTurnoverRewardSettlementRequest { + RequestMeta meta = 1; + string settlement_id = 2; + int64 operator_admin_id = 3; +} + +message RetryRoomTurnoverRewardSettlementResponse { + RoomTurnoverRewardSettlement settlement = 1; +} + // SevenDayCheckInReward 是七日签到配置中某一天的资源组奖励。 message SevenDayCheckInReward { int32 day_index = 1; @@ -1396,6 +1648,162 @@ message GetLuckyGiftDrawSummaryResponse { LuckyGiftDrawSummary summary = 1; } +// WeeklyStarGift 是周星周期内参与积分的指定礼物。 +message WeeklyStarGift { + string gift_id = 1; + int32 sort_order = 2; +} + +// WeeklyStarReward 是周星 Top 排名对应的资源组奖励。 +message WeeklyStarReward { + int32 rank_no = 1; + int64 resource_group_id = 2; +} + +// WeeklyStarCycle 是一个按 UTC epoch ms 生效的周星配置周期。 +message WeeklyStarCycle { + string cycle_id = 1; + string activity_code = 2; + int64 region_id = 3; + string title = 4; + string status = 5; + int64 start_ms = 6; + int64 end_ms = 7; + repeated WeeklyStarGift gifts = 8; + repeated WeeklyStarReward rewards = 9; + int64 created_by_admin_id = 10; + int64 updated_by_admin_id = 11; + int64 settled_at_ms = 12; + int64 created_at_ms = 13; + int64 updated_at_ms = 14; + string app_code = 15; +} + +// WeeklyStarLeaderboardEntry 是一个周期内用户维度的积分排名。 +message WeeklyStarLeaderboardEntry { + int32 rank_no = 1; + int64 user_id = 2; + int64 score = 3; + int64 first_scored_at_ms = 4; + int64 last_scored_at_ms = 5; +} + +// WeeklyStarSettlement 是周期结束后 Top 奖励发放的幂等记录。 +message WeeklyStarSettlement { + string settlement_id = 1; + string cycle_id = 2; + int32 rank_no = 3; + int64 user_id = 4; + int64 score = 5; + int64 resource_group_id = 6; + string wallet_command_id = 7; + string wallet_grant_id = 8; + string status = 9; + string failure_reason = 10; + int32 attempt_count = 11; + int64 created_at_ms = 12; + int64 updated_at_ms = 13; +} + +message ListWeeklyStarCyclesRequest { + RequestMeta meta = 1; + int64 region_id = 2; + string status = 3; + int64 start_ms = 4; + int64 end_ms = 5; + int32 page = 6; + int32 page_size = 7; +} + +message ListWeeklyStarCyclesResponse { + repeated WeeklyStarCycle cycles = 1; + int64 total = 2; +} + +message GetWeeklyStarCycleRequest { + RequestMeta meta = 1; + string cycle_id = 2; +} + +message GetWeeklyStarCycleResponse { + WeeklyStarCycle cycle = 1; +} + +message UpsertWeeklyStarCycleRequest { + RequestMeta meta = 1; + WeeklyStarCycle cycle = 2; + int64 operator_admin_id = 3; +} + +message UpsertWeeklyStarCycleResponse { + WeeklyStarCycle cycle = 1; + bool created = 2; +} + +message SetWeeklyStarCycleStatusRequest { + RequestMeta meta = 1; + string cycle_id = 2; + string status = 3; + int64 operator_admin_id = 4; +} + +message SetWeeklyStarCycleStatusResponse { + WeeklyStarCycle cycle = 1; +} + +message ListWeeklyStarLeaderboardRequest { + RequestMeta meta = 1; + string cycle_id = 2; + int64 region_id = 3; + int32 page_size = 4; + string page_token = 5; +} + +message ListWeeklyStarLeaderboardResponse { + WeeklyStarCycle cycle = 1; + repeated WeeklyStarLeaderboardEntry entries = 2; + string next_page_token = 3; + int64 total = 4; +} + +message ListWeeklyStarSettlementsRequest { + RequestMeta meta = 1; + string cycle_id = 2; +} + +message ListWeeklyStarSettlementsResponse { + repeated WeeklyStarSettlement settlements = 1; +} + +message GetWeeklyStarCurrentRequest { + RequestMeta meta = 1; + int64 user_id = 2; + int64 region_id = 3; +} + +message GetWeeklyStarCurrentResponse { + WeeklyStarCycle cycle = 1; + repeated WeeklyStarLeaderboardEntry top_entries = 2; + WeeklyStarLeaderboardEntry my_entry = 3; + int64 server_time_ms = 4; +} + +message ListWeeklyStarHistoryRequest { + RequestMeta meta = 1; + int64 region_id = 2; + int32 limit = 3; +} + +message WeeklyStarHistoryCycle { + WeeklyStarCycle cycle = 1; + repeated WeeklyStarLeaderboardEntry top_entries = 2; +} + +message ListWeeklyStarHistoryResponse { + repeated WeeklyStarHistoryCycle cycles = 1; + int64 server_time_ms = 2; +} + // ActivityService 只暴露同步查询,不把事件消费伪装成 RPC。 service ActivityService { rpc PingActivity(PingActivityRequest) returns (PingActivityResponse); @@ -1418,6 +1826,8 @@ service ActivityCronService { rpc ProcessMessageFanoutBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessLevelRewardBatch(CronBatchRequest) returns (CronBatchResponse); rpc ProcessAchievementRewardBatch(CronBatchRequest) returns (CronBatchResponse); + rpc ProcessRoomTurnoverRewardSettlementBatch(CronBatchRequest) returns (CronBatchResponse); + rpc ProcessWeeklyStarSettlementBatch(CronBatchRequest) returns (CronBatchResponse); } // TaskService 拥有 App 任务查询、事件进度消费和领奖状态。 @@ -1451,6 +1861,18 @@ service LuckyGiftService { rpc ExecuteLuckyGiftDraw(ExecuteLuckyGiftDrawRequest) returns (ExecuteLuckyGiftDrawResponse); } +// RoomTurnoverRewardService owns App reads for the weekly room turnover reward activity. +service RoomTurnoverRewardService { + rpc GetRoomTurnoverRewardStatus(GetRoomTurnoverRewardStatusRequest) returns (GetRoomTurnoverRewardStatusResponse); +} + +// WeeklyStarService owns App reads for the weekly specified-gift score activity. +service WeeklyStarService { + rpc GetWeeklyStarCurrent(GetWeeklyStarCurrentRequest) returns (GetWeeklyStarCurrentResponse); + rpc ListWeeklyStarLeaderboard(ListWeeklyStarLeaderboardRequest) returns (ListWeeklyStarLeaderboardResponse); + rpc ListWeeklyStarHistory(ListWeeklyStarHistoryRequest) returns (ListWeeklyStarHistoryResponse); +} + // BroadcastService owns server-side Tencent IM global/region broadcast delivery. service BroadcastService { rpc EnsureBroadcastGroups(EnsureBroadcastGroupsRequest) returns (EnsureBroadcastGroupsResponse); @@ -1498,6 +1920,38 @@ service AdminFirstRechargeRewardService { rpc ListFirstRechargeRewardClaims(ListFirstRechargeRewardClaimsRequest) returns (ListFirstRechargeRewardClaimsResponse); } +// CumulativeRechargeRewardService 拥有 App 累充奖励查询和 wallet 充值事实消费入口。 +service CumulativeRechargeRewardService { + rpc GetCumulativeRechargeRewardStatus(GetCumulativeRechargeRewardStatusRequest) returns (GetCumulativeRechargeRewardStatusResponse); + rpc ConsumeCumulativeRechargeReward(ConsumeCumulativeRechargeRewardRequest) returns (ConsumeCumulativeRechargeRewardResponse); +} + +// AdminCumulativeRechargeRewardService 是后台活动管理访问累充奖励配置和发放记录的唯一入口。 +service AdminCumulativeRechargeRewardService { + rpc GetCumulativeRechargeRewardConfig(GetCumulativeRechargeRewardConfigRequest) returns (GetCumulativeRechargeRewardConfigResponse); + rpc UpdateCumulativeRechargeRewardConfig(UpdateCumulativeRechargeRewardConfigRequest) returns (UpdateCumulativeRechargeRewardConfigResponse); + rpc ListCumulativeRechargeRewardGrants(ListCumulativeRechargeRewardGrantsRequest) returns (ListCumulativeRechargeRewardGrantsResponse); +} + +// AdminRoomTurnoverRewardService 是后台活动管理访问房间流水奖励配置和结算记录的唯一入口。 +service AdminRoomTurnoverRewardService { + rpc GetRoomTurnoverRewardConfig(GetRoomTurnoverRewardConfigRequest) returns (GetRoomTurnoverRewardConfigResponse); + rpc UpdateRoomTurnoverRewardConfig(UpdateRoomTurnoverRewardConfigRequest) returns (UpdateRoomTurnoverRewardConfigResponse); + rpc ListRoomTurnoverRewardSettlements(ListRoomTurnoverRewardSettlementsRequest) returns (ListRoomTurnoverRewardSettlementsResponse); + rpc RetryRoomTurnoverRewardSettlement(RetryRoomTurnoverRewardSettlementRequest) returns (RetryRoomTurnoverRewardSettlementResponse); +} + +// AdminWeeklyStarService 是后台活动管理访问周星周期、榜单和结算结果的唯一入口。 +service AdminWeeklyStarService { + rpc ListWeeklyStarCycles(ListWeeklyStarCyclesRequest) returns (ListWeeklyStarCyclesResponse); + rpc CreateWeeklyStarCycle(UpsertWeeklyStarCycleRequest) returns (UpsertWeeklyStarCycleResponse); + rpc GetWeeklyStarCycle(GetWeeklyStarCycleRequest) returns (GetWeeklyStarCycleResponse); + rpc UpdateWeeklyStarCycle(UpsertWeeklyStarCycleRequest) returns (UpsertWeeklyStarCycleResponse); + rpc SetWeeklyStarCycleStatus(SetWeeklyStarCycleStatusRequest) returns (SetWeeklyStarCycleStatusResponse); + rpc ListWeeklyStarLeaderboard(ListWeeklyStarLeaderboardRequest) returns (ListWeeklyStarLeaderboardResponse); + rpc ListWeeklyStarSettlements(ListWeeklyStarSettlementsRequest) returns (ListWeeklyStarSettlementsResponse); +} + // 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 d19e7524..34cbe40a 100644 --- a/api/proto/activity/v1/activity_grpc.pb.go +++ b/api/proto/activity/v1/activity_grpc.pb.go @@ -497,9 +497,11 @@ var MessageInboxService_ServiceDesc = grpc.ServiceDesc{ } const ( - ActivityCronService_ProcessMessageFanoutBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessMessageFanoutBatch" - ActivityCronService_ProcessLevelRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessLevelRewardBatch" - ActivityCronService_ProcessAchievementRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessAchievementRewardBatch" + ActivityCronService_ProcessMessageFanoutBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessMessageFanoutBatch" + ActivityCronService_ProcessLevelRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessLevelRewardBatch" + ActivityCronService_ProcessAchievementRewardBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessAchievementRewardBatch" + ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessRoomTurnoverRewardSettlementBatch" + ActivityCronService_ProcessWeeklyStarSettlementBatch_FullMethodName = "/hyapp.activity.v1.ActivityCronService/ProcessWeeklyStarSettlementBatch" ) // ActivityCronServiceClient is the client API for ActivityCronService service. @@ -511,6 +513,8 @@ type ActivityCronServiceClient interface { ProcessMessageFanoutBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessLevelRewardBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) ProcessAchievementRewardBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) + ProcessWeeklyStarSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) } type activityCronServiceClient struct { @@ -551,6 +555,26 @@ func (c *activityCronServiceClient) ProcessAchievementRewardBatch(ctx context.Co return out, nil } +func (c *activityCronServiceClient) ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CronBatchResponse) + err := c.cc.Invoke(ctx, ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *activityCronServiceClient) ProcessWeeklyStarSettlementBatch(ctx context.Context, in *CronBatchRequest, opts ...grpc.CallOption) (*CronBatchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CronBatchResponse) + err := c.cc.Invoke(ctx, ActivityCronService_ProcessWeeklyStarSettlementBatch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // ActivityCronServiceServer is the server API for ActivityCronService service. // All implementations must embed UnimplementedActivityCronServiceServer // for forward compatibility. @@ -560,6 +584,8 @@ type ActivityCronServiceServer interface { ProcessMessageFanoutBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessLevelRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) ProcessAchievementRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + ProcessRoomTurnoverRewardSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) + ProcessWeeklyStarSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) mustEmbedUnimplementedActivityCronServiceServer() } @@ -579,6 +605,12 @@ func (UnimplementedActivityCronServiceServer) ProcessLevelRewardBatch(context.Co func (UnimplementedActivityCronServiceServer) ProcessAchievementRewardBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { return nil, status.Error(codes.Unimplemented, "method ProcessAchievementRewardBatch not implemented") } +func (UnimplementedActivityCronServiceServer) ProcessRoomTurnoverRewardSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ProcessRoomTurnoverRewardSettlementBatch not implemented") +} +func (UnimplementedActivityCronServiceServer) ProcessWeeklyStarSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ProcessWeeklyStarSettlementBatch not implemented") +} func (UnimplementedActivityCronServiceServer) mustEmbedUnimplementedActivityCronServiceServer() {} func (UnimplementedActivityCronServiceServer) testEmbeddedByValue() {} @@ -654,6 +686,42 @@ func _ActivityCronService_ProcessAchievementRewardBatch_Handler(srv interface{}, return interceptor(ctx, in, info, handler) } +func _ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CronBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ActivityCronServiceServer).ProcessRoomTurnoverRewardSettlementBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ActivityCronServiceServer).ProcessRoomTurnoverRewardSettlementBatch(ctx, req.(*CronBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ActivityCronService_ProcessWeeklyStarSettlementBatch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CronBatchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ActivityCronServiceServer).ProcessWeeklyStarSettlementBatch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ActivityCronService_ProcessWeeklyStarSettlementBatch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ActivityCronServiceServer).ProcessWeeklyStarSettlementBatch(ctx, req.(*CronBatchRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ActivityCronService_ServiceDesc is the grpc.ServiceDesc for ActivityCronService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -673,6 +741,14 @@ var ActivityCronService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ProcessAchievementRewardBatch", Handler: _ActivityCronService_ProcessAchievementRewardBatch_Handler, }, + { + MethodName: "ProcessRoomTurnoverRewardSettlementBatch", + Handler: _ActivityCronService_ProcessRoomTurnoverRewardSettlementBatch_Handler, + }, + { + MethodName: "ProcessWeeklyStarSettlementBatch", + Handler: _ActivityCronService_ProcessWeeklyStarSettlementBatch_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "proto/activity/v1/activity.proto", @@ -1520,6 +1596,295 @@ var LuckyGiftService_ServiceDesc = grpc.ServiceDesc{ Metadata: "proto/activity/v1/activity.proto", } +const ( + RoomTurnoverRewardService_GetRoomTurnoverRewardStatus_FullMethodName = "/hyapp.activity.v1.RoomTurnoverRewardService/GetRoomTurnoverRewardStatus" +) + +// RoomTurnoverRewardServiceClient is the client API for RoomTurnoverRewardService 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. +// +// RoomTurnoverRewardService owns App reads for the weekly room turnover reward activity. +type RoomTurnoverRewardServiceClient interface { + GetRoomTurnoverRewardStatus(ctx context.Context, in *GetRoomTurnoverRewardStatusRequest, opts ...grpc.CallOption) (*GetRoomTurnoverRewardStatusResponse, error) +} + +type roomTurnoverRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewRoomTurnoverRewardServiceClient(cc grpc.ClientConnInterface) RoomTurnoverRewardServiceClient { + return &roomTurnoverRewardServiceClient{cc} +} + +func (c *roomTurnoverRewardServiceClient) GetRoomTurnoverRewardStatus(ctx context.Context, in *GetRoomTurnoverRewardStatusRequest, opts ...grpc.CallOption) (*GetRoomTurnoverRewardStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetRoomTurnoverRewardStatusResponse) + err := c.cc.Invoke(ctx, RoomTurnoverRewardService_GetRoomTurnoverRewardStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// RoomTurnoverRewardServiceServer is the server API for RoomTurnoverRewardService service. +// All implementations must embed UnimplementedRoomTurnoverRewardServiceServer +// for forward compatibility. +// +// RoomTurnoverRewardService owns App reads for the weekly room turnover reward activity. +type RoomTurnoverRewardServiceServer interface { + GetRoomTurnoverRewardStatus(context.Context, *GetRoomTurnoverRewardStatusRequest) (*GetRoomTurnoverRewardStatusResponse, error) + mustEmbedUnimplementedRoomTurnoverRewardServiceServer() +} + +// UnimplementedRoomTurnoverRewardServiceServer 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 UnimplementedRoomTurnoverRewardServiceServer struct{} + +func (UnimplementedRoomTurnoverRewardServiceServer) GetRoomTurnoverRewardStatus(context.Context, *GetRoomTurnoverRewardStatusRequest) (*GetRoomTurnoverRewardStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetRoomTurnoverRewardStatus not implemented") +} +func (UnimplementedRoomTurnoverRewardServiceServer) mustEmbedUnimplementedRoomTurnoverRewardServiceServer() { +} +func (UnimplementedRoomTurnoverRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeRoomTurnoverRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to RoomTurnoverRewardServiceServer will +// result in compilation errors. +type UnsafeRoomTurnoverRewardServiceServer interface { + mustEmbedUnimplementedRoomTurnoverRewardServiceServer() +} + +func RegisterRoomTurnoverRewardServiceServer(s grpc.ServiceRegistrar, srv RoomTurnoverRewardServiceServer) { + // If the following call panics, it indicates UnimplementedRoomTurnoverRewardServiceServer 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(&RoomTurnoverRewardService_ServiceDesc, srv) +} + +func _RoomTurnoverRewardService_GetRoomTurnoverRewardStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRoomTurnoverRewardStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(RoomTurnoverRewardServiceServer).GetRoomTurnoverRewardStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: RoomTurnoverRewardService_GetRoomTurnoverRewardStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(RoomTurnoverRewardServiceServer).GetRoomTurnoverRewardStatus(ctx, req.(*GetRoomTurnoverRewardStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// RoomTurnoverRewardService_ServiceDesc is the grpc.ServiceDesc for RoomTurnoverRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var RoomTurnoverRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.RoomTurnoverRewardService", + HandlerType: (*RoomTurnoverRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetRoomTurnoverRewardStatus", + Handler: _RoomTurnoverRewardService_GetRoomTurnoverRewardStatus_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + +const ( + WeeklyStarService_GetWeeklyStarCurrent_FullMethodName = "/hyapp.activity.v1.WeeklyStarService/GetWeeklyStarCurrent" + WeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName = "/hyapp.activity.v1.WeeklyStarService/ListWeeklyStarLeaderboard" + WeeklyStarService_ListWeeklyStarHistory_FullMethodName = "/hyapp.activity.v1.WeeklyStarService/ListWeeklyStarHistory" +) + +// WeeklyStarServiceClient is the client API for WeeklyStarService 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. +// +// WeeklyStarService owns App reads for the weekly specified-gift score activity. +type WeeklyStarServiceClient interface { + GetWeeklyStarCurrent(ctx context.Context, in *GetWeeklyStarCurrentRequest, opts ...grpc.CallOption) (*GetWeeklyStarCurrentResponse, error) + ListWeeklyStarLeaderboard(ctx context.Context, in *ListWeeklyStarLeaderboardRequest, opts ...grpc.CallOption) (*ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarHistory(ctx context.Context, in *ListWeeklyStarHistoryRequest, opts ...grpc.CallOption) (*ListWeeklyStarHistoryResponse, error) +} + +type weeklyStarServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewWeeklyStarServiceClient(cc grpc.ClientConnInterface) WeeklyStarServiceClient { + return &weeklyStarServiceClient{cc} +} + +func (c *weeklyStarServiceClient) GetWeeklyStarCurrent(ctx context.Context, in *GetWeeklyStarCurrentRequest, opts ...grpc.CallOption) (*GetWeeklyStarCurrentResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetWeeklyStarCurrentResponse) + err := c.cc.Invoke(ctx, WeeklyStarService_GetWeeklyStarCurrent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *weeklyStarServiceClient) ListWeeklyStarLeaderboard(ctx context.Context, in *ListWeeklyStarLeaderboardRequest, opts ...grpc.CallOption) (*ListWeeklyStarLeaderboardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWeeklyStarLeaderboardResponse) + err := c.cc.Invoke(ctx, WeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *weeklyStarServiceClient) ListWeeklyStarHistory(ctx context.Context, in *ListWeeklyStarHistoryRequest, opts ...grpc.CallOption) (*ListWeeklyStarHistoryResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWeeklyStarHistoryResponse) + err := c.cc.Invoke(ctx, WeeklyStarService_ListWeeklyStarHistory_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// WeeklyStarServiceServer is the server API for WeeklyStarService service. +// All implementations must embed UnimplementedWeeklyStarServiceServer +// for forward compatibility. +// +// WeeklyStarService owns App reads for the weekly specified-gift score activity. +type WeeklyStarServiceServer interface { + GetWeeklyStarCurrent(context.Context, *GetWeeklyStarCurrentRequest) (*GetWeeklyStarCurrentResponse, error) + ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarHistory(context.Context, *ListWeeklyStarHistoryRequest) (*ListWeeklyStarHistoryResponse, error) + mustEmbedUnimplementedWeeklyStarServiceServer() +} + +// UnimplementedWeeklyStarServiceServer 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 UnimplementedWeeklyStarServiceServer struct{} + +func (UnimplementedWeeklyStarServiceServer) GetWeeklyStarCurrent(context.Context, *GetWeeklyStarCurrentRequest) (*GetWeeklyStarCurrentResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetWeeklyStarCurrent not implemented") +} +func (UnimplementedWeeklyStarServiceServer) ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented") +} +func (UnimplementedWeeklyStarServiceServer) ListWeeklyStarHistory(context.Context, *ListWeeklyStarHistoryRequest) (*ListWeeklyStarHistoryResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarHistory not implemented") +} +func (UnimplementedWeeklyStarServiceServer) mustEmbedUnimplementedWeeklyStarServiceServer() {} +func (UnimplementedWeeklyStarServiceServer) testEmbeddedByValue() {} + +// UnsafeWeeklyStarServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to WeeklyStarServiceServer will +// result in compilation errors. +type UnsafeWeeklyStarServiceServer interface { + mustEmbedUnimplementedWeeklyStarServiceServer() +} + +func RegisterWeeklyStarServiceServer(s grpc.ServiceRegistrar, srv WeeklyStarServiceServer) { + // If the following call panics, it indicates UnimplementedWeeklyStarServiceServer 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(&WeeklyStarService_ServiceDesc, srv) +} + +func _WeeklyStarService_GetWeeklyStarCurrent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetWeeklyStarCurrentRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WeeklyStarServiceServer).GetWeeklyStarCurrent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WeeklyStarService_GetWeeklyStarCurrent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WeeklyStarServiceServer).GetWeeklyStarCurrent(ctx, req.(*GetWeeklyStarCurrentRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WeeklyStarService_ListWeeklyStarLeaderboard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWeeklyStarLeaderboardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WeeklyStarServiceServer).ListWeeklyStarLeaderboard(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WeeklyStarServiceServer).ListWeeklyStarLeaderboard(ctx, req.(*ListWeeklyStarLeaderboardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WeeklyStarService_ListWeeklyStarHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWeeklyStarHistoryRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WeeklyStarServiceServer).ListWeeklyStarHistory(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WeeklyStarService_ListWeeklyStarHistory_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WeeklyStarServiceServer).ListWeeklyStarHistory(ctx, req.(*ListWeeklyStarHistoryRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// WeeklyStarService_ServiceDesc is the grpc.ServiceDesc for WeeklyStarService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var WeeklyStarService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.WeeklyStarService", + HandlerType: (*WeeklyStarServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetWeeklyStarCurrent", + Handler: _WeeklyStarService_GetWeeklyStarCurrent_Handler, + }, + { + MethodName: "ListWeeklyStarLeaderboard", + Handler: _WeeklyStarService_ListWeeklyStarLeaderboard_Handler, + }, + { + MethodName: "ListWeeklyStarHistory", + Handler: _WeeklyStarService_ListWeeklyStarHistory_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + const ( BroadcastService_EnsureBroadcastGroups_FullMethodName = "/hyapp.activity.v1.BroadcastService/EnsureBroadcastGroups" BroadcastService_PublishRegionBroadcast_FullMethodName = "/hyapp.activity.v1.BroadcastService/PublishRegionBroadcast" @@ -2723,6 +3088,890 @@ var AdminFirstRechargeRewardService_ServiceDesc = grpc.ServiceDesc{ Metadata: "proto/activity/v1/activity.proto", } +const ( + CumulativeRechargeRewardService_GetCumulativeRechargeRewardStatus_FullMethodName = "/hyapp.activity.v1.CumulativeRechargeRewardService/GetCumulativeRechargeRewardStatus" + CumulativeRechargeRewardService_ConsumeCumulativeRechargeReward_FullMethodName = "/hyapp.activity.v1.CumulativeRechargeRewardService/ConsumeCumulativeRechargeReward" +) + +// CumulativeRechargeRewardServiceClient is the client API for CumulativeRechargeRewardService 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. +// +// CumulativeRechargeRewardService 拥有 App 累充奖励查询和 wallet 充值事实消费入口。 +type CumulativeRechargeRewardServiceClient interface { + GetCumulativeRechargeRewardStatus(ctx context.Context, in *GetCumulativeRechargeRewardStatusRequest, opts ...grpc.CallOption) (*GetCumulativeRechargeRewardStatusResponse, error) + ConsumeCumulativeRechargeReward(ctx context.Context, in *ConsumeCumulativeRechargeRewardRequest, opts ...grpc.CallOption) (*ConsumeCumulativeRechargeRewardResponse, error) +} + +type cumulativeRechargeRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewCumulativeRechargeRewardServiceClient(cc grpc.ClientConnInterface) CumulativeRechargeRewardServiceClient { + return &cumulativeRechargeRewardServiceClient{cc} +} + +func (c *cumulativeRechargeRewardServiceClient) GetCumulativeRechargeRewardStatus(ctx context.Context, in *GetCumulativeRechargeRewardStatusRequest, opts ...grpc.CallOption) (*GetCumulativeRechargeRewardStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetCumulativeRechargeRewardStatusResponse) + err := c.cc.Invoke(ctx, CumulativeRechargeRewardService_GetCumulativeRechargeRewardStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *cumulativeRechargeRewardServiceClient) ConsumeCumulativeRechargeReward(ctx context.Context, in *ConsumeCumulativeRechargeRewardRequest, opts ...grpc.CallOption) (*ConsumeCumulativeRechargeRewardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ConsumeCumulativeRechargeRewardResponse) + err := c.cc.Invoke(ctx, CumulativeRechargeRewardService_ConsumeCumulativeRechargeReward_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CumulativeRechargeRewardServiceServer is the server API for CumulativeRechargeRewardService service. +// All implementations must embed UnimplementedCumulativeRechargeRewardServiceServer +// for forward compatibility. +// +// CumulativeRechargeRewardService 拥有 App 累充奖励查询和 wallet 充值事实消费入口。 +type CumulativeRechargeRewardServiceServer interface { + GetCumulativeRechargeRewardStatus(context.Context, *GetCumulativeRechargeRewardStatusRequest) (*GetCumulativeRechargeRewardStatusResponse, error) + ConsumeCumulativeRechargeReward(context.Context, *ConsumeCumulativeRechargeRewardRequest) (*ConsumeCumulativeRechargeRewardResponse, error) + mustEmbedUnimplementedCumulativeRechargeRewardServiceServer() +} + +// UnimplementedCumulativeRechargeRewardServiceServer 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 UnimplementedCumulativeRechargeRewardServiceServer struct{} + +func (UnimplementedCumulativeRechargeRewardServiceServer) GetCumulativeRechargeRewardStatus(context.Context, *GetCumulativeRechargeRewardStatusRequest) (*GetCumulativeRechargeRewardStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetCumulativeRechargeRewardStatus not implemented") +} +func (UnimplementedCumulativeRechargeRewardServiceServer) ConsumeCumulativeRechargeReward(context.Context, *ConsumeCumulativeRechargeRewardRequest) (*ConsumeCumulativeRechargeRewardResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ConsumeCumulativeRechargeReward not implemented") +} +func (UnimplementedCumulativeRechargeRewardServiceServer) mustEmbedUnimplementedCumulativeRechargeRewardServiceServer() { +} +func (UnimplementedCumulativeRechargeRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeCumulativeRechargeRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to CumulativeRechargeRewardServiceServer will +// result in compilation errors. +type UnsafeCumulativeRechargeRewardServiceServer interface { + mustEmbedUnimplementedCumulativeRechargeRewardServiceServer() +} + +func RegisterCumulativeRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv CumulativeRechargeRewardServiceServer) { + // If the following call panics, it indicates UnimplementedCumulativeRechargeRewardServiceServer 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(&CumulativeRechargeRewardService_ServiceDesc, srv) +} + +func _CumulativeRechargeRewardService_GetCumulativeRechargeRewardStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCumulativeRechargeRewardStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CumulativeRechargeRewardServiceServer).GetCumulativeRechargeRewardStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CumulativeRechargeRewardService_GetCumulativeRechargeRewardStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CumulativeRechargeRewardServiceServer).GetCumulativeRechargeRewardStatus(ctx, req.(*GetCumulativeRechargeRewardStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _CumulativeRechargeRewardService_ConsumeCumulativeRechargeReward_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConsumeCumulativeRechargeRewardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CumulativeRechargeRewardServiceServer).ConsumeCumulativeRechargeReward(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: CumulativeRechargeRewardService_ConsumeCumulativeRechargeReward_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CumulativeRechargeRewardServiceServer).ConsumeCumulativeRechargeReward(ctx, req.(*ConsumeCumulativeRechargeRewardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// CumulativeRechargeRewardService_ServiceDesc is the grpc.ServiceDesc for CumulativeRechargeRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var CumulativeRechargeRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.CumulativeRechargeRewardService", + HandlerType: (*CumulativeRechargeRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetCumulativeRechargeRewardStatus", + Handler: _CumulativeRechargeRewardService_GetCumulativeRechargeRewardStatus_Handler, + }, + { + MethodName: "ConsumeCumulativeRechargeReward", + Handler: _CumulativeRechargeRewardService_ConsumeCumulativeRechargeReward_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + +const ( + AdminCumulativeRechargeRewardService_GetCumulativeRechargeRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminCumulativeRechargeRewardService/GetCumulativeRechargeRewardConfig" + AdminCumulativeRechargeRewardService_UpdateCumulativeRechargeRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminCumulativeRechargeRewardService/UpdateCumulativeRechargeRewardConfig" + AdminCumulativeRechargeRewardService_ListCumulativeRechargeRewardGrants_FullMethodName = "/hyapp.activity.v1.AdminCumulativeRechargeRewardService/ListCumulativeRechargeRewardGrants" +) + +// AdminCumulativeRechargeRewardServiceClient is the client API for AdminCumulativeRechargeRewardService 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. +// +// AdminCumulativeRechargeRewardService 是后台活动管理访问累充奖励配置和发放记录的唯一入口。 +type AdminCumulativeRechargeRewardServiceClient interface { + GetCumulativeRechargeRewardConfig(ctx context.Context, in *GetCumulativeRechargeRewardConfigRequest, opts ...grpc.CallOption) (*GetCumulativeRechargeRewardConfigResponse, error) + UpdateCumulativeRechargeRewardConfig(ctx context.Context, in *UpdateCumulativeRechargeRewardConfigRequest, opts ...grpc.CallOption) (*UpdateCumulativeRechargeRewardConfigResponse, error) + ListCumulativeRechargeRewardGrants(ctx context.Context, in *ListCumulativeRechargeRewardGrantsRequest, opts ...grpc.CallOption) (*ListCumulativeRechargeRewardGrantsResponse, error) +} + +type adminCumulativeRechargeRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAdminCumulativeRechargeRewardServiceClient(cc grpc.ClientConnInterface) AdminCumulativeRechargeRewardServiceClient { + return &adminCumulativeRechargeRewardServiceClient{cc} +} + +func (c *adminCumulativeRechargeRewardServiceClient) GetCumulativeRechargeRewardConfig(ctx context.Context, in *GetCumulativeRechargeRewardConfigRequest, opts ...grpc.CallOption) (*GetCumulativeRechargeRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetCumulativeRechargeRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminCumulativeRechargeRewardService_GetCumulativeRechargeRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminCumulativeRechargeRewardServiceClient) UpdateCumulativeRechargeRewardConfig(ctx context.Context, in *UpdateCumulativeRechargeRewardConfigRequest, opts ...grpc.CallOption) (*UpdateCumulativeRechargeRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateCumulativeRechargeRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminCumulativeRechargeRewardService_UpdateCumulativeRechargeRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminCumulativeRechargeRewardServiceClient) ListCumulativeRechargeRewardGrants(ctx context.Context, in *ListCumulativeRechargeRewardGrantsRequest, opts ...grpc.CallOption) (*ListCumulativeRechargeRewardGrantsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListCumulativeRechargeRewardGrantsResponse) + err := c.cc.Invoke(ctx, AdminCumulativeRechargeRewardService_ListCumulativeRechargeRewardGrants_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AdminCumulativeRechargeRewardServiceServer is the server API for AdminCumulativeRechargeRewardService service. +// All implementations must embed UnimplementedAdminCumulativeRechargeRewardServiceServer +// for forward compatibility. +// +// AdminCumulativeRechargeRewardService 是后台活动管理访问累充奖励配置和发放记录的唯一入口。 +type AdminCumulativeRechargeRewardServiceServer interface { + GetCumulativeRechargeRewardConfig(context.Context, *GetCumulativeRechargeRewardConfigRequest) (*GetCumulativeRechargeRewardConfigResponse, error) + UpdateCumulativeRechargeRewardConfig(context.Context, *UpdateCumulativeRechargeRewardConfigRequest) (*UpdateCumulativeRechargeRewardConfigResponse, error) + ListCumulativeRechargeRewardGrants(context.Context, *ListCumulativeRechargeRewardGrantsRequest) (*ListCumulativeRechargeRewardGrantsResponse, error) + mustEmbedUnimplementedAdminCumulativeRechargeRewardServiceServer() +} + +// UnimplementedAdminCumulativeRechargeRewardServiceServer 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 UnimplementedAdminCumulativeRechargeRewardServiceServer struct{} + +func (UnimplementedAdminCumulativeRechargeRewardServiceServer) GetCumulativeRechargeRewardConfig(context.Context, *GetCumulativeRechargeRewardConfigRequest) (*GetCumulativeRechargeRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetCumulativeRechargeRewardConfig not implemented") +} +func (UnimplementedAdminCumulativeRechargeRewardServiceServer) UpdateCumulativeRechargeRewardConfig(context.Context, *UpdateCumulativeRechargeRewardConfigRequest) (*UpdateCumulativeRechargeRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateCumulativeRechargeRewardConfig not implemented") +} +func (UnimplementedAdminCumulativeRechargeRewardServiceServer) ListCumulativeRechargeRewardGrants(context.Context, *ListCumulativeRechargeRewardGrantsRequest) (*ListCumulativeRechargeRewardGrantsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListCumulativeRechargeRewardGrants not implemented") +} +func (UnimplementedAdminCumulativeRechargeRewardServiceServer) mustEmbedUnimplementedAdminCumulativeRechargeRewardServiceServer() { +} +func (UnimplementedAdminCumulativeRechargeRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeAdminCumulativeRechargeRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AdminCumulativeRechargeRewardServiceServer will +// result in compilation errors. +type UnsafeAdminCumulativeRechargeRewardServiceServer interface { + mustEmbedUnimplementedAdminCumulativeRechargeRewardServiceServer() +} + +func RegisterAdminCumulativeRechargeRewardServiceServer(s grpc.ServiceRegistrar, srv AdminCumulativeRechargeRewardServiceServer) { + // If the following call panics, it indicates UnimplementedAdminCumulativeRechargeRewardServiceServer 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(&AdminCumulativeRechargeRewardService_ServiceDesc, srv) +} + +func _AdminCumulativeRechargeRewardService_GetCumulativeRechargeRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCumulativeRechargeRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminCumulativeRechargeRewardServiceServer).GetCumulativeRechargeRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminCumulativeRechargeRewardService_GetCumulativeRechargeRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminCumulativeRechargeRewardServiceServer).GetCumulativeRechargeRewardConfig(ctx, req.(*GetCumulativeRechargeRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminCumulativeRechargeRewardService_UpdateCumulativeRechargeRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateCumulativeRechargeRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminCumulativeRechargeRewardServiceServer).UpdateCumulativeRechargeRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminCumulativeRechargeRewardService_UpdateCumulativeRechargeRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminCumulativeRechargeRewardServiceServer).UpdateCumulativeRechargeRewardConfig(ctx, req.(*UpdateCumulativeRechargeRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminCumulativeRechargeRewardService_ListCumulativeRechargeRewardGrants_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListCumulativeRechargeRewardGrantsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminCumulativeRechargeRewardServiceServer).ListCumulativeRechargeRewardGrants(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminCumulativeRechargeRewardService_ListCumulativeRechargeRewardGrants_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminCumulativeRechargeRewardServiceServer).ListCumulativeRechargeRewardGrants(ctx, req.(*ListCumulativeRechargeRewardGrantsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AdminCumulativeRechargeRewardService_ServiceDesc is the grpc.ServiceDesc for AdminCumulativeRechargeRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AdminCumulativeRechargeRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.AdminCumulativeRechargeRewardService", + HandlerType: (*AdminCumulativeRechargeRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetCumulativeRechargeRewardConfig", + Handler: _AdminCumulativeRechargeRewardService_GetCumulativeRechargeRewardConfig_Handler, + }, + { + MethodName: "UpdateCumulativeRechargeRewardConfig", + Handler: _AdminCumulativeRechargeRewardService_UpdateCumulativeRechargeRewardConfig_Handler, + }, + { + MethodName: "ListCumulativeRechargeRewardGrants", + Handler: _AdminCumulativeRechargeRewardService_ListCumulativeRechargeRewardGrants_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + +const ( + AdminRoomTurnoverRewardService_GetRoomTurnoverRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminRoomTurnoverRewardService/GetRoomTurnoverRewardConfig" + AdminRoomTurnoverRewardService_UpdateRoomTurnoverRewardConfig_FullMethodName = "/hyapp.activity.v1.AdminRoomTurnoverRewardService/UpdateRoomTurnoverRewardConfig" + AdminRoomTurnoverRewardService_ListRoomTurnoverRewardSettlements_FullMethodName = "/hyapp.activity.v1.AdminRoomTurnoverRewardService/ListRoomTurnoverRewardSettlements" + AdminRoomTurnoverRewardService_RetryRoomTurnoverRewardSettlement_FullMethodName = "/hyapp.activity.v1.AdminRoomTurnoverRewardService/RetryRoomTurnoverRewardSettlement" +) + +// AdminRoomTurnoverRewardServiceClient is the client API for AdminRoomTurnoverRewardService 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. +// +// AdminRoomTurnoverRewardService 是后台活动管理访问房间流水奖励配置和结算记录的唯一入口。 +type AdminRoomTurnoverRewardServiceClient interface { + GetRoomTurnoverRewardConfig(ctx context.Context, in *GetRoomTurnoverRewardConfigRequest, opts ...grpc.CallOption) (*GetRoomTurnoverRewardConfigResponse, error) + UpdateRoomTurnoverRewardConfig(ctx context.Context, in *UpdateRoomTurnoverRewardConfigRequest, opts ...grpc.CallOption) (*UpdateRoomTurnoverRewardConfigResponse, error) + ListRoomTurnoverRewardSettlements(ctx context.Context, in *ListRoomTurnoverRewardSettlementsRequest, opts ...grpc.CallOption) (*ListRoomTurnoverRewardSettlementsResponse, error) + RetryRoomTurnoverRewardSettlement(ctx context.Context, in *RetryRoomTurnoverRewardSettlementRequest, opts ...grpc.CallOption) (*RetryRoomTurnoverRewardSettlementResponse, error) +} + +type adminRoomTurnoverRewardServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAdminRoomTurnoverRewardServiceClient(cc grpc.ClientConnInterface) AdminRoomTurnoverRewardServiceClient { + return &adminRoomTurnoverRewardServiceClient{cc} +} + +func (c *adminRoomTurnoverRewardServiceClient) GetRoomTurnoverRewardConfig(ctx context.Context, in *GetRoomTurnoverRewardConfigRequest, opts ...grpc.CallOption) (*GetRoomTurnoverRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetRoomTurnoverRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminRoomTurnoverRewardService_GetRoomTurnoverRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminRoomTurnoverRewardServiceClient) UpdateRoomTurnoverRewardConfig(ctx context.Context, in *UpdateRoomTurnoverRewardConfigRequest, opts ...grpc.CallOption) (*UpdateRoomTurnoverRewardConfigResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpdateRoomTurnoverRewardConfigResponse) + err := c.cc.Invoke(ctx, AdminRoomTurnoverRewardService_UpdateRoomTurnoverRewardConfig_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminRoomTurnoverRewardServiceClient) ListRoomTurnoverRewardSettlements(ctx context.Context, in *ListRoomTurnoverRewardSettlementsRequest, opts ...grpc.CallOption) (*ListRoomTurnoverRewardSettlementsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListRoomTurnoverRewardSettlementsResponse) + err := c.cc.Invoke(ctx, AdminRoomTurnoverRewardService_ListRoomTurnoverRewardSettlements_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminRoomTurnoverRewardServiceClient) RetryRoomTurnoverRewardSettlement(ctx context.Context, in *RetryRoomTurnoverRewardSettlementRequest, opts ...grpc.CallOption) (*RetryRoomTurnoverRewardSettlementResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RetryRoomTurnoverRewardSettlementResponse) + err := c.cc.Invoke(ctx, AdminRoomTurnoverRewardService_RetryRoomTurnoverRewardSettlement_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AdminRoomTurnoverRewardServiceServer is the server API for AdminRoomTurnoverRewardService service. +// All implementations must embed UnimplementedAdminRoomTurnoverRewardServiceServer +// for forward compatibility. +// +// AdminRoomTurnoverRewardService 是后台活动管理访问房间流水奖励配置和结算记录的唯一入口。 +type AdminRoomTurnoverRewardServiceServer interface { + GetRoomTurnoverRewardConfig(context.Context, *GetRoomTurnoverRewardConfigRequest) (*GetRoomTurnoverRewardConfigResponse, error) + UpdateRoomTurnoverRewardConfig(context.Context, *UpdateRoomTurnoverRewardConfigRequest) (*UpdateRoomTurnoverRewardConfigResponse, error) + ListRoomTurnoverRewardSettlements(context.Context, *ListRoomTurnoverRewardSettlementsRequest) (*ListRoomTurnoverRewardSettlementsResponse, error) + RetryRoomTurnoverRewardSettlement(context.Context, *RetryRoomTurnoverRewardSettlementRequest) (*RetryRoomTurnoverRewardSettlementResponse, error) + mustEmbedUnimplementedAdminRoomTurnoverRewardServiceServer() +} + +// UnimplementedAdminRoomTurnoverRewardServiceServer 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 UnimplementedAdminRoomTurnoverRewardServiceServer struct{} + +func (UnimplementedAdminRoomTurnoverRewardServiceServer) GetRoomTurnoverRewardConfig(context.Context, *GetRoomTurnoverRewardConfigRequest) (*GetRoomTurnoverRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetRoomTurnoverRewardConfig not implemented") +} +func (UnimplementedAdminRoomTurnoverRewardServiceServer) UpdateRoomTurnoverRewardConfig(context.Context, *UpdateRoomTurnoverRewardConfigRequest) (*UpdateRoomTurnoverRewardConfigResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateRoomTurnoverRewardConfig not implemented") +} +func (UnimplementedAdminRoomTurnoverRewardServiceServer) ListRoomTurnoverRewardSettlements(context.Context, *ListRoomTurnoverRewardSettlementsRequest) (*ListRoomTurnoverRewardSettlementsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListRoomTurnoverRewardSettlements not implemented") +} +func (UnimplementedAdminRoomTurnoverRewardServiceServer) RetryRoomTurnoverRewardSettlement(context.Context, *RetryRoomTurnoverRewardSettlementRequest) (*RetryRoomTurnoverRewardSettlementResponse, error) { + return nil, status.Error(codes.Unimplemented, "method RetryRoomTurnoverRewardSettlement not implemented") +} +func (UnimplementedAdminRoomTurnoverRewardServiceServer) mustEmbedUnimplementedAdminRoomTurnoverRewardServiceServer() { +} +func (UnimplementedAdminRoomTurnoverRewardServiceServer) testEmbeddedByValue() {} + +// UnsafeAdminRoomTurnoverRewardServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AdminRoomTurnoverRewardServiceServer will +// result in compilation errors. +type UnsafeAdminRoomTurnoverRewardServiceServer interface { + mustEmbedUnimplementedAdminRoomTurnoverRewardServiceServer() +} + +func RegisterAdminRoomTurnoverRewardServiceServer(s grpc.ServiceRegistrar, srv AdminRoomTurnoverRewardServiceServer) { + // If the following call panics, it indicates UnimplementedAdminRoomTurnoverRewardServiceServer 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(&AdminRoomTurnoverRewardService_ServiceDesc, srv) +} + +func _AdminRoomTurnoverRewardService_GetRoomTurnoverRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetRoomTurnoverRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminRoomTurnoverRewardServiceServer).GetRoomTurnoverRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminRoomTurnoverRewardService_GetRoomTurnoverRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminRoomTurnoverRewardServiceServer).GetRoomTurnoverRewardConfig(ctx, req.(*GetRoomTurnoverRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminRoomTurnoverRewardService_UpdateRoomTurnoverRewardConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateRoomTurnoverRewardConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminRoomTurnoverRewardServiceServer).UpdateRoomTurnoverRewardConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminRoomTurnoverRewardService_UpdateRoomTurnoverRewardConfig_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminRoomTurnoverRewardServiceServer).UpdateRoomTurnoverRewardConfig(ctx, req.(*UpdateRoomTurnoverRewardConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminRoomTurnoverRewardService_ListRoomTurnoverRewardSettlements_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListRoomTurnoverRewardSettlementsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminRoomTurnoverRewardServiceServer).ListRoomTurnoverRewardSettlements(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminRoomTurnoverRewardService_ListRoomTurnoverRewardSettlements_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminRoomTurnoverRewardServiceServer).ListRoomTurnoverRewardSettlements(ctx, req.(*ListRoomTurnoverRewardSettlementsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminRoomTurnoverRewardService_RetryRoomTurnoverRewardSettlement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RetryRoomTurnoverRewardSettlementRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminRoomTurnoverRewardServiceServer).RetryRoomTurnoverRewardSettlement(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminRoomTurnoverRewardService_RetryRoomTurnoverRewardSettlement_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminRoomTurnoverRewardServiceServer).RetryRoomTurnoverRewardSettlement(ctx, req.(*RetryRoomTurnoverRewardSettlementRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AdminRoomTurnoverRewardService_ServiceDesc is the grpc.ServiceDesc for AdminRoomTurnoverRewardService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AdminRoomTurnoverRewardService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.AdminRoomTurnoverRewardService", + HandlerType: (*AdminRoomTurnoverRewardServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetRoomTurnoverRewardConfig", + Handler: _AdminRoomTurnoverRewardService_GetRoomTurnoverRewardConfig_Handler, + }, + { + MethodName: "UpdateRoomTurnoverRewardConfig", + Handler: _AdminRoomTurnoverRewardService_UpdateRoomTurnoverRewardConfig_Handler, + }, + { + MethodName: "ListRoomTurnoverRewardSettlements", + Handler: _AdminRoomTurnoverRewardService_ListRoomTurnoverRewardSettlements_Handler, + }, + { + MethodName: "RetryRoomTurnoverRewardSettlement", + Handler: _AdminRoomTurnoverRewardService_RetryRoomTurnoverRewardSettlement_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/activity/v1/activity.proto", +} + +const ( + AdminWeeklyStarService_ListWeeklyStarCycles_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/ListWeeklyStarCycles" + AdminWeeklyStarService_CreateWeeklyStarCycle_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/CreateWeeklyStarCycle" + AdminWeeklyStarService_GetWeeklyStarCycle_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/GetWeeklyStarCycle" + AdminWeeklyStarService_UpdateWeeklyStarCycle_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/UpdateWeeklyStarCycle" + AdminWeeklyStarService_SetWeeklyStarCycleStatus_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/SetWeeklyStarCycleStatus" + AdminWeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/ListWeeklyStarLeaderboard" + AdminWeeklyStarService_ListWeeklyStarSettlements_FullMethodName = "/hyapp.activity.v1.AdminWeeklyStarService/ListWeeklyStarSettlements" +) + +// AdminWeeklyStarServiceClient is the client API for AdminWeeklyStarService 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. +// +// AdminWeeklyStarService 是后台活动管理访问周星周期、榜单和结算结果的唯一入口。 +type AdminWeeklyStarServiceClient interface { + ListWeeklyStarCycles(ctx context.Context, in *ListWeeklyStarCyclesRequest, opts ...grpc.CallOption) (*ListWeeklyStarCyclesResponse, error) + CreateWeeklyStarCycle(ctx context.Context, in *UpsertWeeklyStarCycleRequest, opts ...grpc.CallOption) (*UpsertWeeklyStarCycleResponse, error) + GetWeeklyStarCycle(ctx context.Context, in *GetWeeklyStarCycleRequest, opts ...grpc.CallOption) (*GetWeeklyStarCycleResponse, error) + UpdateWeeklyStarCycle(ctx context.Context, in *UpsertWeeklyStarCycleRequest, opts ...grpc.CallOption) (*UpsertWeeklyStarCycleResponse, error) + SetWeeklyStarCycleStatus(ctx context.Context, in *SetWeeklyStarCycleStatusRequest, opts ...grpc.CallOption) (*SetWeeklyStarCycleStatusResponse, error) + ListWeeklyStarLeaderboard(ctx context.Context, in *ListWeeklyStarLeaderboardRequest, opts ...grpc.CallOption) (*ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarSettlements(ctx context.Context, in *ListWeeklyStarSettlementsRequest, opts ...grpc.CallOption) (*ListWeeklyStarSettlementsResponse, error) +} + +type adminWeeklyStarServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAdminWeeklyStarServiceClient(cc grpc.ClientConnInterface) AdminWeeklyStarServiceClient { + return &adminWeeklyStarServiceClient{cc} +} + +func (c *adminWeeklyStarServiceClient) ListWeeklyStarCycles(ctx context.Context, in *ListWeeklyStarCyclesRequest, opts ...grpc.CallOption) (*ListWeeklyStarCyclesResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWeeklyStarCyclesResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_ListWeeklyStarCycles_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) CreateWeeklyStarCycle(ctx context.Context, in *UpsertWeeklyStarCycleRequest, opts ...grpc.CallOption) (*UpsertWeeklyStarCycleResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpsertWeeklyStarCycleResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_CreateWeeklyStarCycle_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) GetWeeklyStarCycle(ctx context.Context, in *GetWeeklyStarCycleRequest, opts ...grpc.CallOption) (*GetWeeklyStarCycleResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetWeeklyStarCycleResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_GetWeeklyStarCycle_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) UpdateWeeklyStarCycle(ctx context.Context, in *UpsertWeeklyStarCycleRequest, opts ...grpc.CallOption) (*UpsertWeeklyStarCycleResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(UpsertWeeklyStarCycleResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_UpdateWeeklyStarCycle_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) SetWeeklyStarCycleStatus(ctx context.Context, in *SetWeeklyStarCycleStatusRequest, opts ...grpc.CallOption) (*SetWeeklyStarCycleStatusResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(SetWeeklyStarCycleStatusResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_SetWeeklyStarCycleStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) ListWeeklyStarLeaderboard(ctx context.Context, in *ListWeeklyStarLeaderboardRequest, opts ...grpc.CallOption) (*ListWeeklyStarLeaderboardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWeeklyStarLeaderboardResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *adminWeeklyStarServiceClient) ListWeeklyStarSettlements(ctx context.Context, in *ListWeeklyStarSettlementsRequest, opts ...grpc.CallOption) (*ListWeeklyStarSettlementsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListWeeklyStarSettlementsResponse) + err := c.cc.Invoke(ctx, AdminWeeklyStarService_ListWeeklyStarSettlements_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AdminWeeklyStarServiceServer is the server API for AdminWeeklyStarService service. +// All implementations must embed UnimplementedAdminWeeklyStarServiceServer +// for forward compatibility. +// +// AdminWeeklyStarService 是后台活动管理访问周星周期、榜单和结算结果的唯一入口。 +type AdminWeeklyStarServiceServer interface { + ListWeeklyStarCycles(context.Context, *ListWeeklyStarCyclesRequest) (*ListWeeklyStarCyclesResponse, error) + CreateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) + GetWeeklyStarCycle(context.Context, *GetWeeklyStarCycleRequest) (*GetWeeklyStarCycleResponse, error) + UpdateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) + SetWeeklyStarCycleStatus(context.Context, *SetWeeklyStarCycleStatusRequest) (*SetWeeklyStarCycleStatusResponse, error) + ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarSettlements(context.Context, *ListWeeklyStarSettlementsRequest) (*ListWeeklyStarSettlementsResponse, error) + mustEmbedUnimplementedAdminWeeklyStarServiceServer() +} + +// UnimplementedAdminWeeklyStarServiceServer 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 UnimplementedAdminWeeklyStarServiceServer struct{} + +func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarCycles(context.Context, *ListWeeklyStarCyclesRequest) (*ListWeeklyStarCyclesResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarCycles not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) CreateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CreateWeeklyStarCycle not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) GetWeeklyStarCycle(context.Context, *GetWeeklyStarCycleRequest) (*GetWeeklyStarCycleResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetWeeklyStarCycle not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) UpdateWeeklyStarCycle(context.Context, *UpsertWeeklyStarCycleRequest) (*UpsertWeeklyStarCycleResponse, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateWeeklyStarCycle not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) SetWeeklyStarCycleStatus(context.Context, *SetWeeklyStarCycleStatusRequest) (*SetWeeklyStarCycleStatusResponse, error) { + return nil, status.Error(codes.Unimplemented, "method SetWeeklyStarCycleStatus not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarLeaderboard(context.Context, *ListWeeklyStarLeaderboardRequest) (*ListWeeklyStarLeaderboardResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarLeaderboard not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) ListWeeklyStarSettlements(context.Context, *ListWeeklyStarSettlementsRequest) (*ListWeeklyStarSettlementsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListWeeklyStarSettlements not implemented") +} +func (UnimplementedAdminWeeklyStarServiceServer) mustEmbedUnimplementedAdminWeeklyStarServiceServer() { +} +func (UnimplementedAdminWeeklyStarServiceServer) testEmbeddedByValue() {} + +// UnsafeAdminWeeklyStarServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AdminWeeklyStarServiceServer will +// result in compilation errors. +type UnsafeAdminWeeklyStarServiceServer interface { + mustEmbedUnimplementedAdminWeeklyStarServiceServer() +} + +func RegisterAdminWeeklyStarServiceServer(s grpc.ServiceRegistrar, srv AdminWeeklyStarServiceServer) { + // If the following call panics, it indicates UnimplementedAdminWeeklyStarServiceServer 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(&AdminWeeklyStarService_ServiceDesc, srv) +} + +func _AdminWeeklyStarService_ListWeeklyStarCycles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWeeklyStarCyclesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarCycles(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_ListWeeklyStarCycles_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarCycles(ctx, req.(*ListWeeklyStarCyclesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_CreateWeeklyStarCycle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertWeeklyStarCycleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).CreateWeeklyStarCycle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_CreateWeeklyStarCycle_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).CreateWeeklyStarCycle(ctx, req.(*UpsertWeeklyStarCycleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_GetWeeklyStarCycle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetWeeklyStarCycleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).GetWeeklyStarCycle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_GetWeeklyStarCycle_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).GetWeeklyStarCycle(ctx, req.(*GetWeeklyStarCycleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_UpdateWeeklyStarCycle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertWeeklyStarCycleRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).UpdateWeeklyStarCycle(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_UpdateWeeklyStarCycle_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).UpdateWeeklyStarCycle(ctx, req.(*UpsertWeeklyStarCycleRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_SetWeeklyStarCycleStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetWeeklyStarCycleStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).SetWeeklyStarCycleStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_SetWeeklyStarCycleStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).SetWeeklyStarCycleStatus(ctx, req.(*SetWeeklyStarCycleStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_ListWeeklyStarLeaderboard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWeeklyStarLeaderboardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarLeaderboard(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_ListWeeklyStarLeaderboard_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarLeaderboard(ctx, req.(*ListWeeklyStarLeaderboardRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AdminWeeklyStarService_ListWeeklyStarSettlements_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListWeeklyStarSettlementsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarSettlements(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AdminWeeklyStarService_ListWeeklyStarSettlements_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AdminWeeklyStarServiceServer).ListWeeklyStarSettlements(ctx, req.(*ListWeeklyStarSettlementsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AdminWeeklyStarService_ServiceDesc is the grpc.ServiceDesc for AdminWeeklyStarService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AdminWeeklyStarService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hyapp.activity.v1.AdminWeeklyStarService", + HandlerType: (*AdminWeeklyStarServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "ListWeeklyStarCycles", + Handler: _AdminWeeklyStarService_ListWeeklyStarCycles_Handler, + }, + { + MethodName: "CreateWeeklyStarCycle", + Handler: _AdminWeeklyStarService_CreateWeeklyStarCycle_Handler, + }, + { + MethodName: "GetWeeklyStarCycle", + Handler: _AdminWeeklyStarService_GetWeeklyStarCycle_Handler, + }, + { + MethodName: "UpdateWeeklyStarCycle", + Handler: _AdminWeeklyStarService_UpdateWeeklyStarCycle_Handler, + }, + { + MethodName: "SetWeeklyStarCycleStatus", + Handler: _AdminWeeklyStarService_SetWeeklyStarCycleStatus_Handler, + }, + { + MethodName: "ListWeeklyStarLeaderboard", + Handler: _AdminWeeklyStarService_ListWeeklyStarLeaderboard_Handler, + }, + { + MethodName: "ListWeeklyStarSettlements", + Handler: _AdminWeeklyStarService_ListWeeklyStarSettlements_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/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index 31cefea3..0bfed8fb 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -12062,6 +12062,208 @@ func (x *CreditLuckyGiftRewardResponse) GetGrantedAtMs() int64 { return 0 } +// CreditRoomTurnoverRewardRequest 是 activity-service 每周房间流水奖励结算后的金币入账命令。 +type CreditRoomTurnoverRewardRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + SettlementId string `protobuf:"bytes,5,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + PeriodStartMs int64 `protobuf:"varint,7,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + PeriodEndMs int64 `protobuf:"varint,8,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` + CoinSpent int64 `protobuf:"varint,9,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + TierId int64 `protobuf:"varint,10,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,11,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + Reason string `protobuf:"bytes,12,opt,name=reason,proto3" json:"reason,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreditRoomTurnoverRewardRequest) Reset() { + *x = CreditRoomTurnoverRewardRequest{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreditRoomTurnoverRewardRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreditRoomTurnoverRewardRequest) ProtoMessage() {} + +func (x *CreditRoomTurnoverRewardRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + 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 CreditRoomTurnoverRewardRequest.ProtoReflect.Descriptor instead. +func (*CreditRoomTurnoverRewardRequest) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} +} + +func (x *CreditRoomTurnoverRewardRequest) GetCommandId() string { + if x != nil { + return x.CommandId + } + return "" +} + +func (x *CreditRoomTurnoverRewardRequest) GetAppCode() string { + if x != nil { + return x.AppCode + } + return "" +} + +func (x *CreditRoomTurnoverRewardRequest) GetTargetUserId() int64 { + if x != nil { + return x.TargetUserId + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetSettlementId() string { + if x != nil { + return x.SettlementId + } + return "" +} + +func (x *CreditRoomTurnoverRewardRequest) GetRoomId() string { + if x != nil { + return x.RoomId + } + return "" +} + +func (x *CreditRoomTurnoverRewardRequest) GetPeriodStartMs() int64 { + if x != nil { + return x.PeriodStartMs + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetPeriodEndMs() int64 { + if x != nil { + return x.PeriodEndMs + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetCoinSpent() int64 { + if x != nil { + return x.CoinSpent + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetTierId() int64 { + if x != nil { + return x.TierId + } + return 0 +} + +func (x *CreditRoomTurnoverRewardRequest) GetTierCode() string { + if x != nil { + return x.TierCode + } + return "" +} + +func (x *CreditRoomTurnoverRewardRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +// CreditRoomTurnoverRewardResponse 返回房间流水奖励入账流水和用户 COIN 账后余额。 +type CreditRoomTurnoverRewardResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreditRoomTurnoverRewardResponse) Reset() { + *x = CreditRoomTurnoverRewardResponse{} + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreditRoomTurnoverRewardResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreditRoomTurnoverRewardResponse) ProtoMessage() {} + +func (x *CreditRoomTurnoverRewardResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + 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 CreditRoomTurnoverRewardResponse.ProtoReflect.Descriptor instead. +func (*CreditRoomTurnoverRewardResponse) Descriptor() ([]byte, []int) { + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} +} + +func (x *CreditRoomTurnoverRewardResponse) GetTransactionId() string { + if x != nil { + return x.TransactionId + } + return "" +} + +func (x *CreditRoomTurnoverRewardResponse) GetBalance() *AssetBalance { + if x != nil { + return x.Balance + } + return nil +} + +func (x *CreditRoomTurnoverRewardResponse) GetAmount() int64 { + if x != nil { + return x.Amount + } + return 0 +} + +func (x *CreditRoomTurnoverRewardResponse) GetGrantedAtMs() int64 { + if x != nil { + return x.GrantedAtMs + } + return 0 +} + // ApplyGameCoinChangeRequest 是 game-service 唯一可以调用的钱包游戏改账入口。 type ApplyGameCoinChangeRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -12083,7 +12285,7 @@ type ApplyGameCoinChangeRequest struct { func (x *ApplyGameCoinChangeRequest) Reset() { *x = ApplyGameCoinChangeRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12095,7 +12297,7 @@ func (x *ApplyGameCoinChangeRequest) String() string { func (*ApplyGameCoinChangeRequest) ProtoMessage() {} func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[138] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12108,7 +12310,7 @@ func (x *ApplyGameCoinChangeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeRequest.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{138} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} } func (x *ApplyGameCoinChangeRequest) GetRequestId() string { @@ -12207,7 +12409,7 @@ type ApplyGameCoinChangeResponse struct { func (x *ApplyGameCoinChangeResponse) Reset() { *x = ApplyGameCoinChangeResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12219,7 +12421,7 @@ func (x *ApplyGameCoinChangeResponse) String() string { func (*ApplyGameCoinChangeResponse) ProtoMessage() {} func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[139] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12232,7 +12434,7 @@ func (x *ApplyGameCoinChangeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ApplyGameCoinChangeResponse.ProtoReflect.Descriptor instead. func (*ApplyGameCoinChangeResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{139} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} } func (x *ApplyGameCoinChangeResponse) GetWalletTransactionId() string { @@ -12275,7 +12477,7 @@ type RedPacketConfig struct { func (x *RedPacketConfig) Reset() { *x = RedPacketConfig{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12287,7 +12489,7 @@ func (x *RedPacketConfig) String() string { func (*RedPacketConfig) ProtoMessage() {} func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[140] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12300,7 +12502,7 @@ func (x *RedPacketConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketConfig.ProtoReflect.Descriptor instead. func (*RedPacketConfig) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{140} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} } func (x *RedPacketConfig) GetAppCode() string { @@ -12399,7 +12601,7 @@ type RedPacketClaim struct { func (x *RedPacketClaim) Reset() { *x = RedPacketClaim{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12411,7 +12613,7 @@ func (x *RedPacketClaim) String() string { func (*RedPacketClaim) ProtoMessage() {} func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[141] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12424,7 +12626,7 @@ func (x *RedPacketClaim) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacketClaim.ProtoReflect.Descriptor instead. func (*RedPacketClaim) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{141} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} } func (x *RedPacketClaim) GetAppCode() string { @@ -12534,7 +12736,7 @@ type RedPacket struct { func (x *RedPacket) Reset() { *x = RedPacket{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12546,7 +12748,7 @@ func (x *RedPacket) String() string { func (*RedPacket) ProtoMessage() {} func (x *RedPacket) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[142] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12559,7 +12761,7 @@ func (x *RedPacket) ProtoReflect() protoreflect.Message { // Deprecated: Use RedPacket.ProtoReflect.Descriptor instead. func (*RedPacket) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{142} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} } func (x *RedPacket) GetAppCode() string { @@ -12726,7 +12928,7 @@ type GetRedPacketConfigRequest struct { func (x *GetRedPacketConfigRequest) Reset() { *x = GetRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12738,7 +12940,7 @@ func (x *GetRedPacketConfigRequest) String() string { func (*GetRedPacketConfigRequest) ProtoMessage() {} func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[143] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12751,7 +12953,7 @@ func (x *GetRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{143} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} } func (x *GetRedPacketConfigRequest) GetRequestId() string { @@ -12778,7 +12980,7 @@ type GetRedPacketConfigResponse struct { func (x *GetRedPacketConfigResponse) Reset() { *x = GetRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12790,7 +12992,7 @@ func (x *GetRedPacketConfigResponse) String() string { func (*GetRedPacketConfigResponse) ProtoMessage() {} func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[144] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12803,7 +13005,7 @@ func (x *GetRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{144} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} } func (x *GetRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -12838,7 +13040,7 @@ type UpdateRedPacketConfigRequest struct { func (x *UpdateRedPacketConfigRequest) Reset() { *x = UpdateRedPacketConfigRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12850,7 +13052,7 @@ func (x *UpdateRedPacketConfigRequest) String() string { func (*UpdateRedPacketConfigRequest) ProtoMessage() {} func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[145] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12863,7 +13065,7 @@ func (x *UpdateRedPacketConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigRequest.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{145} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} } func (x *UpdateRedPacketConfigRequest) GetRequestId() string { @@ -12946,7 +13148,7 @@ type UpdateRedPacketConfigResponse struct { func (x *UpdateRedPacketConfigResponse) Reset() { *x = UpdateRedPacketConfigResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -12958,7 +13160,7 @@ func (x *UpdateRedPacketConfigResponse) String() string { func (*UpdateRedPacketConfigResponse) ProtoMessage() {} func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[146] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -12971,7 +13173,7 @@ func (x *UpdateRedPacketConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateRedPacketConfigResponse.ProtoReflect.Descriptor instead. func (*UpdateRedPacketConfigResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{146} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} } func (x *UpdateRedPacketConfigResponse) GetConfig() *RedPacketConfig { @@ -13005,7 +13207,7 @@ type CreateRedPacketRequest struct { func (x *CreateRedPacketRequest) Reset() { *x = CreateRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13017,7 +13219,7 @@ func (x *CreateRedPacketRequest) String() string { func (*CreateRedPacketRequest) ProtoMessage() {} func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[147] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13030,7 +13232,7 @@ func (x *CreateRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketRequest.ProtoReflect.Descriptor instead. func (*CreateRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{147} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} } func (x *CreateRedPacketRequest) GetRequestId() string { @@ -13107,7 +13309,7 @@ type CreateRedPacketResponse struct { func (x *CreateRedPacketResponse) Reset() { *x = CreateRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13119,7 +13321,7 @@ func (x *CreateRedPacketResponse) String() string { func (*CreateRedPacketResponse) ProtoMessage() {} func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[148] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13132,7 +13334,7 @@ func (x *CreateRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateRedPacketResponse.ProtoReflect.Descriptor instead. func (*CreateRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{148} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} } func (x *CreateRedPacketResponse) GetPacket() *RedPacket { @@ -13169,7 +13371,7 @@ type ClaimRedPacketRequest struct { func (x *ClaimRedPacketRequest) Reset() { *x = ClaimRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13181,7 +13383,7 @@ func (x *ClaimRedPacketRequest) String() string { func (*ClaimRedPacketRequest) ProtoMessage() {} func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[149] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13194,7 +13396,7 @@ func (x *ClaimRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketRequest.ProtoReflect.Descriptor instead. func (*ClaimRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{149} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} } func (x *ClaimRedPacketRequest) GetRequestId() string { @@ -13244,7 +13446,7 @@ type ClaimRedPacketResponse struct { func (x *ClaimRedPacketResponse) Reset() { *x = ClaimRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13256,7 +13458,7 @@ func (x *ClaimRedPacketResponse) String() string { func (*ClaimRedPacketResponse) ProtoMessage() {} func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[150] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13269,7 +13471,7 @@ func (x *ClaimRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ClaimRedPacketResponse.ProtoReflect.Descriptor instead. func (*ClaimRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{150} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} } func (x *ClaimRedPacketResponse) GetClaim() *RedPacketClaim { @@ -13320,7 +13522,7 @@ type ListRedPacketsRequest struct { func (x *ListRedPacketsRequest) Reset() { *x = ListRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13332,7 +13534,7 @@ func (x *ListRedPacketsRequest) String() string { func (*ListRedPacketsRequest) ProtoMessage() {} func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[151] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13345,7 +13547,7 @@ func (x *ListRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ListRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{151} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} } func (x *ListRedPacketsRequest) GetRequestId() string { @@ -13443,7 +13645,7 @@ type ListRedPacketsResponse struct { func (x *ListRedPacketsResponse) Reset() { *x = ListRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13455,7 +13657,7 @@ func (x *ListRedPacketsResponse) String() string { func (*ListRedPacketsResponse) ProtoMessage() {} func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[152] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13468,7 +13670,7 @@ func (x *ListRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ListRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{152} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{154} } func (x *ListRedPacketsResponse) GetPackets() []*RedPacket { @@ -13505,7 +13707,7 @@ type GetRedPacketRequest struct { func (x *GetRedPacketRequest) Reset() { *x = GetRedPacketRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13517,7 +13719,7 @@ func (x *GetRedPacketRequest) String() string { func (*GetRedPacketRequest) ProtoMessage() {} func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[153] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13530,7 +13732,7 @@ func (x *GetRedPacketRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketRequest.ProtoReflect.Descriptor instead. func (*GetRedPacketRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{153} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{155} } func (x *GetRedPacketRequest) GetRequestId() string { @@ -13578,7 +13780,7 @@ type GetRedPacketResponse struct { func (x *GetRedPacketResponse) Reset() { *x = GetRedPacketResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13590,7 +13792,7 @@ func (x *GetRedPacketResponse) String() string { func (*GetRedPacketResponse) ProtoMessage() {} func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[154] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13603,7 +13805,7 @@ func (x *GetRedPacketResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetRedPacketResponse.ProtoReflect.Descriptor instead. func (*GetRedPacketResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{154} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{156} } func (x *GetRedPacketResponse) GetPacket() *RedPacket { @@ -13631,7 +13833,7 @@ type ExpireRedPacketsRequest struct { func (x *ExpireRedPacketsRequest) Reset() { *x = ExpireRedPacketsRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13643,7 +13845,7 @@ func (x *ExpireRedPacketsRequest) String() string { func (*ExpireRedPacketsRequest) ProtoMessage() {} func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[155] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13656,7 +13858,7 @@ func (x *ExpireRedPacketsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsRequest.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{155} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{157} } func (x *ExpireRedPacketsRequest) GetRequestId() string { @@ -13691,7 +13893,7 @@ type ExpireRedPacketsResponse struct { func (x *ExpireRedPacketsResponse) Reset() { *x = ExpireRedPacketsResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13703,7 +13905,7 @@ func (x *ExpireRedPacketsResponse) String() string { func (*ExpireRedPacketsResponse) ProtoMessage() {} func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[156] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13716,7 +13918,7 @@ func (x *ExpireRedPacketsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ExpireRedPacketsResponse.ProtoReflect.Descriptor instead. func (*ExpireRedPacketsResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{156} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{158} } func (x *ExpireRedPacketsResponse) GetExpiredCount() int32 { @@ -13752,7 +13954,7 @@ type RetryRedPacketRefundRequest struct { func (x *RetryRedPacketRefundRequest) Reset() { *x = RetryRedPacketRefundRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13764,7 +13966,7 @@ func (x *RetryRedPacketRefundRequest) String() string { func (*RetryRedPacketRefundRequest) ProtoMessage() {} func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[157] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13777,7 +13979,7 @@ func (x *RetryRedPacketRefundRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundRequest.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{157} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{159} } func (x *RetryRedPacketRefundRequest) GetRequestId() string { @@ -13819,7 +14021,7 @@ type RetryRedPacketRefundResponse struct { func (x *RetryRedPacketRefundResponse) Reset() { *x = RetryRedPacketRefundResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13831,7 +14033,7 @@ func (x *RetryRedPacketRefundResponse) String() string { func (*RetryRedPacketRefundResponse) ProtoMessage() {} func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[158] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13844,7 +14046,7 @@ func (x *RetryRedPacketRefundResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RetryRedPacketRefundResponse.ProtoReflect.Descriptor instead. func (*RetryRedPacketRefundResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{158} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{160} } func (x *RetryRedPacketRefundResponse) GetPacket() *RedPacket { @@ -13883,7 +14085,7 @@ type CronBatchRequest struct { func (x *CronBatchRequest) Reset() { *x = CronBatchRequest{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13895,7 +14097,7 @@ func (x *CronBatchRequest) String() string { func (*CronBatchRequest) ProtoMessage() {} func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[159] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[161] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13908,7 +14110,7 @@ func (x *CronBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchRequest.ProtoReflect.Descriptor instead. func (*CronBatchRequest) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{159} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{161} } func (x *CronBatchRequest) GetRequestId() string { @@ -13967,7 +14169,7 @@ type CronBatchResponse struct { func (x *CronBatchResponse) Reset() { *x = CronBatchResponse{} - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -13979,7 +14181,7 @@ func (x *CronBatchResponse) String() string { func (*CronBatchResponse) ProtoMessage() {} func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { - mi := &file_proto_wallet_v1_wallet_proto_msgTypes[160] + mi := &file_proto_wallet_v1_wallet_proto_msgTypes[162] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -13992,7 +14194,7 @@ func (x *CronBatchResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CronBatchResponse.ProtoReflect.Descriptor instead. func (*CronBatchResponse) Descriptor() ([]byte, []int) { - return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{160} + return file_proto_wallet_v1_wallet_proto_rawDescGZIP(), []int{162} } func (x *CronBatchResponse) GetClaimedCount() int32 { @@ -15273,6 +15475,27 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x16\n" + "\x06amount\x18\x03 \x01(\x03R\x06amount\x12\"\n" + + "\rgranted_at_ms\x18\x04 \x01(\x03R\vgrantedAtMs\"\x90\x03\n" + + "\x1fCreditRoomTurnoverRewardRequest\x12\x1d\n" + + "\n" + + "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + + "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + + "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + + "\x06amount\x18\x04 \x01(\x03R\x06amount\x12#\n" + + "\rsettlement_id\x18\x05 \x01(\tR\fsettlementId\x12\x17\n" + + "\aroom_id\x18\x06 \x01(\tR\x06roomId\x12&\n" + + "\x0fperiod_start_ms\x18\a \x01(\x03R\rperiodStartMs\x12\"\n" + + "\rperiod_end_ms\x18\b \x01(\x03R\vperiodEndMs\x12\x1d\n" + + "\n" + + "coin_spent\x18\t \x01(\x03R\tcoinSpent\x12\x17\n" + + "\atier_id\x18\n" + + " \x01(\x03R\x06tierId\x12\x1b\n" + + "\ttier_code\x18\v \x01(\tR\btierCode\x12\x16\n" + + "\x06reason\x18\f \x01(\tR\x06reason\"\xbe\x01\n" + + " CreditRoomTurnoverRewardResponse\x12%\n" + + "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + + "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x16\n" + + "\x06amount\x18\x03 \x01(\x03R\x06amount\x12\"\n" + "\rgranted_at_ms\x18\x04 \x01(\x03R\vgrantedAtMs\"\x9a\x03\n" + "\x1aApplyGameCoinChangeRequest\x12\x1d\n" + "\n" + @@ -15472,7 +15695,7 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x11WalletCronService\x12n\n" + "%ProcessHostSalaryDailySettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12r\n" + ")ProcessHostSalaryHalfMonthSettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12g\n" + - "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\x88:\n" + + "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\x89;\n" + "\rWalletService\x12R\n" + "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12a\n" + "\x0eBatchDebitGift\x12&.hyapp.wallet.v1.BatchDebitGiftRequest\x1a'.hyapp.wallet.v1.BatchDebitGiftResponse\x12X\n" + @@ -15531,7 +15754,8 @@ const file_proto_wallet_v1_wallet_proto_rawDesc = "" + "\x12ListAdminVipLevels\x12*.hyapp.wallet.v1.ListAdminVipLevelsRequest\x1a+.hyapp.wallet.v1.ListAdminVipLevelsResponse\x12s\n" + "\x14UpdateAdminVipLevels\x12,.hyapp.wallet.v1.UpdateAdminVipLevelsRequest\x1a-.hyapp.wallet.v1.UpdateAdminVipLevelsResponse\x12g\n" + "\x10CreditTaskReward\x12(.hyapp.wallet.v1.CreditTaskRewardRequest\x1a).hyapp.wallet.v1.CreditTaskRewardResponse\x12v\n" + - "\x15CreditLuckyGiftReward\x12-.hyapp.wallet.v1.CreditLuckyGiftRewardRequest\x1a..hyapp.wallet.v1.CreditLuckyGiftRewardResponse\x12p\n" + + "\x15CreditLuckyGiftReward\x12-.hyapp.wallet.v1.CreditLuckyGiftRewardRequest\x1a..hyapp.wallet.v1.CreditLuckyGiftRewardResponse\x12\x7f\n" + + "\x18CreditRoomTurnoverReward\x120.hyapp.wallet.v1.CreditRoomTurnoverRewardRequest\x1a1.hyapp.wallet.v1.CreditRoomTurnoverRewardResponse\x12p\n" + "\x13ApplyGameCoinChange\x12+.hyapp.wallet.v1.ApplyGameCoinChangeRequest\x1a,.hyapp.wallet.v1.ApplyGameCoinChangeResponse\x12m\n" + "\x12GetRedPacketConfig\x12*.hyapp.wallet.v1.GetRedPacketConfigRequest\x1a+.hyapp.wallet.v1.GetRedPacketConfigResponse\x12v\n" + "\x15UpdateRedPacketConfig\x12-.hyapp.wallet.v1.UpdateRedPacketConfigRequest\x1a..hyapp.wallet.v1.UpdateRedPacketConfigResponse\x12d\n" + @@ -15554,7 +15778,7 @@ func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { return file_proto_wallet_v1_wallet_proto_rawDescData } -var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 161) +var file_proto_wallet_v1_wallet_proto_msgTypes = make([]protoimpl.MessageInfo, 163) var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*DebitGiftRequest)(nil), // 0: hyapp.wallet.v1.DebitGiftRequest (*DebitGiftResponse)(nil), // 1: hyapp.wallet.v1.DebitGiftResponse @@ -15694,29 +15918,31 @@ var file_proto_wallet_v1_wallet_proto_goTypes = []any{ (*CreditTaskRewardResponse)(nil), // 135: hyapp.wallet.v1.CreditTaskRewardResponse (*CreditLuckyGiftRewardRequest)(nil), // 136: hyapp.wallet.v1.CreditLuckyGiftRewardRequest (*CreditLuckyGiftRewardResponse)(nil), // 137: hyapp.wallet.v1.CreditLuckyGiftRewardResponse - (*ApplyGameCoinChangeRequest)(nil), // 138: hyapp.wallet.v1.ApplyGameCoinChangeRequest - (*ApplyGameCoinChangeResponse)(nil), // 139: hyapp.wallet.v1.ApplyGameCoinChangeResponse - (*RedPacketConfig)(nil), // 140: hyapp.wallet.v1.RedPacketConfig - (*RedPacketClaim)(nil), // 141: hyapp.wallet.v1.RedPacketClaim - (*RedPacket)(nil), // 142: hyapp.wallet.v1.RedPacket - (*GetRedPacketConfigRequest)(nil), // 143: hyapp.wallet.v1.GetRedPacketConfigRequest - (*GetRedPacketConfigResponse)(nil), // 144: hyapp.wallet.v1.GetRedPacketConfigResponse - (*UpdateRedPacketConfigRequest)(nil), // 145: hyapp.wallet.v1.UpdateRedPacketConfigRequest - (*UpdateRedPacketConfigResponse)(nil), // 146: hyapp.wallet.v1.UpdateRedPacketConfigResponse - (*CreateRedPacketRequest)(nil), // 147: hyapp.wallet.v1.CreateRedPacketRequest - (*CreateRedPacketResponse)(nil), // 148: hyapp.wallet.v1.CreateRedPacketResponse - (*ClaimRedPacketRequest)(nil), // 149: hyapp.wallet.v1.ClaimRedPacketRequest - (*ClaimRedPacketResponse)(nil), // 150: hyapp.wallet.v1.ClaimRedPacketResponse - (*ListRedPacketsRequest)(nil), // 151: hyapp.wallet.v1.ListRedPacketsRequest - (*ListRedPacketsResponse)(nil), // 152: hyapp.wallet.v1.ListRedPacketsResponse - (*GetRedPacketRequest)(nil), // 153: hyapp.wallet.v1.GetRedPacketRequest - (*GetRedPacketResponse)(nil), // 154: hyapp.wallet.v1.GetRedPacketResponse - (*ExpireRedPacketsRequest)(nil), // 155: hyapp.wallet.v1.ExpireRedPacketsRequest - (*ExpireRedPacketsResponse)(nil), // 156: hyapp.wallet.v1.ExpireRedPacketsResponse - (*RetryRedPacketRefundRequest)(nil), // 157: hyapp.wallet.v1.RetryRedPacketRefundRequest - (*RetryRedPacketRefundResponse)(nil), // 158: hyapp.wallet.v1.RetryRedPacketRefundResponse - (*CronBatchRequest)(nil), // 159: hyapp.wallet.v1.CronBatchRequest - (*CronBatchResponse)(nil), // 160: hyapp.wallet.v1.CronBatchResponse + (*CreditRoomTurnoverRewardRequest)(nil), // 138: hyapp.wallet.v1.CreditRoomTurnoverRewardRequest + (*CreditRoomTurnoverRewardResponse)(nil), // 139: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse + (*ApplyGameCoinChangeRequest)(nil), // 140: hyapp.wallet.v1.ApplyGameCoinChangeRequest + (*ApplyGameCoinChangeResponse)(nil), // 141: hyapp.wallet.v1.ApplyGameCoinChangeResponse + (*RedPacketConfig)(nil), // 142: hyapp.wallet.v1.RedPacketConfig + (*RedPacketClaim)(nil), // 143: hyapp.wallet.v1.RedPacketClaim + (*RedPacket)(nil), // 144: hyapp.wallet.v1.RedPacket + (*GetRedPacketConfigRequest)(nil), // 145: hyapp.wallet.v1.GetRedPacketConfigRequest + (*GetRedPacketConfigResponse)(nil), // 146: hyapp.wallet.v1.GetRedPacketConfigResponse + (*UpdateRedPacketConfigRequest)(nil), // 147: hyapp.wallet.v1.UpdateRedPacketConfigRequest + (*UpdateRedPacketConfigResponse)(nil), // 148: hyapp.wallet.v1.UpdateRedPacketConfigResponse + (*CreateRedPacketRequest)(nil), // 149: hyapp.wallet.v1.CreateRedPacketRequest + (*CreateRedPacketResponse)(nil), // 150: hyapp.wallet.v1.CreateRedPacketResponse + (*ClaimRedPacketRequest)(nil), // 151: hyapp.wallet.v1.ClaimRedPacketRequest + (*ClaimRedPacketResponse)(nil), // 152: hyapp.wallet.v1.ClaimRedPacketResponse + (*ListRedPacketsRequest)(nil), // 153: hyapp.wallet.v1.ListRedPacketsRequest + (*ListRedPacketsResponse)(nil), // 154: hyapp.wallet.v1.ListRedPacketsResponse + (*GetRedPacketRequest)(nil), // 155: hyapp.wallet.v1.GetRedPacketRequest + (*GetRedPacketResponse)(nil), // 156: hyapp.wallet.v1.GetRedPacketResponse + (*ExpireRedPacketsRequest)(nil), // 157: hyapp.wallet.v1.ExpireRedPacketsRequest + (*ExpireRedPacketsResponse)(nil), // 158: hyapp.wallet.v1.ExpireRedPacketsResponse + (*RetryRedPacketRefundRequest)(nil), // 159: hyapp.wallet.v1.RetryRedPacketRefundRequest + (*RetryRedPacketRefundResponse)(nil), // 160: hyapp.wallet.v1.RetryRedPacketRefundResponse + (*CronBatchRequest)(nil), // 161: hyapp.wallet.v1.CronBatchRequest + (*CronBatchResponse)(nil), // 162: hyapp.wallet.v1.CronBatchResponse } var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 2, // 0: hyapp.wallet.v1.BatchDebitGiftRequest.targets:type_name -> hyapp.wallet.v1.DebitGiftTarget @@ -15785,160 +16011,163 @@ var file_proto_wallet_v1_wallet_proto_depIdxs = []int32{ 119, // 63: hyapp.wallet.v1.UpdateAdminVipLevelsResponse.levels:type_name -> hyapp.wallet.v1.VipLevel 6, // 64: hyapp.wallet.v1.CreditTaskRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance 6, // 65: hyapp.wallet.v1.CreditLuckyGiftRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance - 141, // 66: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim - 140, // 67: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 140, // 68: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig - 142, // 69: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 141, // 70: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim - 142, // 71: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 142, // 72: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket - 142, // 73: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 142, // 74: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket - 159, // 75: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 159, // 76: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 159, // 77: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest - 0, // 78: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest - 3, // 79: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest - 7, // 80: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest - 11, // 81: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest - 14, // 82: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest - 16, // 83: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest - 18, // 84: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest - 20, // 85: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest - 23, // 86: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest - 25, // 87: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest - 27, // 88: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest - 39, // 89: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest - 41, // 90: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest - 43, // 91: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest - 44, // 92: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest - 45, // 93: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest - 47, // 94: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest - 49, // 95: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest - 51, // 96: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest - 52, // 97: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest - 53, // 98: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest - 55, // 99: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest - 57, // 100: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest - 61, // 101: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest - 62, // 102: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest - 63, // 103: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest - 59, // 104: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest - 65, // 105: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest - 66, // 106: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest - 68, // 107: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest - 70, // 108: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest - 72, // 109: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest - 74, // 110: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest - 77, // 111: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest - 80, // 112: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest - 82, // 113: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest - 84, // 114: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest - 86, // 115: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest - 89, // 116: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest - 92, // 117: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest - 95, // 118: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest - 98, // 119: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest - 101, // 120: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest - 103, // 121: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest - 105, // 122: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest - 107, // 123: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest - 108, // 124: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest - 109, // 125: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest - 113, // 126: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest - 116, // 127: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest - 121, // 128: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest - 123, // 129: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest - 125, // 130: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest - 127, // 131: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest - 130, // 132: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest - 132, // 133: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest - 134, // 134: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest - 136, // 135: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest - 138, // 136: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest - 143, // 137: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest - 145, // 138: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest - 147, // 139: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest - 149, // 140: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest - 151, // 141: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest - 153, // 142: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest - 155, // 143: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest - 157, // 144: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest - 160, // 145: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 160, // 146: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 160, // 147: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse - 1, // 148: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse - 5, // 149: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse - 8, // 150: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse - 12, // 151: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse - 15, // 152: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse - 17, // 153: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse - 19, // 154: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse - 21, // 155: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse - 24, // 156: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse - 26, // 157: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse - 28, // 158: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse - 40, // 159: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse - 42, // 160: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse - 46, // 161: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 46, // 162: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse - 46, // 163: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse - 48, // 164: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse - 50, // 165: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse - 54, // 166: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 54, // 167: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 54, // 168: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse - 56, // 169: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse - 58, // 170: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse - 64, // 171: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 64, // 172: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse - 64, // 173: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse - 60, // 174: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse - 67, // 175: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 67, // 176: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse - 69, // 177: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse - 71, // 178: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse - 73, // 179: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse - 76, // 180: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse - 78, // 181: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse - 81, // 182: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse - 83, // 183: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse - 85, // 184: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse - 87, // 185: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse - 90, // 186: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse - 93, // 187: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse - 96, // 188: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse - 99, // 189: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse - 102, // 190: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse - 104, // 191: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse - 106, // 192: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse - 110, // 193: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 110, // 194: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse - 111, // 195: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse - 114, // 196: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse - 117, // 197: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse - 122, // 198: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse - 124, // 199: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse - 126, // 200: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse - 128, // 201: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse - 131, // 202: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse - 133, // 203: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse - 135, // 204: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse - 137, // 205: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse - 139, // 206: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse - 144, // 207: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse - 146, // 208: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse - 148, // 209: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse - 150, // 210: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse - 152, // 211: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse - 154, // 212: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse - 156, // 213: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse - 158, // 214: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse - 145, // [145:215] is the sub-list for method output_type - 75, // [75:145] is the sub-list for method input_type - 75, // [75:75] is the sub-list for extension type_name - 75, // [75:75] is the sub-list for extension extendee - 0, // [0:75] is the sub-list for field type_name + 6, // 66: hyapp.wallet.v1.CreditRoomTurnoverRewardResponse.balance:type_name -> hyapp.wallet.v1.AssetBalance + 143, // 67: hyapp.wallet.v1.RedPacket.claims:type_name -> hyapp.wallet.v1.RedPacketClaim + 142, // 68: hyapp.wallet.v1.GetRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 142, // 69: hyapp.wallet.v1.UpdateRedPacketConfigResponse.config:type_name -> hyapp.wallet.v1.RedPacketConfig + 144, // 70: hyapp.wallet.v1.CreateRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 143, // 71: hyapp.wallet.v1.ClaimRedPacketResponse.claim:type_name -> hyapp.wallet.v1.RedPacketClaim + 144, // 72: hyapp.wallet.v1.ClaimRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 144, // 73: hyapp.wallet.v1.ListRedPacketsResponse.packets:type_name -> hyapp.wallet.v1.RedPacket + 144, // 74: hyapp.wallet.v1.GetRedPacketResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 144, // 75: hyapp.wallet.v1.RetryRedPacketRefundResponse.packet:type_name -> hyapp.wallet.v1.RedPacket + 161, // 76: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 161, // 77: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 161, // 78: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:input_type -> hyapp.wallet.v1.CronBatchRequest + 0, // 79: hyapp.wallet.v1.WalletService.DebitGift:input_type -> hyapp.wallet.v1.DebitGiftRequest + 3, // 80: hyapp.wallet.v1.WalletService.BatchDebitGift:input_type -> hyapp.wallet.v1.BatchDebitGiftRequest + 7, // 81: hyapp.wallet.v1.WalletService.GetBalances:input_type -> hyapp.wallet.v1.GetBalancesRequest + 11, // 82: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:input_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest + 14, // 83: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:input_type -> hyapp.wallet.v1.GetHostSalaryProgressRequest + 16, // 84: hyapp.wallet.v1.WalletService.AdminCreditAsset:input_type -> hyapp.wallet.v1.AdminCreditAssetRequest + 18, // 85: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:input_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockRequest + 20, // 86: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:input_type -> hyapp.wallet.v1.TransferCoinFromSellerRequest + 23, // 87: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:input_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest + 25, // 88: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:input_type -> hyapp.wallet.v1.ExchangeSalaryToCoinRequest + 27, // 89: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:input_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerRequest + 39, // 90: hyapp.wallet.v1.WalletService.ListResources:input_type -> hyapp.wallet.v1.ListResourcesRequest + 41, // 91: hyapp.wallet.v1.WalletService.GetResource:input_type -> hyapp.wallet.v1.GetResourceRequest + 43, // 92: hyapp.wallet.v1.WalletService.CreateResource:input_type -> hyapp.wallet.v1.CreateResourceRequest + 44, // 93: hyapp.wallet.v1.WalletService.UpdateResource:input_type -> hyapp.wallet.v1.UpdateResourceRequest + 45, // 94: hyapp.wallet.v1.WalletService.SetResourceStatus:input_type -> hyapp.wallet.v1.SetResourceStatusRequest + 47, // 95: hyapp.wallet.v1.WalletService.ListResourceGroups:input_type -> hyapp.wallet.v1.ListResourceGroupsRequest + 49, // 96: hyapp.wallet.v1.WalletService.GetResourceGroup:input_type -> hyapp.wallet.v1.GetResourceGroupRequest + 51, // 97: hyapp.wallet.v1.WalletService.CreateResourceGroup:input_type -> hyapp.wallet.v1.CreateResourceGroupRequest + 52, // 98: hyapp.wallet.v1.WalletService.UpdateResourceGroup:input_type -> hyapp.wallet.v1.UpdateResourceGroupRequest + 53, // 99: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:input_type -> hyapp.wallet.v1.SetResourceGroupStatusRequest + 55, // 100: hyapp.wallet.v1.WalletService.ListGiftConfigs:input_type -> hyapp.wallet.v1.ListGiftConfigsRequest + 57, // 101: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:input_type -> hyapp.wallet.v1.ListGiftTypeConfigsRequest + 61, // 102: hyapp.wallet.v1.WalletService.CreateGiftConfig:input_type -> hyapp.wallet.v1.CreateGiftConfigRequest + 62, // 103: hyapp.wallet.v1.WalletService.UpdateGiftConfig:input_type -> hyapp.wallet.v1.UpdateGiftConfigRequest + 63, // 104: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:input_type -> hyapp.wallet.v1.SetGiftConfigStatusRequest + 59, // 105: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:input_type -> hyapp.wallet.v1.UpsertGiftTypeConfigRequest + 65, // 106: hyapp.wallet.v1.WalletService.GrantResource:input_type -> hyapp.wallet.v1.GrantResourceRequest + 66, // 107: hyapp.wallet.v1.WalletService.GrantResourceGroup:input_type -> hyapp.wallet.v1.GrantResourceGroupRequest + 68, // 108: hyapp.wallet.v1.WalletService.ListUserResources:input_type -> hyapp.wallet.v1.ListUserResourcesRequest + 70, // 109: hyapp.wallet.v1.WalletService.EquipUserResource:input_type -> hyapp.wallet.v1.EquipUserResourceRequest + 72, // 110: hyapp.wallet.v1.WalletService.UnequipUserResource:input_type -> hyapp.wallet.v1.UnequipUserResourceRequest + 74, // 111: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:input_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest + 77, // 112: hyapp.wallet.v1.WalletService.ListResourceGrants:input_type -> hyapp.wallet.v1.ListResourceGrantsRequest + 80, // 113: hyapp.wallet.v1.WalletService.ListResourceShopItems:input_type -> hyapp.wallet.v1.ListResourceShopItemsRequest + 82, // 114: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:input_type -> hyapp.wallet.v1.UpsertResourceShopItemsRequest + 84, // 115: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:input_type -> hyapp.wallet.v1.SetResourceShopItemStatusRequest + 86, // 116: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:input_type -> hyapp.wallet.v1.PurchaseResourceShopItemRequest + 89, // 117: hyapp.wallet.v1.WalletService.ListRechargeBills:input_type -> hyapp.wallet.v1.ListRechargeBillsRequest + 92, // 118: hyapp.wallet.v1.WalletService.GetWalletOverview:input_type -> hyapp.wallet.v1.GetWalletOverviewRequest + 95, // 119: hyapp.wallet.v1.WalletService.GetWalletValueSummary:input_type -> hyapp.wallet.v1.GetWalletValueSummaryRequest + 98, // 120: hyapp.wallet.v1.WalletService.GetUserGiftWall:input_type -> hyapp.wallet.v1.GetUserGiftWallRequest + 101, // 121: hyapp.wallet.v1.WalletService.ListRechargeProducts:input_type -> hyapp.wallet.v1.ListRechargeProductsRequest + 103, // 122: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:input_type -> hyapp.wallet.v1.ConfirmGooglePaymentRequest + 105, // 123: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:input_type -> hyapp.wallet.v1.ListAdminRechargeProductsRequest + 107, // 124: hyapp.wallet.v1.WalletService.CreateRechargeProduct:input_type -> hyapp.wallet.v1.CreateRechargeProductRequest + 108, // 125: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:input_type -> hyapp.wallet.v1.UpdateRechargeProductRequest + 109, // 126: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:input_type -> hyapp.wallet.v1.DeleteRechargeProductRequest + 113, // 127: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:input_type -> hyapp.wallet.v1.GetDiamondExchangeConfigRequest + 116, // 128: hyapp.wallet.v1.WalletService.ListWalletTransactions:input_type -> hyapp.wallet.v1.ListWalletTransactionsRequest + 121, // 129: hyapp.wallet.v1.WalletService.ListVipPackages:input_type -> hyapp.wallet.v1.ListVipPackagesRequest + 123, // 130: hyapp.wallet.v1.WalletService.GetMyVip:input_type -> hyapp.wallet.v1.GetMyVipRequest + 125, // 131: hyapp.wallet.v1.WalletService.PurchaseVip:input_type -> hyapp.wallet.v1.PurchaseVipRequest + 127, // 132: hyapp.wallet.v1.WalletService.GrantVip:input_type -> hyapp.wallet.v1.GrantVipRequest + 130, // 133: hyapp.wallet.v1.WalletService.ListAdminVipLevels:input_type -> hyapp.wallet.v1.ListAdminVipLevelsRequest + 132, // 134: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:input_type -> hyapp.wallet.v1.UpdateAdminVipLevelsRequest + 134, // 135: hyapp.wallet.v1.WalletService.CreditTaskReward:input_type -> hyapp.wallet.v1.CreditTaskRewardRequest + 136, // 136: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:input_type -> hyapp.wallet.v1.CreditLuckyGiftRewardRequest + 138, // 137: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:input_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardRequest + 140, // 138: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:input_type -> hyapp.wallet.v1.ApplyGameCoinChangeRequest + 145, // 139: hyapp.wallet.v1.WalletService.GetRedPacketConfig:input_type -> hyapp.wallet.v1.GetRedPacketConfigRequest + 147, // 140: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:input_type -> hyapp.wallet.v1.UpdateRedPacketConfigRequest + 149, // 141: hyapp.wallet.v1.WalletService.CreateRedPacket:input_type -> hyapp.wallet.v1.CreateRedPacketRequest + 151, // 142: hyapp.wallet.v1.WalletService.ClaimRedPacket:input_type -> hyapp.wallet.v1.ClaimRedPacketRequest + 153, // 143: hyapp.wallet.v1.WalletService.ListRedPackets:input_type -> hyapp.wallet.v1.ListRedPacketsRequest + 155, // 144: hyapp.wallet.v1.WalletService.GetRedPacket:input_type -> hyapp.wallet.v1.GetRedPacketRequest + 157, // 145: hyapp.wallet.v1.WalletService.ExpireRedPackets:input_type -> hyapp.wallet.v1.ExpireRedPacketsRequest + 159, // 146: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:input_type -> hyapp.wallet.v1.RetryRedPacketRefundRequest + 162, // 147: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryDailySettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 162, // 148: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryHalfMonthSettlementBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 162, // 149: hyapp.wallet.v1.WalletCronService.ProcessHostSalaryMonthEndBatch:output_type -> hyapp.wallet.v1.CronBatchResponse + 1, // 150: hyapp.wallet.v1.WalletService.DebitGift:output_type -> hyapp.wallet.v1.DebitGiftResponse + 5, // 151: hyapp.wallet.v1.WalletService.BatchDebitGift:output_type -> hyapp.wallet.v1.BatchDebitGiftResponse + 8, // 152: hyapp.wallet.v1.WalletService.GetBalances:output_type -> hyapp.wallet.v1.GetBalancesResponse + 12, // 153: hyapp.wallet.v1.WalletService.GetActiveHostSalaryPolicy:output_type -> hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse + 15, // 154: hyapp.wallet.v1.WalletService.GetHostSalaryProgress:output_type -> hyapp.wallet.v1.GetHostSalaryProgressResponse + 17, // 155: hyapp.wallet.v1.WalletService.AdminCreditAsset:output_type -> hyapp.wallet.v1.AdminCreditAssetResponse + 19, // 156: hyapp.wallet.v1.WalletService.AdminCreditCoinSellerStock:output_type -> hyapp.wallet.v1.AdminCreditCoinSellerStockResponse + 21, // 157: hyapp.wallet.v1.WalletService.TransferCoinFromSeller:output_type -> hyapp.wallet.v1.TransferCoinFromSellerResponse + 24, // 158: hyapp.wallet.v1.WalletService.ListCoinSellerSalaryExchangeRateTiers:output_type -> hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse + 26, // 159: hyapp.wallet.v1.WalletService.ExchangeSalaryToCoin:output_type -> hyapp.wallet.v1.ExchangeSalaryToCoinResponse + 28, // 160: hyapp.wallet.v1.WalletService.TransferSalaryToCoinSeller:output_type -> hyapp.wallet.v1.TransferSalaryToCoinSellerResponse + 40, // 161: hyapp.wallet.v1.WalletService.ListResources:output_type -> hyapp.wallet.v1.ListResourcesResponse + 42, // 162: hyapp.wallet.v1.WalletService.GetResource:output_type -> hyapp.wallet.v1.GetResourceResponse + 46, // 163: hyapp.wallet.v1.WalletService.CreateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 46, // 164: hyapp.wallet.v1.WalletService.UpdateResource:output_type -> hyapp.wallet.v1.ResourceResponse + 46, // 165: hyapp.wallet.v1.WalletService.SetResourceStatus:output_type -> hyapp.wallet.v1.ResourceResponse + 48, // 166: hyapp.wallet.v1.WalletService.ListResourceGroups:output_type -> hyapp.wallet.v1.ListResourceGroupsResponse + 50, // 167: hyapp.wallet.v1.WalletService.GetResourceGroup:output_type -> hyapp.wallet.v1.GetResourceGroupResponse + 54, // 168: hyapp.wallet.v1.WalletService.CreateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 54, // 169: hyapp.wallet.v1.WalletService.UpdateResourceGroup:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 54, // 170: hyapp.wallet.v1.WalletService.SetResourceGroupStatus:output_type -> hyapp.wallet.v1.ResourceGroupResponse + 56, // 171: hyapp.wallet.v1.WalletService.ListGiftConfigs:output_type -> hyapp.wallet.v1.ListGiftConfigsResponse + 58, // 172: hyapp.wallet.v1.WalletService.ListGiftTypeConfigs:output_type -> hyapp.wallet.v1.ListGiftTypeConfigsResponse + 64, // 173: hyapp.wallet.v1.WalletService.CreateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 64, // 174: hyapp.wallet.v1.WalletService.UpdateGiftConfig:output_type -> hyapp.wallet.v1.GiftConfigResponse + 64, // 175: hyapp.wallet.v1.WalletService.SetGiftConfigStatus:output_type -> hyapp.wallet.v1.GiftConfigResponse + 60, // 176: hyapp.wallet.v1.WalletService.UpsertGiftTypeConfig:output_type -> hyapp.wallet.v1.GiftTypeConfigResponse + 67, // 177: hyapp.wallet.v1.WalletService.GrantResource:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 67, // 178: hyapp.wallet.v1.WalletService.GrantResourceGroup:output_type -> hyapp.wallet.v1.ResourceGrantResponse + 69, // 179: hyapp.wallet.v1.WalletService.ListUserResources:output_type -> hyapp.wallet.v1.ListUserResourcesResponse + 71, // 180: hyapp.wallet.v1.WalletService.EquipUserResource:output_type -> hyapp.wallet.v1.EquipUserResourceResponse + 73, // 181: hyapp.wallet.v1.WalletService.UnequipUserResource:output_type -> hyapp.wallet.v1.UnequipUserResourceResponse + 76, // 182: hyapp.wallet.v1.WalletService.BatchGetUserEquippedResources:output_type -> hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse + 78, // 183: hyapp.wallet.v1.WalletService.ListResourceGrants:output_type -> hyapp.wallet.v1.ListResourceGrantsResponse + 81, // 184: hyapp.wallet.v1.WalletService.ListResourceShopItems:output_type -> hyapp.wallet.v1.ListResourceShopItemsResponse + 83, // 185: hyapp.wallet.v1.WalletService.UpsertResourceShopItems:output_type -> hyapp.wallet.v1.UpsertResourceShopItemsResponse + 85, // 186: hyapp.wallet.v1.WalletService.SetResourceShopItemStatus:output_type -> hyapp.wallet.v1.ResourceShopItemResponse + 87, // 187: hyapp.wallet.v1.WalletService.PurchaseResourceShopItem:output_type -> hyapp.wallet.v1.PurchaseResourceShopItemResponse + 90, // 188: hyapp.wallet.v1.WalletService.ListRechargeBills:output_type -> hyapp.wallet.v1.ListRechargeBillsResponse + 93, // 189: hyapp.wallet.v1.WalletService.GetWalletOverview:output_type -> hyapp.wallet.v1.GetWalletOverviewResponse + 96, // 190: hyapp.wallet.v1.WalletService.GetWalletValueSummary:output_type -> hyapp.wallet.v1.GetWalletValueSummaryResponse + 99, // 191: hyapp.wallet.v1.WalletService.GetUserGiftWall:output_type -> hyapp.wallet.v1.GetUserGiftWallResponse + 102, // 192: hyapp.wallet.v1.WalletService.ListRechargeProducts:output_type -> hyapp.wallet.v1.ListRechargeProductsResponse + 104, // 193: hyapp.wallet.v1.WalletService.ConfirmGooglePayment:output_type -> hyapp.wallet.v1.ConfirmGooglePaymentResponse + 106, // 194: hyapp.wallet.v1.WalletService.ListAdminRechargeProducts:output_type -> hyapp.wallet.v1.ListAdminRechargeProductsResponse + 110, // 195: hyapp.wallet.v1.WalletService.CreateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 110, // 196: hyapp.wallet.v1.WalletService.UpdateRechargeProduct:output_type -> hyapp.wallet.v1.RechargeProductResponse + 111, // 197: hyapp.wallet.v1.WalletService.DeleteRechargeProduct:output_type -> hyapp.wallet.v1.DeleteRechargeProductResponse + 114, // 198: hyapp.wallet.v1.WalletService.GetDiamondExchangeConfig:output_type -> hyapp.wallet.v1.GetDiamondExchangeConfigResponse + 117, // 199: hyapp.wallet.v1.WalletService.ListWalletTransactions:output_type -> hyapp.wallet.v1.ListWalletTransactionsResponse + 122, // 200: hyapp.wallet.v1.WalletService.ListVipPackages:output_type -> hyapp.wallet.v1.ListVipPackagesResponse + 124, // 201: hyapp.wallet.v1.WalletService.GetMyVip:output_type -> hyapp.wallet.v1.GetMyVipResponse + 126, // 202: hyapp.wallet.v1.WalletService.PurchaseVip:output_type -> hyapp.wallet.v1.PurchaseVipResponse + 128, // 203: hyapp.wallet.v1.WalletService.GrantVip:output_type -> hyapp.wallet.v1.GrantVipResponse + 131, // 204: hyapp.wallet.v1.WalletService.ListAdminVipLevels:output_type -> hyapp.wallet.v1.ListAdminVipLevelsResponse + 133, // 205: hyapp.wallet.v1.WalletService.UpdateAdminVipLevels:output_type -> hyapp.wallet.v1.UpdateAdminVipLevelsResponse + 135, // 206: hyapp.wallet.v1.WalletService.CreditTaskReward:output_type -> hyapp.wallet.v1.CreditTaskRewardResponse + 137, // 207: hyapp.wallet.v1.WalletService.CreditLuckyGiftReward:output_type -> hyapp.wallet.v1.CreditLuckyGiftRewardResponse + 139, // 208: hyapp.wallet.v1.WalletService.CreditRoomTurnoverReward:output_type -> hyapp.wallet.v1.CreditRoomTurnoverRewardResponse + 141, // 209: hyapp.wallet.v1.WalletService.ApplyGameCoinChange:output_type -> hyapp.wallet.v1.ApplyGameCoinChangeResponse + 146, // 210: hyapp.wallet.v1.WalletService.GetRedPacketConfig:output_type -> hyapp.wallet.v1.GetRedPacketConfigResponse + 148, // 211: hyapp.wallet.v1.WalletService.UpdateRedPacketConfig:output_type -> hyapp.wallet.v1.UpdateRedPacketConfigResponse + 150, // 212: hyapp.wallet.v1.WalletService.CreateRedPacket:output_type -> hyapp.wallet.v1.CreateRedPacketResponse + 152, // 213: hyapp.wallet.v1.WalletService.ClaimRedPacket:output_type -> hyapp.wallet.v1.ClaimRedPacketResponse + 154, // 214: hyapp.wallet.v1.WalletService.ListRedPackets:output_type -> hyapp.wallet.v1.ListRedPacketsResponse + 156, // 215: hyapp.wallet.v1.WalletService.GetRedPacket:output_type -> hyapp.wallet.v1.GetRedPacketResponse + 158, // 216: hyapp.wallet.v1.WalletService.ExpireRedPackets:output_type -> hyapp.wallet.v1.ExpireRedPacketsResponse + 160, // 217: hyapp.wallet.v1.WalletService.RetryRedPacketRefund:output_type -> hyapp.wallet.v1.RetryRedPacketRefundResponse + 147, // [147:218] is the sub-list for method output_type + 76, // [76:147] is the sub-list for method input_type + 76, // [76:76] is the sub-list for extension type_name + 76, // [76:76] is the sub-list for extension extendee + 0, // [0:76] is the sub-list for field type_name } func init() { file_proto_wallet_v1_wallet_proto_init() } @@ -15954,7 +16183,7 @@ func file_proto_wallet_v1_wallet_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), NumEnums: 0, - NumMessages: 161, + NumMessages: 163, NumExtensions: 0, NumServices: 2, }, diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 4daa67e5..24e24c98 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -1345,6 +1345,30 @@ message CreditLuckyGiftRewardResponse { int64 granted_at_ms = 4; } +// CreditRoomTurnoverRewardRequest 是 activity-service 每周房间流水奖励结算后的金币入账命令。 +message CreditRoomTurnoverRewardRequest { + string command_id = 1; + string app_code = 2; + int64 target_user_id = 3; + int64 amount = 4; + string settlement_id = 5; + string room_id = 6; + int64 period_start_ms = 7; + int64 period_end_ms = 8; + int64 coin_spent = 9; + int64 tier_id = 10; + string tier_code = 11; + string reason = 12; +} + +// CreditRoomTurnoverRewardResponse 返回房间流水奖励入账流水和用户 COIN 账后余额。 +message CreditRoomTurnoverRewardResponse { + string transaction_id = 1; + AssetBalance balance = 2; + int64 amount = 3; + int64 granted_at_ms = 4; +} + // ApplyGameCoinChangeRequest 是 game-service 唯一可以调用的钱包游戏改账入口。 message ApplyGameCoinChangeRequest { string request_id = 1; @@ -1627,6 +1651,7 @@ service WalletService { rpc UpdateAdminVipLevels(UpdateAdminVipLevelsRequest) returns (UpdateAdminVipLevelsResponse); rpc CreditTaskReward(CreditTaskRewardRequest) returns (CreditTaskRewardResponse); rpc CreditLuckyGiftReward(CreditLuckyGiftRewardRequest) returns (CreditLuckyGiftRewardResponse); + rpc CreditRoomTurnoverReward(CreditRoomTurnoverRewardRequest) returns (CreditRoomTurnoverRewardResponse); rpc ApplyGameCoinChange(ApplyGameCoinChangeRequest) returns (ApplyGameCoinChangeResponse); rpc GetRedPacketConfig(GetRedPacketConfigRequest) returns (GetRedPacketConfigResponse); rpc UpdateRedPacketConfig(UpdateRedPacketConfigRequest) returns (UpdateRedPacketConfigResponse); diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index ad9fcccb..91ff44d8 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -259,6 +259,7 @@ const ( WalletService_UpdateAdminVipLevels_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateAdminVipLevels" WalletService_CreditTaskReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditTaskReward" WalletService_CreditLuckyGiftReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditLuckyGiftReward" + WalletService_CreditRoomTurnoverReward_FullMethodName = "/hyapp.wallet.v1.WalletService/CreditRoomTurnoverReward" WalletService_ApplyGameCoinChange_FullMethodName = "/hyapp.wallet.v1.WalletService/ApplyGameCoinChange" WalletService_GetRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/GetRedPacketConfig" WalletService_UpdateRedPacketConfig_FullMethodName = "/hyapp.wallet.v1.WalletService/UpdateRedPacketConfig" @@ -334,6 +335,7 @@ type WalletServiceClient interface { UpdateAdminVipLevels(ctx context.Context, in *UpdateAdminVipLevelsRequest, opts ...grpc.CallOption) (*UpdateAdminVipLevelsResponse, error) CreditTaskReward(ctx context.Context, in *CreditTaskRewardRequest, opts ...grpc.CallOption) (*CreditTaskRewardResponse, error) CreditLuckyGiftReward(ctx context.Context, in *CreditLuckyGiftRewardRequest, opts ...grpc.CallOption) (*CreditLuckyGiftRewardResponse, error) + CreditRoomTurnoverReward(ctx context.Context, in *CreditRoomTurnoverRewardRequest, opts ...grpc.CallOption) (*CreditRoomTurnoverRewardResponse, error) ApplyGameCoinChange(ctx context.Context, in *ApplyGameCoinChangeRequest, opts ...grpc.CallOption) (*ApplyGameCoinChangeResponse, error) GetRedPacketConfig(ctx context.Context, in *GetRedPacketConfigRequest, opts ...grpc.CallOption) (*GetRedPacketConfigResponse, error) UpdateRedPacketConfig(ctx context.Context, in *UpdateRedPacketConfigRequest, opts ...grpc.CallOption) (*UpdateRedPacketConfigResponse, error) @@ -933,6 +935,16 @@ func (c *walletServiceClient) CreditLuckyGiftReward(ctx context.Context, in *Cre return out, nil } +func (c *walletServiceClient) CreditRoomTurnoverReward(ctx context.Context, in *CreditRoomTurnoverRewardRequest, opts ...grpc.CallOption) (*CreditRoomTurnoverRewardResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(CreditRoomTurnoverRewardResponse) + err := c.cc.Invoke(ctx, WalletService_CreditRoomTurnoverReward_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *walletServiceClient) ApplyGameCoinChange(ctx context.Context, in *ApplyGameCoinChangeRequest, opts ...grpc.CallOption) (*ApplyGameCoinChangeResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ApplyGameCoinChangeResponse) @@ -1087,6 +1099,7 @@ type WalletServiceServer interface { UpdateAdminVipLevels(context.Context, *UpdateAdminVipLevelsRequest) (*UpdateAdminVipLevelsResponse, error) CreditTaskReward(context.Context, *CreditTaskRewardRequest) (*CreditTaskRewardResponse, error) CreditLuckyGiftReward(context.Context, *CreditLuckyGiftRewardRequest) (*CreditLuckyGiftRewardResponse, error) + CreditRoomTurnoverReward(context.Context, *CreditRoomTurnoverRewardRequest) (*CreditRoomTurnoverRewardResponse, error) ApplyGameCoinChange(context.Context, *ApplyGameCoinChangeRequest) (*ApplyGameCoinChangeResponse, error) GetRedPacketConfig(context.Context, *GetRedPacketConfigRequest) (*GetRedPacketConfigResponse, error) UpdateRedPacketConfig(context.Context, *UpdateRedPacketConfigRequest) (*UpdateRedPacketConfigResponse, error) @@ -1280,6 +1293,9 @@ func (UnimplementedWalletServiceServer) CreditTaskReward(context.Context, *Credi func (UnimplementedWalletServiceServer) CreditLuckyGiftReward(context.Context, *CreditLuckyGiftRewardRequest) (*CreditLuckyGiftRewardResponse, error) { return nil, status.Error(codes.Unimplemented, "method CreditLuckyGiftReward not implemented") } +func (UnimplementedWalletServiceServer) CreditRoomTurnoverReward(context.Context, *CreditRoomTurnoverRewardRequest) (*CreditRoomTurnoverRewardResponse, error) { + return nil, status.Error(codes.Unimplemented, "method CreditRoomTurnoverReward not implemented") +} func (UnimplementedWalletServiceServer) ApplyGameCoinChange(context.Context, *ApplyGameCoinChangeRequest) (*ApplyGameCoinChangeResponse, error) { return nil, status.Error(codes.Unimplemented, "method ApplyGameCoinChange not implemented") } @@ -2372,6 +2388,24 @@ func _WalletService_CreditLuckyGiftReward_Handler(srv interface{}, ctx context.C return interceptor(ctx, in, info, handler) } +func _WalletService_CreditRoomTurnoverReward_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreditRoomTurnoverRewardRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WalletServiceServer).CreditRoomTurnoverReward(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: WalletService_CreditRoomTurnoverReward_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WalletServiceServer).CreditRoomTurnoverReward(ctx, req.(*CreditRoomTurnoverRewardRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WalletService_ApplyGameCoinChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ApplyGameCoinChangeRequest) if err := dec(in); err != nil { @@ -2773,6 +2807,10 @@ var WalletService_ServiceDesc = grpc.ServiceDesc{ MethodName: "CreditLuckyGiftReward", Handler: _WalletService_CreditLuckyGiftReward_Handler, }, + { + MethodName: "CreditRoomTurnoverReward", + Handler: _WalletService_CreditRoomTurnoverReward_Handler, + }, { MethodName: "ApplyGameCoinChange", Handler: _WalletService_ApplyGameCoinChange_Handler, diff --git a/server/admin/cmd/server/main.go b/server/admin/cmd/server/main.go index 634a9051..31654d26 100644 --- a/server/admin/cmd/server/main.go +++ b/server/admin/cmd/server/main.go @@ -32,6 +32,7 @@ import ( authmodule "hyapp-admin-server/internal/modules/auth" coinledgermodule "hyapp-admin-server/internal/modules/coinledger" countryregionmodule "hyapp-admin-server/internal/modules/countryregion" + cumulativerechargerewardmodule "hyapp-admin-server/internal/modules/cumulativerechargereward" dailytaskmodule "hyapp-admin-server/internal/modules/dailytask" dashboardmodule "hyapp-admin-server/internal/modules/dashboard" firstrechargerewardmodule "hyapp-admin-server/internal/modules/firstrechargereward" @@ -54,6 +55,7 @@ import ( resourcemodule "hyapp-admin-server/internal/modules/resource" roomadminmodule "hyapp-admin-server/internal/modules/roomadmin" roomrocketmodule "hyapp-admin-server/internal/modules/roomrocket" + roomturnoverrewardmodule "hyapp-admin-server/internal/modules/roomturnoverreward" searchmodule "hyapp-admin-server/internal/modules/search" sevendaycheckinmodule "hyapp-admin-server/internal/modules/sevendaycheckin" teamsalarypolicymodule "hyapp-admin-server/internal/modules/teamsalarypolicy" @@ -61,6 +63,7 @@ import ( uploadmodule "hyapp-admin-server/internal/modules/upload" userleaderboardmodule "hyapp-admin-server/internal/modules/userleaderboard" vipconfigmodule "hyapp-admin-server/internal/modules/vipconfig" + weeklystarmodule "hyapp-admin-server/internal/modules/weeklystar" "hyapp-admin-server/internal/platform/logging" "hyapp-admin-server/internal/platform/tencentcos" "hyapp-admin-server/internal/repository" @@ -227,6 +230,7 @@ func main() { 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), + CumulativeRecharge: cumulativerechargerewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), DailyTask: dailytaskmodule.New(activityclient.NewGRPC(activityConn), auditHandler), Dashboard: dashboardmodule.New(store, cfg), FirstRechargeReward: firstrechargerewardmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), @@ -249,6 +253,7 @@ func main() { Resource: resourcemodule.New(walletclient.NewGRPC(walletConn), store, userDB, cfg.WalletService.RequestTimeout, auditHandler), RoomAdmin: roomadminmodule.New(userDB, roomClient, auditHandler), RoomRocket: roomrocketmodule.New(roomClient, auditHandler), + RoomTurnoverReward: roomturnoverrewardmodule.New(activityclient.NewGRPC(activityConn), auditHandler), Search: searchmodule.New(store), SevenDayCheckIn: sevendaycheckinmodule.New(activityclient.NewGRPC(activityConn), userDB, auditHandler), TeamSalaryPolicy: teamsalarypolicymodule.New(store, auditHandler), @@ -256,6 +261,7 @@ func main() { Upload: uploadmodule.New(objectUploader, cfg.TencentCOS.ObjectPrefix, auditHandler), UserLeaderboard: userleaderboardmodule.New(walletDB, userDB, roomClient), VIPConfig: vipconfigmodule.New(walletclient.NewGRPC(walletConn), auditHandler), + WeeklyStar: weeklystarmodule.New(activityclient.NewGRPC(activityConn), auditHandler), } 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 b1dfe2d7..35d37b21 100644 --- a/server/admin/internal/integration/activityclient/client.go +++ b/server/admin/internal/integration/activityclient/client.go @@ -21,9 +21,23 @@ type Client interface { 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) + GetCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardConfigRequest) (*activityv1.GetCumulativeRechargeRewardConfigResponse, error) + UpdateCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateCumulativeRechargeRewardConfigRequest) (*activityv1.UpdateCumulativeRechargeRewardConfigResponse, error) + ListCumulativeRechargeRewardGrants(ctx context.Context, req *activityv1.ListCumulativeRechargeRewardGrantsRequest) (*activityv1.ListCumulativeRechargeRewardGrantsResponse, 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) + GetRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.GetRoomTurnoverRewardConfigRequest) (*activityv1.GetRoomTurnoverRewardConfigResponse, error) + UpdateRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.UpdateRoomTurnoverRewardConfigRequest) (*activityv1.UpdateRoomTurnoverRewardConfigResponse, error) + ListRoomTurnoverRewardSettlements(ctx context.Context, req *activityv1.ListRoomTurnoverRewardSettlementsRequest) (*activityv1.ListRoomTurnoverRewardSettlementsResponse, error) + RetryRoomTurnoverRewardSettlement(ctx context.Context, req *activityv1.RetryRoomTurnoverRewardSettlementRequest) (*activityv1.RetryRoomTurnoverRewardSettlementResponse, error) + ListWeeklyStarCycles(ctx context.Context, req *activityv1.ListWeeklyStarCyclesRequest) (*activityv1.ListWeeklyStarCyclesResponse, error) + CreateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) + GetWeeklyStarCycle(ctx context.Context, req *activityv1.GetWeeklyStarCycleRequest) (*activityv1.GetWeeklyStarCycleResponse, error) + UpdateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) + SetWeeklyStarCycleStatus(ctx context.Context, req *activityv1.SetWeeklyStarCycleStatusRequest) (*activityv1.SetWeeklyStarCycleStatusResponse, error) + ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarSettlements(ctx context.Context, req *activityv1.ListWeeklyStarSettlementsRequest) (*activityv1.ListWeeklyStarSettlementsResponse, error) GetLuckyGiftConfig(ctx context.Context, req *activityv1.GetLuckyGiftConfigRequest) (*activityv1.GetLuckyGiftConfigResponse, error) UpsertLuckyGiftConfig(ctx context.Context, req *activityv1.UpsertLuckyGiftConfigRequest) (*activityv1.UpsertLuckyGiftConfigResponse, error) ListLuckyGiftConfigs(ctx context.Context, req *activityv1.ListLuckyGiftConfigsRequest) (*activityv1.ListLuckyGiftConfigsResponse, error) @@ -41,7 +55,10 @@ type GRPCClient struct { achievementClient activityv1.AdminAchievementServiceClient registrationRewardClient activityv1.AdminRegistrationRewardServiceClient firstRechargeRewardClient activityv1.AdminFirstRechargeRewardServiceClient + cumulativeRechargeClient activityv1.AdminCumulativeRechargeRewardServiceClient sevenDayCheckInClient activityv1.AdminSevenDayCheckInServiceClient + roomTurnoverRewardClient activityv1.AdminRoomTurnoverRewardServiceClient + weeklyStarClient activityv1.AdminWeeklyStarServiceClient luckyGiftClient activityv1.AdminLuckyGiftServiceClient broadcastClient activityv1.BroadcastServiceClient growthClient activityv1.AdminGrowthLevelServiceClient @@ -53,7 +70,10 @@ func NewGRPC(conn grpc.ClientConnInterface) *GRPCClient { achievementClient: activityv1.NewAdminAchievementServiceClient(conn), registrationRewardClient: activityv1.NewAdminRegistrationRewardServiceClient(conn), firstRechargeRewardClient: activityv1.NewAdminFirstRechargeRewardServiceClient(conn), + cumulativeRechargeClient: activityv1.NewAdminCumulativeRechargeRewardServiceClient(conn), sevenDayCheckInClient: activityv1.NewAdminSevenDayCheckInServiceClient(conn), + roomTurnoverRewardClient: activityv1.NewAdminRoomTurnoverRewardServiceClient(conn), + weeklyStarClient: activityv1.NewAdminWeeklyStarServiceClient(conn), luckyGiftClient: activityv1.NewAdminLuckyGiftServiceClient(conn), broadcastClient: activityv1.NewBroadcastServiceClient(conn), growthClient: activityv1.NewAdminGrowthLevelServiceClient(conn), @@ -104,6 +124,18 @@ func (c *GRPCClient) ListFirstRechargeRewardClaims(ctx context.Context, req *act return c.firstRechargeRewardClient.ListFirstRechargeRewardClaims(ctx, req) } +func (c *GRPCClient) GetCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardConfigRequest) (*activityv1.GetCumulativeRechargeRewardConfigResponse, error) { + return c.cumulativeRechargeClient.GetCumulativeRechargeRewardConfig(ctx, req) +} + +func (c *GRPCClient) UpdateCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateCumulativeRechargeRewardConfigRequest) (*activityv1.UpdateCumulativeRechargeRewardConfigResponse, error) { + return c.cumulativeRechargeClient.UpdateCumulativeRechargeRewardConfig(ctx, req) +} + +func (c *GRPCClient) ListCumulativeRechargeRewardGrants(ctx context.Context, req *activityv1.ListCumulativeRechargeRewardGrantsRequest) (*activityv1.ListCumulativeRechargeRewardGrantsResponse, error) { + return c.cumulativeRechargeClient.ListCumulativeRechargeRewardGrants(ctx, req) +} + func (c *GRPCClient) GetSevenDayCheckInConfig(ctx context.Context, req *activityv1.GetSevenDayCheckInConfigRequest) (*activityv1.GetSevenDayCheckInConfigResponse, error) { return c.sevenDayCheckInClient.GetSevenDayCheckInConfig(ctx, req) } @@ -116,6 +148,50 @@ func (c *GRPCClient) ListSevenDayCheckInClaims(ctx context.Context, req *activit return c.sevenDayCheckInClient.ListSevenDayCheckInClaims(ctx, req) } +func (c *GRPCClient) GetRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.GetRoomTurnoverRewardConfigRequest) (*activityv1.GetRoomTurnoverRewardConfigResponse, error) { + return c.roomTurnoverRewardClient.GetRoomTurnoverRewardConfig(ctx, req) +} + +func (c *GRPCClient) UpdateRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.UpdateRoomTurnoverRewardConfigRequest) (*activityv1.UpdateRoomTurnoverRewardConfigResponse, error) { + return c.roomTurnoverRewardClient.UpdateRoomTurnoverRewardConfig(ctx, req) +} + +func (c *GRPCClient) ListRoomTurnoverRewardSettlements(ctx context.Context, req *activityv1.ListRoomTurnoverRewardSettlementsRequest) (*activityv1.ListRoomTurnoverRewardSettlementsResponse, error) { + return c.roomTurnoverRewardClient.ListRoomTurnoverRewardSettlements(ctx, req) +} + +func (c *GRPCClient) RetryRoomTurnoverRewardSettlement(ctx context.Context, req *activityv1.RetryRoomTurnoverRewardSettlementRequest) (*activityv1.RetryRoomTurnoverRewardSettlementResponse, error) { + return c.roomTurnoverRewardClient.RetryRoomTurnoverRewardSettlement(ctx, req) +} + +func (c *GRPCClient) ListWeeklyStarCycles(ctx context.Context, req *activityv1.ListWeeklyStarCyclesRequest) (*activityv1.ListWeeklyStarCyclesResponse, error) { + return c.weeklyStarClient.ListWeeklyStarCycles(ctx, req) +} + +func (c *GRPCClient) CreateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) { + return c.weeklyStarClient.CreateWeeklyStarCycle(ctx, req) +} + +func (c *GRPCClient) GetWeeklyStarCycle(ctx context.Context, req *activityv1.GetWeeklyStarCycleRequest) (*activityv1.GetWeeklyStarCycleResponse, error) { + return c.weeklyStarClient.GetWeeklyStarCycle(ctx, req) +} + +func (c *GRPCClient) UpdateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) { + return c.weeklyStarClient.UpdateWeeklyStarCycle(ctx, req) +} + +func (c *GRPCClient) SetWeeklyStarCycleStatus(ctx context.Context, req *activityv1.SetWeeklyStarCycleStatusRequest) (*activityv1.SetWeeklyStarCycleStatusResponse, error) { + return c.weeklyStarClient.SetWeeklyStarCycleStatus(ctx, req) +} + +func (c *GRPCClient) ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) { + return c.weeklyStarClient.ListWeeklyStarLeaderboard(ctx, req) +} + +func (c *GRPCClient) ListWeeklyStarSettlements(ctx context.Context, req *activityv1.ListWeeklyStarSettlementsRequest) (*activityv1.ListWeeklyStarSettlementsResponse, error) { + return c.weeklyStarClient.ListWeeklyStarSettlements(ctx, req) +} + func (c *GRPCClient) GetLuckyGiftConfig(ctx context.Context, req *activityv1.GetLuckyGiftConfigRequest) (*activityv1.GetLuckyGiftConfigResponse, error) { return c.luckyGiftClient.GetLuckyGiftConfig(ctx, req) } diff --git a/server/admin/internal/integration/userclient/client.go b/server/admin/internal/integration/userclient/client.go index 958e16f1..aef89d21 100644 --- a/server/admin/internal/integration/userclient/client.go +++ b/server/admin/internal/integration/userclient/client.go @@ -393,7 +393,7 @@ type BDProfile struct { ParentLeaderUserID int64 `json:"parentLeaderUserId,string"` PositionAlias string `json:"positionAlias"` Status string `json:"status"` - CreatedByUserID int64 `json:"createdByUserId"` + CreatedByUserID int64 `json:"createdByUserId,string"` CreatedAtMs int64 `json:"createdAtMs"` UpdatedAtMs int64 `json:"updatedAtMs"` DisplayUserID string `json:"displayUserId"` @@ -410,7 +410,7 @@ type BDProfile struct { } type Agency struct { - AgencyID int64 `json:"agencyId"` + AgencyID int64 `json:"agencyId,string"` OwnerUserID int64 `json:"ownerUserId,string"` RegionID int64 `json:"regionId"` ParentBDUserID int64 `json:"parentBdUserId,string"` @@ -418,7 +418,7 @@ type Agency struct { Status string `json:"status"` JoinEnabled bool `json:"joinEnabled"` MaxHosts int32 `json:"maxHosts"` - CreatedByUserID int64 `json:"createdByUserId"` + CreatedByUserID int64 `json:"createdByUserId,string"` CreatedAtMs int64 `json:"createdAtMs"` UpdatedAtMs int64 `json:"updatedAtMs"` OwnerDisplayUserID string `json:"ownerDisplayUserId"` @@ -434,8 +434,8 @@ type HostProfile struct { UserID int64 `json:"userId,string"` Status string `json:"status"` RegionID int64 `json:"regionId"` - CurrentAgencyID int64 `json:"currentAgencyId"` - CurrentMembershipID int64 `json:"currentMembershipId"` + CurrentAgencyID int64 `json:"currentAgencyId,string"` + CurrentMembershipID int64 `json:"currentMembershipId,string"` Source string `json:"source"` FirstBecameHostAtMs int64 `json:"firstBecameHostAtMs"` CreatedAtMs int64 `json:"createdAtMs"` @@ -456,14 +456,14 @@ type CoinSellerProfile struct { UserID int64 `json:"userId,string"` Status string `json:"status"` MerchantAssetType string `json:"merchantAssetType"` - CreatedByUserID int64 `json:"createdByUserId"` + CreatedByUserID int64 `json:"createdByUserId,string"` CreatedAtMs int64 `json:"createdAtMs"` UpdatedAtMs int64 `json:"updatedAtMs"` } type AgencyMembership struct { - MembershipID int64 `json:"membershipId"` - AgencyID int64 `json:"agencyId"` + MembershipID int64 `json:"membershipId,string"` + AgencyID int64 `json:"agencyId,string"` HostUserID int64 `json:"hostUserId,string"` RegionID int64 `json:"regionId"` MembershipType string `json:"membershipType"` diff --git a/server/admin/internal/integration/userclient/client_test.go b/server/admin/internal/integration/userclient/client_test.go new file mode 100644 index 00000000..e1f7309c --- /dev/null +++ b/server/admin/internal/integration/userclient/client_test.go @@ -0,0 +1,34 @@ +package userclient + +import ( + "encoding/json" + "strings" + "testing" +) + +func TestAgencyJSONKeepsSnowflakeIDsAsStrings(t *testing.T) { + agency := Agency{ + AgencyID: 321170072154411009, + OwnerUserID: 316033326332776448, + ParentBDUserID: 320470609978986496, + CreatedByUserID: 320470609978986496, + } + + payload, err := json.Marshal(agency) + if err != nil { + t.Fatalf("marshal agency: %v", err) + } + body := string(payload) + + // 后台前端运行在浏览器里,雪花 ID 超过 JavaScript 安全整数上限;这里必须以字符串返回,避免 321170072154411009 被解析成 321170072154411000 后再提交给删除接口。 + for _, want := range []string{ + `"agencyId":"321170072154411009"`, + `"ownerUserId":"316033326332776448"`, + `"parentBdUserId":"320470609978986496"`, + `"createdByUserId":"320470609978986496"`, + } { + if !strings.Contains(body, want) { + t.Fatalf("agency json should contain %s, got %s", want, body) + } + } +} diff --git a/server/admin/internal/modules/appuser/handler.go b/server/admin/internal/modules/appuser/handler.go index 9aaa38a7..708e4746 100644 --- a/server/admin/internal/modules/appuser/handler.go +++ b/server/admin/internal/modules/appuser/handler.go @@ -154,13 +154,19 @@ func (h *Handler) setUserStatus(c *gin.Context, status string, action string, su func parseListQuery(c *gin.Context) listQuery { options := shared.ListOptions(c) + regionID, regionIDSet := queryOptionalInt64(c, "region_id", "regionId") return normalizeListQuery(listQuery{ Page: options.Page, PageSize: options.PageSize, + Country: firstQuery(c, "country", "country_code", "countryCode"), Keyword: options.Keyword, + RegionID: regionID, + RegionIDSet: regionIDSet, Status: options.Status, SortBy: firstQuery(c, "sort_by", "sortBy"), SortDirection: firstQuery(c, "sort_direction", "sortDirection", "order"), + StartMs: queryInt64(c, "start_ms", "startMs", "start_at_ms", "startAtMs"), + EndMs: queryInt64(c, "end_ms", "endMs", "end_at_ms", "endAtMs"), }) } diff --git a/server/admin/internal/modules/appuser/request.go b/server/admin/internal/modules/appuser/request.go index f87e9aca..cf75fa14 100644 --- a/server/admin/internal/modules/appuser/request.go +++ b/server/admin/internal/modules/appuser/request.go @@ -3,10 +3,15 @@ package appuser type listQuery struct { Page int PageSize int + Country string Keyword string + RegionID int64 + RegionIDSet bool Status string SortBy string SortDirection string + StartMs int64 + EndMs int64 } type loginLogQuery struct { diff --git a/server/admin/internal/modules/appuser/service.go b/server/admin/internal/modules/appuser/service.go index 42e2def1..fac2f31d 100644 --- a/server/admin/internal/modules/appuser/service.go +++ b/server/admin/internal/modules/appuser/service.go @@ -73,17 +73,7 @@ func (s *Service) ListUsers(ctx context.Context, query listQuery) ([]AppUser, in } query = normalizeListQuery(query) appCode := appctx.FromContext(ctx) - whereSQL := "FROM users u WHERE u.app_code = ?" - args := []any{appCode} - if query.Status != "" { - whereSQL += " AND u.status = ?" - args = append(args, query.Status) - } - if query.Keyword != "" { - like := "%" + query.Keyword + "%" - whereSQL += " AND (CAST(u.user_id AS CHAR) LIKE ? OR u.current_display_user_id LIKE ? OR u.username LIKE ?)" - args = append(args, like, like, like) - } + whereSQL, args := appUserListWhereSQL(appCode, query) total, err := countRows(ctx, s.userDB, whereSQL, args...) if err != nil { @@ -562,13 +552,73 @@ func normalizeListQuery(query listQuery) listQuery { if query.PageSize > 100 { query.PageSize = 100 } + query.Country = normalizeCountryCode(query.Country) query.Keyword = strings.TrimSpace(query.Keyword) + if query.RegionID < 0 { + query.RegionID = 0 + query.RegionIDSet = false + } + if query.StartMs < 0 { + query.StartMs = 0 + } + if query.EndMs < 0 { + query.EndMs = 0 + } query.Status = strings.ToLower(strings.TrimSpace(query.Status)) query.SortBy = normalizeAppUserSortBy(query.SortBy) query.SortDirection = normalizeSortDirection(query.SortDirection) return query } +func appUserListWhereSQL(appCode string, query listQuery) (string, []any) { + whereSQL := "FROM users u WHERE u.app_code = ?" + args := []any{appCode} + if query.Status != "" { + whereSQL += " AND u.status = ?" + args = append(args, query.Status) + } + if query.Keyword != "" { + like := "%" + query.Keyword + "%" + whereSQL += " AND (CAST(u.user_id AS CHAR) LIKE ? OR u.current_display_user_id LIKE ? OR u.username LIKE ?)" + args = append(args, like, like, like) + } + if query.Country != "" { + // 国家筛选用 users.country 的 ISO code 精确命中;前端传展示名时不会被猜测转换,避免误筛到错误国家。 + whereSQL += " AND UPPER(u.country) = ?" + args = append(args, query.Country) + } + if query.RegionIDSet { + if query.RegionID == 0 { + // 列表展示里无区域或无有效业务区域都会显示为 GLOBAL;筛选 GLOBAL 时保持同一套展示口径。 + whereSQL += " AND (COALESCE(u.region_id, 0) = 0 OR NOT " + appUserValidRegionExistsSQL("u") + ")" + } else { + whereSQL += " AND u.region_id = ?" + args = append(args, query.RegionID) + } + } + if query.StartMs > 0 { + // 时间区间筛选的是用户创建时间,和列表“创建 / 活跃”列的第一行保持一致。 + whereSQL += " AND u.created_at_ms >= ?" + args = append(args, query.StartMs) + } + if query.EndMs > 0 { + whereSQL += " AND u.created_at_ms < ?" + args = append(args, query.EndMs) + } + return whereSQL, args +} + +func appUserValidRegionExistsSQL(userAlias string) string { + return fmt.Sprintf(`EXISTS ( + SELECT 1 FROM regions rg + WHERE rg.app_code = %[1]s.app_code + AND rg.region_id = %[1]s.region_id + AND rg.status = 'active' + AND rg.region_code NOT IN ('Australia and New Zealand', 'Caribbean', 'Melanesia', 'Micronesia', 'Polynesia', 'Southern Africa', 'UNSPECIFIED') + LIMIT 1 + )`, userAlias) +} + func normalizeAppUserSortBy(value string) string { switch strings.ToLower(strings.TrimSpace(value)) { case "coin", "coins": diff --git a/server/admin/internal/modules/appuser/service_test.go b/server/admin/internal/modules/appuser/service_test.go index 8f68b1cc..070f222b 100644 --- a/server/admin/internal/modules/appuser/service_test.go +++ b/server/admin/internal/modules/appuser/service_test.go @@ -1,6 +1,9 @@ package appuser -import "testing" +import ( + "strings" + "testing" +) func TestNormalizeListQuerySort(t *testing.T) { query := normalizeListQuery(listQuery{Page: 0, PageSize: 1000, SortBy: "coins", SortDirection: "asc"}) @@ -12,6 +15,46 @@ func TestNormalizeListQuerySort(t *testing.T) { if query.SortBy != "created_at" || query.SortDirection != "desc" { t.Fatalf("created sort default mismatch: %+v", query) } + + query = normalizeListQuery(listQuery{Country: " ph ", RegionID: -3, RegionIDSet: true, StartMs: -1, EndMs: -2}) + if query.Country != "PH" || query.RegionIDSet || query.StartMs != 0 || query.EndMs != 0 { + t.Fatalf("filter normalization mismatch: %+v", query) + } +} + +func TestAppUserListWhereSQLFilters(t *testing.T) { + whereSQL, args := appUserListWhereSQL("lalu", normalizeListQuery(listQuery{ + Country: "ph", + Keyword: "hunter", + RegionID: 3, + RegionIDSet: true, + StartMs: 1000, + EndMs: 2000, + Status: "active", + })) + for _, want := range []string{ + "u.status = ?", + "CAST(u.user_id AS CHAR) LIKE ?", + "UPPER(u.country) = ?", + "u.region_id = ?", + "u.created_at_ms >= ?", + "u.created_at_ms < ?", + } { + if !strings.Contains(whereSQL, want) { + t.Fatalf("where sql missing %q: %s", want, whereSQL) + } + } + if len(args) != 9 || args[0] != "lalu" || args[5] != "PH" || args[6] != int64(3) || args[7] != int64(1000) || args[8] != int64(2000) { + t.Fatalf("where args mismatch: %+v", args) + } + + whereSQL, args = appUserListWhereSQL("lalu", normalizeListQuery(listQuery{RegionID: 0, RegionIDSet: true})) + if !strings.Contains(whereSQL, "COALESCE(u.region_id, 0) = 0") || !strings.Contains(whereSQL, "NOT EXISTS") { + t.Fatalf("global region sql mismatch: %s", whereSQL) + } + if len(args) != 1 || args[0] != "lalu" { + t.Fatalf("global region args mismatch: %+v", args) + } } func TestAppUserOrderSQL(t *testing.T) { diff --git a/server/admin/internal/modules/coinledger/dto.go b/server/admin/internal/modules/coinledger/dto.go index 6d0629c2..a8c97240 100644 --- a/server/admin/internal/modules/coinledger/dto.go +++ b/server/admin/internal/modules/coinledger/dto.go @@ -7,6 +7,12 @@ type coinLedgerUserDTO struct { Avatar string `json:"avatar"` } +type CSVExport struct { + FileName string + Content []byte + Count int +} + type coinLedgerEntryDTO struct { EntryID int64 `json:"entryId"` TransactionID string `json:"transactionId"` @@ -26,20 +32,22 @@ type coinLedgerEntryDTO struct { } type coinSellerLedgerDTO struct { - EntryID int64 `json:"entryId"` - TransactionID string `json:"transactionId"` - CommandID string `json:"commandId"` - LedgerType string `json:"ledgerType"` - BizType string `json:"bizType"` - Seller coinLedgerUserDTO `json:"seller"` - Receiver coinLedgerUserDTO `json:"receiver"` - Amount int64 `json:"amount"` - Direction string `json:"direction"` - AvailableDelta int64 `json:"availableDelta"` - SellerBalanceAfter int64 `json:"sellerBalanceAfter"` - CounterpartyUserID string `json:"counterpartyUserId"` - Metadata map[string]any `json:"metadata"` - CreatedAtMS int64 `json:"createdAtMs"` + EntryID int64 `json:"entryId"` + TransactionID string `json:"transactionId"` + CommandID string `json:"commandId"` + LedgerType string `json:"ledgerType"` + BizType string `json:"bizType"` + Seller coinLedgerUserDTO `json:"seller"` + Receiver coinLedgerUserDTO `json:"receiver"` + Amount int64 `json:"amount"` + Direction string `json:"direction"` + AvailableDelta int64 `json:"availableDelta"` + SellerBalanceAfter int64 `json:"sellerBalanceAfter"` + CounterpartyUserID string `json:"counterpartyUserId"` + OperatorUserID string `json:"operatorUserId"` + Operator coinAdjustmentOperatorDTO `json:"operator"` + Metadata map[string]any `json:"metadata"` + CreatedAtMS int64 `json:"createdAtMs"` } type coinAdjustmentOperatorDTO struct { diff --git a/server/admin/internal/modules/coinledger/handler.go b/server/admin/internal/modules/coinledger/handler.go index 75231536..ac21d6aa 100644 --- a/server/admin/internal/modules/coinledger/handler.go +++ b/server/admin/internal/modules/coinledger/handler.go @@ -55,6 +55,28 @@ func (h *Handler) ListCoinSellerLedger(c *gin.Context) { response.OK(c, response.Page{Items: items, Page: query.Page, PageSize: query.PageSize, Total: total}) } +func (h *Handler) ExportCoinSellerLedger(c *gin.Context) { + query, ok := parseCoinSellerLedgerQuery(c) + if !ok { + return + } + export, err := h.service.ExportCoinSellerLedger(c.Request.Context(), appctx.FromContext(c.Request.Context()), query) + if err != nil { + if errors.Is(err, errInvalidCoinSellerLedgerType) { + response.BadRequest(c, "流水类型不正确") + return + } + response.ServerError(c, "导出币商流水失败") + return + } + + shared.OperationLog(c, h.audit, "export-coin-seller-ledger", "wallet_entries", "success", fmt.Sprintf("%d entries", export.Count)) + c.Header("Content-Disposition", "attachment; filename="+export.FileName) + c.Header("Content-Type", "text/csv; charset=utf-8") + c.Writer.WriteHeader(200) + _, _ = c.Writer.Write(export.Content) +} + func (h *Handler) ListCoinAdjustments(c *gin.Context) { query, ok := parseListQuery(c) if !ok { diff --git a/server/admin/internal/modules/coinledger/routes.go b/server/admin/internal/modules/coinledger/routes.go index 7ce439be..1b05a107 100644 --- a/server/admin/internal/modules/coinledger/routes.go +++ b/server/admin/internal/modules/coinledger/routes.go @@ -13,6 +13,7 @@ func RegisterRoutes(protected *gin.RouterGroup, h *Handler) { protected.GET("/admin/operations/coin-ledger", middleware.RequirePermission("coin-ledger:view"), h.ListCoinLedger) protected.GET("/admin/operations/coin-seller-ledger", middleware.RequirePermission("coin-seller-ledger:view"), h.ListCoinSellerLedger) + protected.GET("/admin/operations/coin-seller-ledger/export", middleware.RequirePermission("coin-seller-ledger:view"), h.ExportCoinSellerLedger) protected.GET("/admin/operations/coin-adjustments", middleware.RequirePermission("coin-adjustment:view"), h.ListCoinAdjustments) protected.GET("/admin/operations/coin-adjustments/target", middleware.RequirePermission("coin-adjustment:create"), h.LookupCoinAdjustmentTarget) protected.POST("/admin/operations/coin-adjustments", middleware.RequirePermission("coin-adjustment:create"), h.CreateCoinAdjustment) diff --git a/server/admin/internal/modules/coinledger/service.go b/server/admin/internal/modules/coinledger/service.go index a8731ec8..8e44247b 100644 --- a/server/admin/internal/modules/coinledger/service.go +++ b/server/admin/internal/modules/coinledger/service.go @@ -1,8 +1,10 @@ package coinledger import ( + "bytes" "context" "database/sql" + "encoding/csv" "encoding/json" "errors" "fmt" @@ -154,6 +156,41 @@ func (s *Service) ListCoinLedger(ctx context.Context, appCode string, query list } func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, query coinSellerLedgerQuery) ([]coinSellerLedgerDTO, int64, error) { + return s.listCoinSellerLedger(ctx, appCode, query, true) +} + +func (s *Service) ExportCoinSellerLedger(ctx context.Context, appCode string, query coinSellerLedgerQuery) (CSVExport, error) { + items, total, err := s.listCoinSellerLedger(ctx, appCode, query, false) + if err != nil { + return CSVExport{}, err + } + var buf bytes.Buffer + writer := csv.NewWriter(&buf) + _ = writer.Write([]string{"币商名称", "币商短ID", "币商长ID", "流水类型", "转账金额", "收款人名称", "收款人短ID", "收款人长ID", "操作人", "操作人ID", "币商余额", "转账时间", "交易ID", "命令ID"}) + for _, item := range items { + operatorName, operatorID := coinSellerLedgerOperatorExportFields(item) + _ = writer.Write([]string{ + item.Seller.Username, + item.Seller.DisplayUserID, + item.Seller.UserID, + coinSellerLedgerLabel(item), + strconv.FormatInt(signedCoinSellerLedgerAmount(item), 10), + item.Receiver.Username, + item.Receiver.DisplayUserID, + item.Receiver.UserID, + operatorName, + operatorID, + strconv.FormatInt(item.SellerBalanceAfter, 10), + time.UnixMilli(item.CreatedAtMS).UTC().Format(time.RFC3339), + item.TransactionID, + item.CommandID, + }) + } + writer.Flush() + return CSVExport{FileName: "hyapp-coin-seller-ledger.csv", Content: buf.Bytes(), Count: int(total)}, writer.Error() +} + +func (s *Service) listCoinSellerLedger(ctx context.Context, appCode string, query coinSellerLedgerQuery, paginated bool) ([]coinSellerLedgerDTO, int64, error) { query = normalizeCoinSellerLedgerQuery(query) if s == nil || s.walletDB == nil { return nil, 0, fmt.Errorf("wallet mysql is not configured") @@ -177,29 +214,35 @@ func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, quer return nil, 0, err } var total int64 - if err := s.walletDB.QueryRowContext(ctx, ` - SELECT COUNT(*) - FROM wallet_entries e - JOIN wallet_transactions wt ON wt.app_code = e.app_code AND wt.transaction_id = e.transaction_id - `+whereSQL, - args..., - ).Scan(&total); err != nil { - return nil, 0, err + if paginated { + if err := s.walletDB.QueryRowContext(ctx, ` + SELECT COUNT(*) + FROM wallet_entries e + JOIN wallet_transactions wt ON wt.app_code = e.app_code AND wt.transaction_id = e.transaction_id + `+whereSQL, + args..., + ).Scan(&total); err != nil { + return nil, 0, err + } } // 明细查询只取币商侧 COIN_SELLER_COIN 分录:available_delta 表示币商库存可用变化, // available_after 表示该币商分录落账后的库存余额,receiver 再按 biz_type 从 metadata/counterparty 补出。 - rows, err := s.walletDB.QueryContext(ctx, ` + querySQL := ` SELECT e.entry_id, e.transaction_id, wt.command_id, e.user_id, wt.biz_type, e.available_delta, e.available_after, e.counterparty_user_id, COALESCE(CAST(wt.metadata_json AS CHAR), '{}'), e.created_at_ms FROM wallet_entries e JOIN wallet_transactions wt ON wt.app_code = e.app_code AND wt.transaction_id = e.transaction_id - `+whereSQL+` - ORDER BY e.created_at_ms DESC, e.entry_id DESC - LIMIT ? OFFSET ?`, - append(args, query.PageSize, offset(query.Page, query.PageSize))..., - ) + ` + whereSQL + ` + ORDER BY e.created_at_ms DESC, e.entry_id DESC` + queryArgs := args + if paginated { + querySQL += ` + LIMIT ? OFFSET ?` + queryArgs = append(queryArgs, query.PageSize, offset(query.Page, query.PageSize)) + } + rows, err := s.walletDB.QueryContext(ctx, querySQL, queryArgs...) if err != nil { return nil, 0, err } @@ -207,6 +250,7 @@ func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, quer items := make([]coinSellerLedgerDTO, 0, query.PageSize) profileIDs := make([]int64, 0, query.PageSize*2) + operatorIDs := make([]int64, 0, query.PageSize) for rows.Next() { var item coinSellerLedgerDTO var sellerUserID int64 @@ -230,6 +274,7 @@ func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, quer if err != nil { return nil, 0, err } + operatorUserID := metadataInt64(metadata, "operator_user_id", "operatorUserId") // 收款人按产品口径取实际收款人:币商转用户优先取 metadata.target_user_id,老数据没有 metadata 时再用 counterparty_user_id; // 后台入账和工资转币商的实际收款人都是币商本人,所以不能被 counterparty 字段误导成付款方或操作方。 receiverUserID := coinSellerLedgerReceiverUserID(item.BizType, sellerUserID, counterpartyUserID, metadata) @@ -237,20 +282,31 @@ func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, quer item.Direction = directionForDelta(item.AvailableDelta) item.Amount = absInt64(item.AvailableDelta) item.CounterpartyUserID = formatOptionalID(counterpartyUserID) + item.OperatorUserID = formatOptionalID(operatorUserID) item.Metadata = metadata item.Seller = coinLedgerUserDTO{UserID: strconv.FormatInt(sellerUserID, 10)} item.Receiver = coinLedgerUserDTO{UserID: strconv.FormatInt(receiverUserID, 10)} items = append(items, item) profileIDs = append(profileIDs, sellerUserID, receiverUserID) + if operatorUserID > 0 && item.LedgerType == coinSellerLedgerTypeAdminStockCredit { + operatorIDs = append(operatorIDs, operatorUserID) + } } if err := rows.Err(); err != nil { return nil, 0, err } + if !paginated { + total = int64(len(items)) + } profiles, err := s.userProfiles(ctx, appCode, profileIDs) if err != nil { return nil, 0, err } + operators, err := s.adminProfiles(ctx, operatorIDs) + if err != nil { + return nil, 0, err + } for i := range items { sellerUserID, _ := strconv.ParseInt(items[i].Seller.UserID, 10, 64) receiverUserID, _ := strconv.ParseInt(items[i].Receiver.UserID, 10, 64) @@ -262,6 +318,10 @@ func (s *Service) ListCoinSellerLedger(ctx context.Context, appCode string, quer if profile, ok := profiles[receiverUserID]; ok { items[i].Receiver = userDTOFromProfile(profile) } + operatorUserID, _ := strconv.ParseInt(items[i].OperatorUserID, 10, 64) + if operator, ok := operators[operatorUserID]; ok { + items[i].Operator = operator + } } return items, total, nil } @@ -759,6 +819,45 @@ func coinSellerLedgerTypeForBizType(bizType string) string { } } +func coinSellerLedgerLabel(item coinSellerLedgerDTO) string { + switch item.LedgerType { + case coinSellerLedgerTypeAdminStockCredit: + return "后台入账" + case coinSellerLedgerTypeSellerTransfer: + return "币商转用户" + case coinSellerLedgerTypeSalaryTransferIncome: + return "工资转币商" + default: + switch item.BizType { + case coinSellerStockPurchaseBizType: + return "币商进货" + case coinSellerCoinCompensationBizType: + return "金币补偿" + case coinSellerTransferBizType: + return "币商转用户" + case salaryTransferToCoinSellerBizType: + return "工资转币商" + default: + return firstNonEmpty(item.LedgerType, item.BizType, "-") + } + } +} + +func signedCoinSellerLedgerAmount(item coinSellerLedgerDTO) int64 { + if item.Direction == directionOut || item.AvailableDelta < 0 { + return -absInt64(item.Amount) + } + return absInt64(item.Amount) +} + +func coinSellerLedgerOperatorExportFields(item coinSellerLedgerDTO) (string, string) { + if item.LedgerType != coinSellerLedgerTypeAdminStockCredit { + return "", "" + } + operatorID := firstNonEmpty(item.Operator.AdminID, item.OperatorUserID) + return firstNonEmpty(item.Operator.Username, item.Operator.Name, operatorID), operatorID +} + func coinSellerLedgerReceiverUserID(bizType string, sellerUserID int64, counterpartyUserID int64, metadata map[string]any) int64 { if bizType == coinSellerTransferBizType { // 新数据把真实收款用户写在 metadata.target_user_id,优先使用它,避免 counterparty 语义随老交易实现变化。 @@ -846,6 +945,16 @@ func metadataInt64(metadata map[string]any, keys ...string) int64 { return 0 } +func firstNonEmpty(values ...string) string { + for _, value := range values { + value = strings.TrimSpace(value) + if value != "" { + return value + } + } + return "" +} + func parseFlexibleUserID(value any) (int64, error) { switch typed := value.(type) { case float64: diff --git a/server/admin/internal/modules/coinledger/service_test.go b/server/admin/internal/modules/coinledger/service_test.go index b7aa6aa7..88b8c77d 100644 --- a/server/admin/internal/modules/coinledger/service_test.go +++ b/server/admin/internal/modules/coinledger/service_test.go @@ -59,6 +59,19 @@ func TestCoinSellerLedgerWhereMapsAdminStockCredit(t *testing.T) { } } +func TestCoinSellerLedgerWhereEmptyTypeUsesAllPublicTypes(t *testing.T) { + where, args, err := coinSellerLedgerWhere("lalu", coinSellerLedgerQuery{}, nil) + if err != nil { + t.Fatalf("coin seller ledger where failed: %v", err) + } + if want := "WHERE e.app_code = ? AND e.asset_type = ? AND wt.biz_type IN (?,?,?,?)"; where != want { + t.Fatalf("where mismatch:\nwant %s\n got %s", want, where) + } + if len(args) != 6 || args[0] != "lalu" || args[1] != coinSellerAssetType || args[2] != coinSellerStockPurchaseBizType || args[3] != coinSellerCoinCompensationBizType || args[4] != coinSellerTransferBizType || args[5] != salaryTransferToCoinSellerBizType { + t.Fatalf("args mismatch: %#v", args) + } +} + func TestCoinSellerLedgerWhereRejectsInvalidType(t *testing.T) { _, _, err := coinSellerLedgerWhere("lalu", coinSellerLedgerQuery{LedgerType: "bad_type"}, nil) if err == nil { @@ -79,6 +92,24 @@ func TestCoinSellerLedgerReceiverUserIDUsesActualReceiver(t *testing.T) { } } +func TestCoinSellerLedgerOperatorExportFieldsOnlyForAdminStock(t *testing.T) { + adminItem := coinSellerLedgerDTO{ + LedgerType: coinSellerLedgerTypeAdminStockCredit, + OperatorUserID: "7", + Operator: coinAdjustmentOperatorDTO{AdminID: "7", Username: "hyappadmin", Name: "Admin"}, + } + operatorName, operatorID := coinSellerLedgerOperatorExportFields(adminItem) + if operatorName != "hyappadmin" || operatorID != "7" { + t.Fatalf("operator fields mismatch: name=%q id=%q", operatorName, operatorID) + } + + transferItem := coinSellerLedgerDTO{LedgerType: coinSellerLedgerTypeSellerTransfer, OperatorUserID: "7"} + operatorName, operatorID = coinSellerLedgerOperatorExportFields(transferItem) + if operatorName != "" || operatorID != "" { + t.Fatalf("seller transfer should not export operator: name=%q id=%q", operatorName, operatorID) + } +} + func TestNormalizeCoinSellerLedgerQueryCapsPageSize(t *testing.T) { query := normalizeCoinSellerLedgerQuery(coinSellerLedgerQuery{Page: -1, PageSize: 1000, SellerKeyword: " 164425 ", LedgerType: " seller_transfer "}) if query.Page != 1 || query.PageSize != 100 || query.SellerKeyword != "164425" || query.LedgerType != coinSellerLedgerTypeSellerTransfer { diff --git a/server/admin/internal/modules/cumulativerechargereward/handler.go b/server/admin/internal/modules/cumulativerechargereward/handler.go new file mode 100644 index 00000000..165af9c4 --- /dev/null +++ b/server/admin/internal/modules/cumulativerechargereward/handler.go @@ -0,0 +1,356 @@ +package cumulativerechargereward + +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"` + ThresholdUSDMinor int64 `json:"threshold_usd_minor"` + 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 grantDTO struct { + GrantID string `json:"grant_id"` + AppCode string `json:"app_code"` + CycleKey string `json:"cycle_key"` + UserID int64 `json:"user_id"` + User *userDTO `json:"user,omitempty"` + EventID string `json:"event_id"` + TransactionID string `json:"transaction_id"` + CommandID string `json:"command_id"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ThresholdUSDMinor int64 `json:"threshold_usd_minor"` + ResourceGroupID int64 `json:"resource_group_id"` + ReachedUSDMinor int64 `json:"reached_usd_minor"` + QualifyingUSDMinor int64 `json:"qualifying_usd_minor"` + RechargeCoinAmount int64 `json:"recharge_coin_amount"` + 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"` + 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.GetCumulativeRechargeRewardConfig(c.Request.Context(), &activityv1.GetCumulativeRechargeRewardConfigRequest{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 + } + // admin-server 只做输入透传和操作人注入,档位有效性、重复门槛和启用规则统一交给 activity-service 校验。 + tiers := make([]*activityv1.CumulativeRechargeRewardTier, 0, len(req.Tiers)) + for _, tier := range req.Tiers { + tiers = append(tiers, &activityv1.CumulativeRechargeRewardTier{ + TierId: tier.TierID, + TierCode: strings.TrimSpace(tier.TierCode), + TierName: strings.TrimSpace(tier.TierName), + ThresholdUsdMinor: tier.ThresholdUSDMinor, + ResourceGroupId: tier.ResourceGroupID, + Status: strings.TrimSpace(tier.Status), + SortOrder: tier.SortOrder, + }) + } + resp, err := h.activity.UpdateCumulativeRechargeRewardConfig(c.Request.Context(), &activityv1.UpdateCumulativeRechargeRewardConfigRequest{ + 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-cumulative-recharge-reward", "cumulative_recharge_reward_configs", item.AppCode, "success", "") + response.OK(c, item) +} + +func (h *Handler) ListGrants(c *gin.Context) { + options := shared.ListOptions(c) + // 发放记录主表只存 user_id;后台 keyword 先在 users 表解析成精确用户,再下推给 activity-service 查询。 + userID, matched, ok := h.resolveGrantUserID(c.Request.Context(), strings.TrimSpace(options.Keyword)) + if !ok { + response.ServerError(c, "查询用户信息失败") + return + } + if options.Keyword != "" && !matched { + response.OK(c, response.Page{Items: []grantDTO{}, Page: options.Page, PageSize: options.PageSize, Total: 0}) + return + } + resp, err := h.activity.ListCumulativeRechargeRewardGrants(c.Request.Context(), &activityv1.ListCumulativeRechargeRewardGrantsRequest{ + Meta: h.meta(c), + Status: strings.TrimSpace(options.Status), + UserId: userID, + CycleKey: strings.TrimSpace(c.Query("cycle_key")), + Page: int32(options.Page), + PageSize: int32(options.PageSize), + }) + if err != nil { + response.ServerError(c, "获取累充奖励发放记录失败") + return + } + items := make([]grantDTO, 0, len(resp.GetGrants())) + for _, grant := range resp.GetGrants() { + items = append(items, grantFromProto(grant)) + } + if err := h.fillGrantUsers(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) resolveGrantUserID(ctx context.Context, keyword string) (int64, bool, bool) { + if keyword == "" { + return 0, false, true + } + if h.userDB == nil { + return 0, false, true + } + // keyword 支持真实 user_id、短 ID 和昵称模糊匹配;排序优先精确 ID,避免昵称碰撞查到错误用户。 + 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) fillGrantUsers(ctx context.Context, grants []grantDTO) error { + if h.userDB == nil || len(grants) == 0 { + return nil + } + // 列表补用户资料是展示增强,找不到用户时仍返回 grant 原始 user_id,避免审计记录因为用户资料缺失而不可见。 + ids := collectGrantUserIDs(grants) + 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 grants { + if user, ok := users[grants[index].UserID]; ok { + grants[index].User = &user + continue + } + grants[index].User = &userDTO{UserID: grants[index].UserID} + } + return nil +} + +func configFromProto(config *activityv1.CumulativeRechargeRewardConfig) 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.CumulativeRechargeRewardTier) tierDTO { + if tier == nil { + return tierDTO{} + } + return tierDTO{ + TierID: tier.GetTierId(), + TierCode: tier.GetTierCode(), + TierName: tier.GetTierName(), + ThresholdUSDMinor: tier.GetThresholdUsdMinor(), + ResourceGroupID: tier.GetResourceGroupId(), + Status: tier.GetStatus(), + SortOrder: tier.GetSortOrder(), + CreatedAtMS: tier.GetCreatedAtMs(), + UpdatedAtMS: tier.GetUpdatedAtMs(), + } +} + +func grantFromProto(grant *activityv1.CumulativeRechargeRewardGrant) grantDTO { + if grant == nil { + return grantDTO{} + } + return grantDTO{ + GrantID: grant.GetGrantId(), + AppCode: grant.GetAppCode(), + CycleKey: grant.GetCycleKey(), + UserID: grant.GetUserId(), + EventID: grant.GetEventId(), + TransactionID: grant.GetTransactionId(), + CommandID: grant.GetCommandId(), + TierID: grant.GetTierId(), + TierCode: grant.GetTierCode(), + ThresholdUSDMinor: grant.GetThresholdUsdMinor(), + ResourceGroupID: grant.GetResourceGroupId(), + ReachedUSDMinor: grant.GetReachedUsdMinor(), + QualifyingUSDMinor: grant.GetQualifyingUsdMinor(), + RechargeCoinAmount: grant.GetRechargeCoinAmount(), + RechargeType: grant.GetRechargeType(), + Status: grant.GetStatus(), + WalletCommandID: grant.GetWalletCommandId(), + WalletGrantID: grant.GetWalletGrantId(), + FailureReason: grant.GetFailureReason(), + GrantedAtMS: grant.GetGrantedAtMs(), + CreatedAtMS: grant.GetCreatedAtMs(), + UpdatedAtMS: grant.GetUpdatedAtMs(), + } +} + +func collectGrantUserIDs(grants []grantDTO) []int64 { + seen := make(map[int64]struct{}, len(grants)) + ids := make([]int64, 0, len(grants)) + for _, grant := range grants { + if grant.UserID <= 0 { + continue + } + if _, ok := seen[grant.UserID]; ok { + continue + } + seen[grant.UserID] = struct{}{} + ids = append(ids, grant.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/cumulativerechargereward/routes.go b/server/admin/internal/modules/cumulativerechargereward/routes.go new file mode 100644 index 00000000..390d662b --- /dev/null +++ b/server/admin/internal/modules/cumulativerechargereward/routes.go @@ -0,0 +1,16 @@ +package cumulativerechargereward + +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/cumulative-recharge-reward/config", middleware.RequirePermission("cumulative-recharge-reward:view"), h.GetConfig) + protected.PUT("/admin/activity/cumulative-recharge-reward/config", middleware.RequirePermission("cumulative-recharge-reward:update"), h.UpdateConfig) + protected.GET("/admin/activity/cumulative-recharge-reward/grants", middleware.RequirePermission("cumulative-recharge-reward:view"), h.ListGrants) +} diff --git a/server/admin/internal/modules/gamemanagement/sync_games.go b/server/admin/internal/modules/gamemanagement/sync_games.go index 98fb4d3c..f4195818 100644 --- a/server/admin/internal/modules/gamemanagement/sync_games.go +++ b/server/admin/internal/modules/gamemanagement/sync_games.go @@ -26,6 +26,7 @@ import ( const ( adapterBaishunV1 = "baishun_v1" adapterZeeOneV1 = "zeeone_v1" + adapterVivaGamesV1 = "vivagames_v1" defaultGameStatus = "disabled" defaultGameCategory = "casino" defaultLaunchMode = "full_screen" @@ -131,6 +132,8 @@ func fetchProviderGameSyncPlan(ctx context.Context, platform *gamev1.GamePlatfor return fetchBaishunGameSyncPlan(ctx, platform, req) case adapterZeeOneV1: return fetchZeeOneGameSyncPlan(platform, req) + case adapterVivaGamesV1: + return fetchVivaGamesGameSyncPlan(platform, req) default: // 不在配置文件写死游戏:每家厂商新增“列表 API”时只加一个 adapter fetcher,后台入口保持不变。 return providerGameSyncPlan{}, fmt.Errorf("当前适配器暂未接入厂商游戏列表 API: %s", platform.GetAdapterType()) @@ -177,6 +180,14 @@ type zeeoneSyncConfig struct { GameCovers map[string]string `json:"game_covers"` } +type vivaGamesSyncConfig struct { + // VIVAGAMES 文档说明游戏 URL 由厂商提供,后台用这个映射把 URL 转成可勾选的本地目录候选项。 + GameURLs map[string]string `json:"game_urls"` + GameNames map[string]string `json:"game_names"` + GameIcons map[string]string `json:"game_icons"` + GameCovers map[string]string `json:"game_covers"` +} + func fetchZeeOneGameSyncPlan(platform *gamev1.GamePlatform, req syncGamesRequest) (providerGameSyncPlan, error) { config, err := decodeZeeOneSyncConfig(platform.GetAdapterConfigJson()) if err != nil { @@ -257,6 +268,67 @@ func zeeoneGameNameFromURL(raw string) string { return titleGameName(candidate) } +func fetchVivaGamesGameSyncPlan(platform *gamev1.GamePlatform, req syncGamesRequest) (providerGameSyncPlan, error) { + config, err := decodeVivaGamesSyncConfig(platform.GetAdapterConfigJson()) + if err != nil { + return providerGameSyncPlan{}, err + } + games, gameURLs := vivaGamesCatalogItems(platform.GetPlatformCode(), config, req) + if len(games) == 0 { + return providerGameSyncPlan{}, fmt.Errorf("VIVAGAMES 游戏列表为空:请在 adapterConfigJson.game_urls 配置游戏 ID 到 H5 URL 的映射") + } + return providerGameSyncPlan{ + Games: games, + GameURLs: gameURLs, + }, nil +} + +func decodeVivaGamesSyncConfig(raw string) (vivaGamesSyncConfig, error) { + if strings.TrimSpace(raw) == "" { + return vivaGamesSyncConfig{}, nil + } + var config vivaGamesSyncConfig + if err := json.Unmarshal([]byte(raw), &config); err != nil { + return vivaGamesSyncConfig{}, fmt.Errorf("VIVAGAMES 适配器配置 JSON 不合法") + } + return config, nil +} + +func vivaGamesCatalogItems(platformCode string, config vivaGamesSyncConfig, req syncGamesRequest) ([]catalogRequest, map[string]string) { + keys := make([]string, 0, len(config.GameURLs)) + for providerGameID, launchURL := range config.GameURLs { + if strings.TrimSpace(providerGameID) != "" && strings.TrimSpace(launchURL) != "" { + keys = append(keys, strings.TrimSpace(providerGameID)) + } + } + sort.Strings(keys) + items := make([]catalogRequest, 0, len(keys)) + gameURLs := make(map[string]string, len(keys)) + for index, providerGameID := range keys { + launchURL := strings.TrimSpace(config.GameURLs[providerGameID]) + gameURLs[providerGameID] = launchURL + name := firstNonEmpty(config.GameNames[providerGameID], zeeoneGameNameFromURL(launchURL), providerGameID) + iconURL := strings.TrimSpace(config.GameIcons[providerGameID]) + coverURL := firstNonEmpty(config.GameCovers[providerGameID], iconURL) + items = append(items, catalogRequest{ + GameID: stableGameID(platformCode, providerGameID), + PlatformCode: strings.TrimSpace(platformCode), + ProviderGameID: providerGameID, + GameName: name, + Category: defaulted(req.Category, defaultGameCategory), + IconURL: iconURL, + CoverURL: coverURL, + LaunchMode: defaulted(req.LaunchMode, defaultLaunchMode), + Orientation: defaultOrientation, + MinCoin: req.MinCoin, + Status: defaulted(req.Status, defaultGameStatus), + SortOrder: int32((index + 1) * 10), + Tags: compactTags(append([]string{strings.TrimSpace(platformCode), adapterVivaGamesV1}, req.Tags...)), + }) + } + return items, gameURLs +} + func titleGameName(value string) string { tokens := splitGameNameTokens(value) if len(tokens) == 0 { diff --git a/server/admin/internal/modules/gamemanagement/sync_games_test.go b/server/admin/internal/modules/gamemanagement/sync_games_test.go index a3a2a1b3..acfd8be6 100644 --- a/server/admin/internal/modules/gamemanagement/sync_games_test.go +++ b/server/admin/internal/modules/gamemanagement/sync_games_test.go @@ -105,6 +105,37 @@ func TestFetchZeeOneGameSyncPlanReadsConfiguredGameURLs(t *testing.T) { } } +func TestFetchVivaGamesGameSyncPlanReadsConfiguredGameURLs(t *testing.T) { + plan, err := fetchProviderGameSyncPlan(t.Context(), &gamev1.GamePlatform{ + PlatformCode: "vivagames", + AdapterType: adapterVivaGamesV1, + AdapterConfigJson: `{ + "game_urls": { + "2": "https://dev-rich2.s3.ap-southeast-1.amazonaws.com/richForever.html?game_id=2&isShow=1" + }, + "game_names": { + "2": "Rich Forever" + } + }`, + }, syncGamesRequest{}) + if err != nil { + t.Fatalf("fetchProviderGameSyncPlan failed: %v", err) + } + if len(plan.Games) != 1 { + t.Fatalf("games len = %d, want 1", len(plan.Games)) + } + game := plan.Games[0] + if game.GameID != "vivagames_2" || game.ProviderGameID != "2" || game.GameName != "Rich Forever" { + t.Fatalf("vivagames game mismatch: %+v", game) + } + if plan.GameURLs["2"] != "https://dev-rich2.s3.ap-southeast-1.amazonaws.com/richForever.html?game_id=2&isShow=1" { + t.Fatalf("game url mismatch: %+v", plan.GameURLs) + } + if game.Status != "disabled" || game.LaunchMode != "full_screen" || game.Orientation != "portrait" { + t.Fatalf("default fields mismatch: %+v", game) + } +} + func TestSelectProviderGamesKeepsOnlySelectedIDs(t *testing.T) { games := []catalogRequest{ {ProviderGameID: "1001", GameName: "one"}, diff --git a/server/admin/internal/modules/hostorg/reader.go b/server/admin/internal/modules/hostorg/reader.go index b3362702..c3585640 100644 --- a/server/admin/internal/modules/hostorg/reader.go +++ b/server/admin/internal/modules/hostorg/reader.go @@ -27,15 +27,17 @@ type CoinSellerListItem struct { Status string `json:"status"` MerchantAssetType string `json:"merchantAssetType"` MerchantBalance int64 `json:"merchantBalance"` - Contact string `json:"contact"` - DisplayUserID string `json:"displayUserId"` - Username string `json:"username"` - Avatar string `json:"avatar"` - RegionID int64 `json:"regionId"` - RegionName string `json:"regionName"` - CreatedByUserID int64 `json:"createdByUserId"` - CreatedAtMs int64 `json:"createdAtMs"` - UpdatedAtMs int64 `json:"updatedAtMs"` + // TotalRechargeUSDTMicro 是币商 USDT 进货累计付款微单位,只统计 counts_as_seller_recharge 的库存记录。 + TotalRechargeUSDTMicro int64 `json:"totalRechargeUsdtMicro"` + Contact string `json:"contact"` + DisplayUserID string `json:"displayUserId"` + Username string `json:"username"` + Avatar string `json:"avatar"` + RegionID int64 `json:"regionId"` + RegionName string `json:"regionName"` + CreatedByUserID int64 `json:"createdByUserId"` + CreatedAtMs int64 `json:"createdAtMs"` + UpdatedAtMs int64 `json:"updatedAtMs"` } type CoinSellerSalaryRateTier struct { @@ -615,6 +617,13 @@ func (r *Reader) ListCoinSellers(ctx context.Context, query listQuery) ([]*CoinS if err != nil { return nil, 0, err } + limitSQL := "LIMIT ? OFFSET ?" + queryArgs := append(args, query.PageSize, offset(query.Page, query.PageSize)) + if isCoinSellerComputedSort(query.SortBy) { + // 币商余额和累充 USDT 都来自 wallet-service 聚合,必须先读取所有匹配币商再排序分页,避免只排序当前页。 + limitSQL = "" + queryArgs = args + } rows, err := r.db.QueryContext(ctx, fmt.Sprintf(` SELECT csp.user_id, csp.status, csp.merchant_asset_type, COALESCE(csp.contact_info, ''), @@ -624,8 +633,8 @@ func (r *Reader) ListCoinSellers(ctx context.Context, query listQuery) ([]*CoinS COALESCE(r.name, '') %s ORDER BY csp.created_at_ms DESC, csp.user_id DESC - LIMIT ? OFFSET ? - `, whereSQL), append(args, query.PageSize, offset(query.Page, query.PageSize))...) + %s + `, whereSQL, limitSQL), queryArgs...) if err != nil { return nil, 0, err } @@ -661,8 +670,17 @@ func (r *Reader) ListCoinSellers(ctx context.Context, query listQuery) ([]*CoinS if err != nil { return nil, 0, err } + rechargeTotals, err := r.coinSellerRechargeTotals(ctx, appCode, userIDs) + if err != nil { + return nil, 0, err + } for _, item := range items { item.MerchantBalance = balances[item.UserID] + item.TotalRechargeUSDTMicro = rechargeTotals[item.UserID] + } + if isCoinSellerComputedSort(query.SortBy) { + sortCoinSellerListItems(items, query.SortBy, query.SortDirection) + items = paginateCoinSellerListItems(items, query.Page, query.PageSize) } return items, total, nil } @@ -851,6 +869,41 @@ func (r *Reader) coinSellerBalances(ctx context.Context, appCode string, userIDs return result, rows.Err() } +// coinSellerRechargeTotals 从币商进货专表汇总 USDT 付款,金币补偿不会计入累充口径。 +func (r *Reader) coinSellerRechargeTotals(ctx context.Context, appCode string, userIDs []int64) (map[int64]int64, error) { + result := make(map[int64]int64, len(userIDs)) + if r == nil || r.walletDB == nil || len(userIDs) == 0 { + return result, nil + } + placeholders := sqlPlaceholders(len(userIDs)) + args := []any{appCode, paidCurrencyUSDT} + for _, userID := range userIDs { + args = append(args, userID) + } + rows, err := r.walletDB.QueryContext(ctx, fmt.Sprintf(` + SELECT seller_user_id, COALESCE(SUM(paid_amount_micro), 0) + FROM coin_seller_stock_records + WHERE app_code = ? + AND counts_as_seller_recharge = TRUE + AND paid_currency_code = ? + AND seller_user_id IN (%s) + GROUP BY seller_user_id + `, placeholders), args...) + if err != nil { + return nil, err + } + defer rows.Close() + for rows.Next() { + var userID int64 + var amount int64 + if err := rows.Scan(&userID, &amount); err != nil { + return nil, err + } + result[userID] = amount + } + return result, rows.Err() +} + func (r *Reader) hostPeriodDiamonds(ctx context.Context, appCode string, userIDs []int64) (map[int64]int64, error) { result := make(map[int64]int64, len(userIDs)) if r == nil || r.walletDB == nil || len(userIDs) == 0 { @@ -881,6 +934,39 @@ func (r *Reader) hostPeriodDiamonds(ctx context.Context, appCode string, userIDs return result, rows.Err() } +func isCoinSellerComputedSort(sortBy string) bool { + return sortBy == sortByMerchantBalance || sortBy == sortByTotalRechargeUSDT +} + +// sortCoinSellerListItems 只处理 wallet 聚合字段排序,基础身份字段仍使用 SQL 默认创建时间排序。 +func sortCoinSellerListItems(items []*CoinSellerListItem, sortBy string, direction string) { + sort.SliceStable(items, func(i, j int) bool { + left := coinSellerSortValue(items[i], sortBy) + right := coinSellerSortValue(items[j], sortBy) + if left == right { + return false + } + if direction == "asc" { + return left < right + } + return left > right + }) +} + +func coinSellerSortValue(item *CoinSellerListItem, sortBy string) int64 { + if item == nil { + return 0 + } + switch sortBy { + case sortByTotalRechargeUSDT: + return item.TotalRechargeUSDTMicro + case sortByMerchantBalance: + return item.MerchantBalance + default: + return 0 + } +} + func sortHostProfilesByDiamond(items []*userclient.HostProfile, direction string) { sort.SliceStable(items, func(i, j int) bool { if items[i].Diamond == items[j].Diamond { @@ -893,6 +979,24 @@ func sortHostProfilesByDiamond(items []*userclient.HostProfile, direction string }) } +func paginateCoinSellerListItems(items []*CoinSellerListItem, page int, pageSize int) []*CoinSellerListItem { + if page < 1 { + page = 1 + } + if pageSize < 1 { + pageSize = 20 + } + start := (page - 1) * pageSize + if start >= len(items) { + return []*CoinSellerListItem{} + } + end := start + pageSize + if end > len(items) { + end = len(items) + } + return items[start:end] +} + func paginateHostProfiles(items []*userclient.HostProfile, page int, pageSize int) []*userclient.HostProfile { if page < 1 { page = 1 diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index fed44301..da1af390 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -18,6 +18,9 @@ const ( coinSellerStockTypePurchase = "usdt_purchase" coinSellerStockTypeCompensate = "coin_compensation" paidCurrencyUSDT = "USDT" + sortByDiamond = "diamond" + sortByMerchantBalance = "merchant_balance" + sortByTotalRechargeUSDT = "total_recharge_usdt" bdLeaderPositionAliasMaxRunes = 64 ) @@ -524,7 +527,9 @@ func normalizeListQuery(query listQuery) listQuery { query.Keyword = strings.TrimSpace(query.Keyword) query.Status = strings.ToLower(strings.TrimSpace(query.Status)) query.SortBy = strings.ToLower(strings.TrimSpace(query.SortBy)) - if query.SortBy != "diamond" { + switch query.SortBy { + case sortByDiamond, sortByMerchantBalance, sortByTotalRechargeUSDT: + default: query.SortBy = "" query.SortDirection = "" return query diff --git a/server/admin/internal/modules/hostorg/service_test.go b/server/admin/internal/modules/hostorg/service_test.go new file mode 100644 index 00000000..7bd84b4a --- /dev/null +++ b/server/admin/internal/modules/hostorg/service_test.go @@ -0,0 +1,32 @@ +package hostorg + +import "testing" + +// TestNormalizeListQueryAllowsCoinSellerComputedSorts 锁定币商余额和累充 USDT 排序字段会被后台列表查询接受。 +func TestNormalizeListQueryAllowsCoinSellerComputedSorts(t *testing.T) { + for _, sortBy := range []string{sortByMerchantBalance, sortByTotalRechargeUSDT} { + query := normalizeListQuery(listQuery{Page: 1, PageSize: 50, SortBy: sortBy, SortDirection: "asc"}) + if query.SortBy != sortBy || query.SortDirection != "asc" { + t.Fatalf("expected sort %s asc to be kept, got sort_by=%q direction=%q", sortBy, query.SortBy, query.SortDirection) + } + } +} + +// TestSortCoinSellerListItemsComputedFields 验证 wallet 聚合字段排序只改变展示顺序,不改动币商身份数据。 +func TestSortCoinSellerListItemsComputedFields(t *testing.T) { + items := []*CoinSellerListItem{ + {UserID: 1, MerchantBalance: 100, TotalRechargeUSDTMicro: 30_000_000}, + {UserID: 2, MerchantBalance: 300, TotalRechargeUSDTMicro: 10_000_000}, + {UserID: 3, MerchantBalance: 200, TotalRechargeUSDTMicro: 20_000_000}, + } + + sortCoinSellerListItems(items, sortByMerchantBalance, "desc") + if got := []int64{items[0].UserID, items[1].UserID, items[2].UserID}; got[0] != 2 || got[1] != 3 || got[2] != 1 { + t.Fatalf("merchant balance desc order mismatch: %v", got) + } + + sortCoinSellerListItems(items, sortByTotalRechargeUSDT, "asc") + if got := []int64{items[0].UserID, items[1].UserID, items[2].UserID}; got[0] != 2 || got[1] != 3 || got[2] != 1 { + t.Fatalf("total recharge usdt asc order mismatch: %v", got) + } +} diff --git a/server/admin/internal/modules/registrationreward/handler.go b/server/admin/internal/modules/registrationreward/handler.go index 34e50931..474c992a 100644 --- a/server/admin/internal/modules/registrationreward/handler.go +++ b/server/admin/internal/modules/registrationreward/handler.go @@ -3,6 +3,7 @@ package registrationreward import ( "context" "database/sql" + "strconv" "strings" "time" @@ -72,6 +73,14 @@ type userDTO struct { Avatar string `json:"avatar"` } +type claimsPageDTO struct { + Items []claimDTO `json:"items"` + Page int `json:"page"` + PageSize int `json:"pageSize"` + Total int64 `json:"total"` + TodayClaimedCount int64 `json:"today_claimed_count"` +} + func (h *Handler) GetRegistrationRewardConfig(c *gin.Context) { resp, err := h.activity.GetRegistrationRewardConfig(c.Request.Context(), &activityv1.GetRegistrationRewardConfigRequest{Meta: h.meta(c)}) if err != nil { @@ -107,21 +116,29 @@ func (h *Handler) UpdateRegistrationRewardConfig(c *gin.Context) { func (h *Handler) ListRegistrationRewardClaims(c *gin.Context) { options := shared.ListOptions(c) + claimedStartMS := queryInt64(c, "claimed_start_ms", "claimedStartMs", "start_ms", "startMs") + claimedEndMS := queryInt64(c, "claimed_end_ms", "claimedEndMs", "end_ms", "endMs") 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}) + todayClaimedCount, ok := h.loadTodayClaimedCount(c) + if !ok { + return + } + response.OK(c, claimsPageDTO{Items: []claimDTO{}, Page: options.Page, PageSize: options.PageSize, Total: 0, TodayClaimedCount: todayClaimedCount}) return } resp, err := h.activity.ListRegistrationRewardClaims(c.Request.Context(), &activityv1.ListRegistrationRewardClaimsRequest{ - Meta: h.meta(c), - Status: strings.TrimSpace(options.Status), - UserId: userID, - Page: int32(options.Page), - PageSize: int32(options.PageSize), + Meta: h.meta(c), + Status: strings.TrimSpace(options.Status), + UserId: userID, + ClaimedStartMs: claimedStartMS, + ClaimedEndMs: claimedEndMS, + Page: int32(options.Page), + PageSize: int32(options.PageSize), }) if err != nil { response.ServerError(c, "获取注册奖励领取记录失败") @@ -135,7 +152,26 @@ func (h *Handler) ListRegistrationRewardClaims(c *gin.Context) { response.ServerError(c, "补全用户信息失败") return } - response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) + response.OK(c, claimsPageDTO{ + Items: items, + Page: options.Page, + PageSize: options.PageSize, + Total: resp.GetTotal(), + TodayClaimedCount: resp.GetTodayClaimedCount(), + }) +} + +func (h *Handler) loadTodayClaimedCount(c *gin.Context) (int64, bool) { + resp, err := h.activity.ListRegistrationRewardClaims(c.Request.Context(), &activityv1.ListRegistrationRewardClaimsRequest{ + Meta: h.meta(c), + Page: 1, + PageSize: 1, + }) + if err != nil { + response.ServerError(c, "获取注册奖励今日领取数量失败") + return 0, false + } + return resp.GetTodayClaimedCount(), true } func (h *Handler) meta(c *gin.Context) *activityv1.RequestMeta { @@ -303,3 +339,17 @@ func int64Args(values []int64) []any { } return args } + +func queryInt64(c *gin.Context, names ...string) int64 { + for _, name := range names { + value := strings.TrimSpace(c.Query(name)) + if value == "" { + continue + } + parsed, err := strconv.ParseInt(value, 10, 64) + if err == nil && parsed > 0 { + return parsed + } + } + return 0 +} diff --git a/server/admin/internal/modules/roomturnoverreward/handler.go b/server/admin/internal/modules/roomturnoverreward/handler.go new file mode 100644 index 00000000..627dcff8 --- /dev/null +++ b/server/admin/internal/modules/roomturnoverreward/handler.go @@ -0,0 +1,227 @@ +package roomturnoverreward + +import ( + "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 + audit shared.OperationLogger +} + +func New(activity activityclient.Client, audit shared.OperationLogger) *Handler { + return &Handler{activity: activity, 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"` + ThresholdCoinSpent int64 `json:"threshold_coin_spent"` + RewardCoinAmount int64 `json:"reward_coin_amount"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type settlementDTO struct { + SettlementID string `json:"settlement_id"` + RoomID string `json:"room_id"` + OwnerUserID int64 `json:"owner_user_id"` + PeriodStartMS int64 `json:"period_start_ms"` + PeriodEndMS int64 `json:"period_end_ms"` + CoinSpent int64 `json:"coin_spent"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ThresholdCoinSpent int64 `json:"threshold_coin_spent"` + RewardCoinAmount int64 `json:"reward_coin_amount"` + Status string `json:"status"` + WalletCommandID string `json:"wallet_command_id"` + WalletTransactionID string `json:"wallet_transaction_id"` + FailureReason string `json:"failure_reason"` + SettledAtMS int64 `json:"settled_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +func (h *Handler) GetConfig(c *gin.Context) { + // 后台服务只透传到 activity-service 获取当前 App 配置;活动规则 owner 不在 admin-server 内部复制。 + resp, err := h.activity.GetRoomTurnoverRewardConfig(c.Request.Context(), &activityv1.GetRoomTurnoverRewardConfigRequest{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.RoomTurnoverRewardTier, 0, len(req.Tiers)) + for _, tier := range req.Tiers { + // 后台只做输入清洗和操作者透传;阈值递增、奖励金额和启用状态等业务校验统一由 activity-service 执行。 + tiers = append(tiers, &activityv1.RoomTurnoverRewardTier{ + TierId: tier.TierID, + TierCode: strings.TrimSpace(tier.TierCode), + TierName: strings.TrimSpace(tier.TierName), + ThresholdCoinSpent: tier.ThresholdCoinSpent, + RewardCoinAmount: tier.RewardCoinAmount, + Status: strings.TrimSpace(tier.Status), + SortOrder: tier.SortOrder, + }) + } + resp, err := h.activity.UpdateRoomTurnoverRewardConfig(c.Request.Context(), &activityv1.UpdateRoomTurnoverRewardConfigRequest{ + 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()) + // 配置修改必须留下后台审计资源 ID,后续排查结算金额变化时可以回到具体 App 配置记录。 + shared.OperationLogWithResourceID(c, h.audit, "update-room-turnover-reward", "room_turnover_reward_configs", item.AppCode, "success", "") + response.OK(c, item) +} + +func (h *Handler) ListSettlements(c *gin.Context) { + // 列表筛选沿用通用 ListOptions:status 过滤结算状态,keyword 用作 room_id 精确查询,避免后台接口引入模糊扫表。 + options := shared.ListOptions(c) + resp, err := h.activity.ListRoomTurnoverRewardSettlements(c.Request.Context(), &activityv1.ListRoomTurnoverRewardSettlementsRequest{ + Meta: h.meta(c), + Status: strings.TrimSpace(options.Status), + RoomId: strings.TrimSpace(options.Keyword), + Page: int32(options.Page), + PageSize: int32(options.PageSize), + }) + if err != nil { + response.ServerError(c, "获取房间流水奖励结算记录失败") + return + } + items := make([]settlementDTO, 0, len(resp.GetSettlements())) + for _, settlement := range resp.GetSettlements() { + items = append(items, settlementFromProto(settlement)) + } + response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) +} + +func (h *Handler) RetrySettlement(c *gin.Context) { + settlementID := strings.TrimSpace(c.Param("settlement_id")) + if settlementID == "" { + response.BadRequest(c, "结算记录 ID 不正确") + return + } + // retry 只把指定 settlement 交还 activity-service;是否重新取房主、是否调用钱包和是否幂等都由活动服务闭环处理。 + resp, err := h.activity.RetryRoomTurnoverRewardSettlement(c.Request.Context(), &activityv1.RetryRoomTurnoverRewardSettlementRequest{ + Meta: h.meta(c), + SettlementId: settlementID, + OperatorAdminId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + item := settlementFromProto(resp.GetSettlement()) + shared.OperationLogWithResourceID(c, h.audit, "retry-room-turnover-reward", "room_turnover_reward_settlements", settlementID, "success", "") + response.OK(c, item) +} + +func (h *Handler) meta(c *gin.Context) *activityv1.RequestMeta { + return &activityv1.RequestMeta{ + // 使用后台请求 ID 串起 admin-server、activity-service 和 wallet-service 日志,AppCode 来自当前后台上下文。 + RequestId: middleware.CurrentRequestID(c), + Caller: "admin-server", + AppCode: appctx.FromContext(c.Request.Context()), + SentAtMs: time.Now().UnixMilli(), + } +} + +func configFromProto(config *activityv1.RoomTurnoverRewardConfig) 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.RoomTurnoverRewardTier) tierDTO { + if tier == nil { + return tierDTO{} + } + return tierDTO{ + TierID: tier.GetTierId(), + TierCode: tier.GetTierCode(), + TierName: tier.GetTierName(), + ThresholdCoinSpent: tier.GetThresholdCoinSpent(), + RewardCoinAmount: tier.GetRewardCoinAmount(), + Status: tier.GetStatus(), + SortOrder: tier.GetSortOrder(), + CreatedAtMS: tier.GetCreatedAtMs(), + UpdatedAtMS: tier.GetUpdatedAtMs(), + } +} + +func settlementFromProto(settlement *activityv1.RoomTurnoverRewardSettlement) settlementDTO { + if settlement == nil { + return settlementDTO{} + } + return settlementDTO{ + SettlementID: settlement.GetSettlementId(), + RoomID: settlement.GetRoomId(), + OwnerUserID: settlement.GetOwnerUserId(), + PeriodStartMS: settlement.GetPeriodStartMs(), + PeriodEndMS: settlement.GetPeriodEndMs(), + CoinSpent: settlement.GetCoinSpent(), + TierID: settlement.GetTierId(), + TierCode: settlement.GetTierCode(), + ThresholdCoinSpent: settlement.GetThresholdCoinSpent(), + RewardCoinAmount: settlement.GetRewardCoinAmount(), + Status: settlement.GetStatus(), + WalletCommandID: settlement.GetWalletCommandId(), + WalletTransactionID: settlement.GetWalletTransactionId(), + FailureReason: settlement.GetFailureReason(), + SettledAtMS: settlement.GetSettledAtMs(), + CreatedAtMS: settlement.GetCreatedAtMs(), + UpdatedAtMS: settlement.GetUpdatedAtMs(), + } +} diff --git a/server/admin/internal/modules/roomturnoverreward/routes.go b/server/admin/internal/modules/roomturnoverreward/routes.go new file mode 100644 index 00000000..14951334 --- /dev/null +++ b/server/admin/internal/modules/roomturnoverreward/routes.go @@ -0,0 +1,17 @@ +package roomturnoverreward + +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/room-turnover-reward/config", middleware.RequirePermission("room-turnover-reward:view"), h.GetConfig) + protected.PUT("/admin/activity/room-turnover-reward/config", middleware.RequirePermission("room-turnover-reward:update"), h.UpdateConfig) + protected.GET("/admin/activity/room-turnover-reward/settlements", middleware.RequirePermission("room-turnover-reward:view"), h.ListSettlements) + protected.POST("/admin/activity/room-turnover-reward/settlements/:settlement_id/retry", middleware.RequirePermission("room-turnover-reward:retry"), h.RetrySettlement) +} diff --git a/server/admin/internal/modules/weeklystar/handler.go b/server/admin/internal/modules/weeklystar/handler.go new file mode 100644 index 00000000..ae8ce5ae --- /dev/null +++ b/server/admin/internal/modules/weeklystar/handler.go @@ -0,0 +1,350 @@ +package weeklystar + +import ( + "strconv" + "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 + audit shared.OperationLogger +} + +func New(activity activityclient.Client, audit shared.OperationLogger) *Handler { + return &Handler{activity: activity, audit: audit} +} + +type cycleRequest struct { + CycleID string `json:"cycle_id"` + Title string `json:"title"` + Status string `json:"status"` + RegionID int64 `json:"region_id"` + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` + GiftIDs []string `json:"gift_ids"` + Gifts []giftDTO `json:"gifts"` + Rewards []rewardDTO `json:"rewards"` + Top1ResourceGroupID int64 `json:"top1_resource_group_id"` + Top2ResourceGroupID int64 `json:"top2_resource_group_id"` + Top3ResourceGroupID int64 `json:"top3_resource_group_id"` +} + +type statusRequest struct { + Status string `json:"status"` +} + +type cycleDTO struct { + AppCode string `json:"app_code,omitempty"` + CycleID string `json:"cycle_id"` + ActivityCode string `json:"activity_code"` + RegionID int64 `json:"region_id"` + Title string `json:"title"` + Status string `json:"status"` + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` + Gifts []giftDTO `json:"gifts"` + Rewards []rewardDTO `json:"rewards"` + CreatedByAdminID int64 `json:"created_by_admin_id"` + UpdatedByAdminID int64 `json:"updated_by_admin_id"` + SettledAtMS int64 `json:"settled_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type giftDTO struct { + GiftID string `json:"gift_id"` + SortOrder int32 `json:"sort_order"` +} + +type rewardDTO struct { + RankNo int32 `json:"rank_no"` + ResourceGroupID int64 `json:"resource_group_id"` +} + +type leaderboardEntryDTO struct { + RankNo int32 `json:"rank_no"` + UserID int64 `json:"user_id"` + Score int64 `json:"score"` + FirstScoredAtMS int64 `json:"first_scored_at_ms"` + LastScoredAtMS int64 `json:"last_scored_at_ms"` + DisplayUserID string `json:"display_user_id,omitempty"` + Username string `json:"username,omitempty"` + Avatar string `json:"avatar,omitempty"` +} + +type settlementDTO struct { + SettlementID string `json:"settlement_id"` + CycleID string `json:"cycle_id"` + RankNo int32 `json:"rank_no"` + UserID int64 `json:"user_id"` + Score int64 `json:"score"` + ResourceGroupID int64 `json:"resource_group_id"` + WalletCommandID string `json:"wallet_command_id"` + WalletGrantID string `json:"wallet_grant_id"` + Status string `json:"status"` + FailureReason string `json:"failure_reason"` + AttemptCount int32 `json:"attempt_count"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +func (h *Handler) ListCycles(c *gin.Context) { + options := shared.ListOptions(c) + resp, err := h.activity.ListWeeklyStarCycles(c.Request.Context(), &activityv1.ListWeeklyStarCyclesRequest{ + Meta: h.meta(c), + Status: strings.TrimSpace(options.Status), + StartMs: parseInt64Query(c, "start_ms"), + EndMs: parseInt64Query(c, "end_ms"), + RegionId: parseInt64Query(c, "region_id"), + Page: int32(options.Page), + PageSize: int32(options.PageSize), + }) + if err != nil { + response.ServerError(c, "获取周星周期失败") + return + } + items := make([]cycleDTO, 0, len(resp.GetCycles())) + for _, cycle := range resp.GetCycles() { + items = append(items, cycleFromProto(cycle)) + } + response.OK(c, response.Page{Items: items, Page: options.Page, PageSize: options.PageSize, Total: resp.GetTotal()}) +} + +func (h *Handler) CreateCycle(c *gin.Context) { + var req cycleRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "周星周期参数不正确") + return + } + resp, err := h.activity.CreateWeeklyStarCycle(c.Request.Context(), &activityv1.UpsertWeeklyStarCycleRequest{ + Meta: h.meta(c), + Cycle: req.toProto(), + OperatorAdminId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + item := cycleFromProto(resp.GetCycle()) + shared.OperationLogWithResourceID(c, h.audit, "create-weekly-star-cycle", "weekly_star_cycles", item.CycleID, "success", "") + response.OK(c, item) +} + +func (h *Handler) GetCycle(c *gin.Context) { + cycleID := strings.TrimSpace(c.Param("cycle_id")) + resp, err := h.activity.GetWeeklyStarCycle(c.Request.Context(), &activityv1.GetWeeklyStarCycleRequest{Meta: h.meta(c), CycleId: cycleID}) + if err != nil { + response.ServerError(c, "获取周星周期详情失败") + return + } + response.OK(c, cycleFromProto(resp.GetCycle())) +} + +func (h *Handler) UpdateCycle(c *gin.Context) { + var req cycleRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "周星周期参数不正确") + return + } + req.CycleID = strings.TrimSpace(c.Param("cycle_id")) + resp, err := h.activity.UpdateWeeklyStarCycle(c.Request.Context(), &activityv1.UpsertWeeklyStarCycleRequest{ + Meta: h.meta(c), + Cycle: req.toProto(), + OperatorAdminId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + item := cycleFromProto(resp.GetCycle()) + shared.OperationLogWithResourceID(c, h.audit, "update-weekly-star-cycle", "weekly_star_cycles", item.CycleID, "success", "") + response.OK(c, item) +} + +func (h *Handler) SetCycleStatus(c *gin.Context) { + var req statusRequest + if err := c.ShouldBindJSON(&req); err != nil { + response.BadRequest(c, "周星周期状态参数不正确") + return + } + cycleID := strings.TrimSpace(c.Param("cycle_id")) + resp, err := h.activity.SetWeeklyStarCycleStatus(c.Request.Context(), &activityv1.SetWeeklyStarCycleStatusRequest{ + Meta: h.meta(c), + CycleId: cycleID, + Status: strings.TrimSpace(req.Status), + OperatorAdminId: int64(middleware.CurrentUserID(c)), + }) + if err != nil { + response.BadRequest(c, err.Error()) + return + } + item := cycleFromProto(resp.GetCycle()) + shared.OperationLogWithResourceID(c, h.audit, "set-weekly-star-cycle-status", "weekly_star_cycles", item.CycleID, "success", "") + response.OK(c, item) +} + +func (h *Handler) ListLeaderboard(c *gin.Context) { + resp, err := h.activity.ListWeeklyStarLeaderboard(c.Request.Context(), &activityv1.ListWeeklyStarLeaderboardRequest{ + Meta: h.meta(c), + CycleId: strings.TrimSpace(c.Param("cycle_id")), + PageSize: int32(parseIntQuery(c, "page_size", 50)), + PageToken: strings.TrimSpace(c.Query("page_token")), + }) + if err != nil { + response.ServerError(c, "获取周星排行榜失败") + return + } + items := make([]leaderboardEntryDTO, 0, len(resp.GetEntries())) + for _, entry := range resp.GetEntries() { + items = append(items, leaderboardEntryFromProto(entry)) + } + response.OK(c, gin.H{"cycle": cycleFromProto(resp.GetCycle()), "items": items, "total": resp.GetTotal(), "next_page_token": resp.GetNextPageToken()}) +} + +func (h *Handler) ListSettlements(c *gin.Context) { + resp, err := h.activity.ListWeeklyStarSettlements(c.Request.Context(), &activityv1.ListWeeklyStarSettlementsRequest{ + Meta: h.meta(c), + CycleId: strings.TrimSpace(c.Param("cycle_id")), + }) + if err != nil { + response.ServerError(c, "获取周星结算记录失败") + return + } + items := make([]settlementDTO, 0, len(resp.GetSettlements())) + for _, settlement := range resp.GetSettlements() { + items = append(items, settlementFromProto(settlement)) + } + response.OK(c, items) +} + +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 (r cycleRequest) toProto() *activityv1.WeeklyStarCycle { + gifts := make([]*activityv1.WeeklyStarGift, 0, 3) + if len(r.Gifts) > 0 { + for _, gift := range r.Gifts { + gifts = append(gifts, &activityv1.WeeklyStarGift{GiftId: strings.TrimSpace(gift.GiftID), SortOrder: gift.SortOrder}) + } + } else { + for index, giftID := range r.GiftIDs { + gifts = append(gifts, &activityv1.WeeklyStarGift{GiftId: strings.TrimSpace(giftID), SortOrder: int32(index + 1)}) + } + } + rewards := make([]*activityv1.WeeklyStarReward, 0, 3) + if len(r.Rewards) > 0 { + for _, reward := range r.Rewards { + rewards = append(rewards, &activityv1.WeeklyStarReward{RankNo: reward.RankNo, ResourceGroupId: reward.ResourceGroupID}) + } + } else { + rewards = append(rewards, + &activityv1.WeeklyStarReward{RankNo: 1, ResourceGroupId: r.Top1ResourceGroupID}, + &activityv1.WeeklyStarReward{RankNo: 2, ResourceGroupId: r.Top2ResourceGroupID}, + &activityv1.WeeklyStarReward{RankNo: 3, ResourceGroupId: r.Top3ResourceGroupID}, + ) + } + return &activityv1.WeeklyStarCycle{ + CycleId: strings.TrimSpace(r.CycleID), + RegionId: r.RegionID, + Title: strings.TrimSpace(r.Title), + Status: strings.TrimSpace(r.Status), + StartMs: r.StartMS, + EndMs: r.EndMS, + Gifts: gifts, + Rewards: rewards, + } +} + +func cycleFromProto(cycle *activityv1.WeeklyStarCycle) cycleDTO { + if cycle == nil { + return cycleDTO{Gifts: []giftDTO{}, Rewards: []rewardDTO{}} + } + gifts := make([]giftDTO, 0, len(cycle.GetGifts())) + for _, gift := range cycle.GetGifts() { + gifts = append(gifts, giftDTO{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder()}) + } + rewards := make([]rewardDTO, 0, len(cycle.GetRewards())) + for _, reward := range cycle.GetRewards() { + rewards = append(rewards, rewardDTO{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()}) + } + return cycleDTO{ + AppCode: cycle.GetAppCode(), + CycleID: cycle.GetCycleId(), + ActivityCode: cycle.GetActivityCode(), + RegionID: cycle.GetRegionId(), + Title: cycle.GetTitle(), + Status: cycle.GetStatus(), + StartMS: cycle.GetStartMs(), + EndMS: cycle.GetEndMs(), + Gifts: gifts, + Rewards: rewards, + CreatedByAdminID: cycle.GetCreatedByAdminId(), + UpdatedByAdminID: cycle.GetUpdatedByAdminId(), + SettledAtMS: cycle.GetSettledAtMs(), + CreatedAtMS: cycle.GetCreatedAtMs(), + UpdatedAtMS: cycle.GetUpdatedAtMs(), + } +} + +func leaderboardEntryFromProto(entry *activityv1.WeeklyStarLeaderboardEntry) leaderboardEntryDTO { + if entry == nil { + return leaderboardEntryDTO{} + } + return leaderboardEntryDTO{ + RankNo: entry.GetRankNo(), + UserID: entry.GetUserId(), + Score: entry.GetScore(), + FirstScoredAtMS: entry.GetFirstScoredAtMs(), + LastScoredAtMS: entry.GetLastScoredAtMs(), + } +} + +func settlementFromProto(settlement *activityv1.WeeklyStarSettlement) settlementDTO { + if settlement == nil { + return settlementDTO{} + } + return settlementDTO{ + SettlementID: settlement.GetSettlementId(), + CycleID: settlement.GetCycleId(), + RankNo: settlement.GetRankNo(), + UserID: settlement.GetUserId(), + Score: settlement.GetScore(), + ResourceGroupID: settlement.GetResourceGroupId(), + WalletCommandID: settlement.GetWalletCommandId(), + WalletGrantID: settlement.GetWalletGrantId(), + Status: settlement.GetStatus(), + FailureReason: settlement.GetFailureReason(), + AttemptCount: settlement.GetAttemptCount(), + CreatedAtMS: settlement.GetCreatedAtMs(), + UpdatedAtMS: settlement.GetUpdatedAtMs(), + } +} + +func parseInt64Query(c *gin.Context, key string) int64 { + value, _ := strconv.ParseInt(strings.TrimSpace(c.Query(key)), 10, 64) + return value +} + +func parseIntQuery(c *gin.Context, key string, fallback int) int { + value, err := strconv.Atoi(strings.TrimSpace(c.Query(key))) + if err != nil || value <= 0 { + return fallback + } + return value +} diff --git a/server/admin/internal/modules/weeklystar/routes.go b/server/admin/internal/modules/weeklystar/routes.go new file mode 100644 index 00000000..9835d517 --- /dev/null +++ b/server/admin/internal/modules/weeklystar/routes.go @@ -0,0 +1,20 @@ +package weeklystar + +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/weekly-star/cycles", middleware.RequirePermission("weekly-star:view"), h.ListCycles) + protected.POST("/admin/activity/weekly-star/cycles", middleware.RequirePermission("weekly-star:create"), h.CreateCycle) + protected.GET("/admin/activity/weekly-star/cycles/:cycle_id", middleware.RequirePermission("weekly-star:view"), h.GetCycle) + protected.PUT("/admin/activity/weekly-star/cycles/:cycle_id", middleware.RequirePermission("weekly-star:update"), h.UpdateCycle) + protected.PATCH("/admin/activity/weekly-star/cycles/:cycle_id/status", middleware.RequirePermission("weekly-star:update"), h.SetCycleStatus) + protected.GET("/admin/activity/weekly-star/cycles/:cycle_id/leaderboard", middleware.RequirePermission("weekly-star:view"), h.ListLeaderboard) + protected.GET("/admin/activity/weekly-star/cycles/:cycle_id/settlements", middleware.RequirePermission("weekly-star:view"), h.ListSettlements) +} diff --git a/server/admin/internal/repository/seed.go b/server/admin/internal/repository/seed.go index 68fb881e..4e280a4c 100644 --- a/server/admin/internal/repository/seed.go +++ b/server/admin/internal/repository/seed.go @@ -124,6 +124,10 @@ var defaultPermissions = []model.Permission{ {Name: "VIP 配置查看", Code: "vip-config:view", Kind: "menu"}, {Name: "VIP 配置更新", Code: "vip-config:update", Kind: "button"}, {Name: "VIP 赠送", Code: "vip-config:grant", Kind: "button"}, + {Name: "周星配置查看", Code: "weekly-star:view", Kind: "menu"}, + {Name: "周星配置创建", Code: "weekly-star:create", Kind: "button"}, + {Name: "周星配置更新", Code: "weekly-star:update", Kind: "button"}, + {Name: "周星结算查看", Code: "weekly-star:settle", Kind: "button"}, {Name: "角色查看", Code: "role:view", Kind: "menu"}, {Name: "角色创建", Code: "role:create", Kind: "button"}, {Name: "角色更新", Code: "role:update", Kind: "button"}, @@ -174,18 +178,18 @@ func (s *Store) seedMenus() error { gameID := uint(0) menus := []model.Menu{ {Title: "总览", Code: "overview", Path: "/overview", Icon: "dashboard", PermissionCode: "overview:view", Sort: 10, Visible: true}, - {Title: "后台设置", Code: "system", Path: "", Icon: "settings", PermissionCode: "", Sort: 30, Visible: true}, - {Title: "日志审计", Code: "logs", Path: "", Icon: "history", PermissionCode: "", Sort: 40, Visible: false}, - {Title: "用户管理", Code: "app-users", Path: "", Icon: "users", PermissionCode: "", Sort: 60, Visible: true}, - {Title: "房间管理", Code: "rooms", Path: "", Icon: "room", PermissionCode: "", Sort: 65, Visible: true}, - {Title: "APP配置", Code: "app-config", Path: "", Icon: "settings", PermissionCode: "", Sort: 66, Visible: true}, - {Title: "资源管理", Code: "resources", Path: "", Icon: "inventory", PermissionCode: "", Sort: 67, Visible: true}, - {Title: "运营管理", Code: "operations", Path: "", Icon: "operations", PermissionCode: "", Sort: 68, Visible: true}, - {Title: "支付管理", Code: "payment", Path: "", Icon: "wallet", PermissionCode: "", Sort: 69, Visible: true}, - {Title: "活动管理", Code: "activities", Path: "", Icon: "campaign", PermissionCode: "", Sort: 70, Visible: true}, - {Title: "游戏管理", Code: "games", Path: "", Icon: "sports_esports", PermissionCode: "", Sort: 71, Visible: true}, - {Title: "地区管理", Code: "geo", Path: "", Icon: "map", PermissionCode: "", Sort: 72, Visible: true}, - {Title: "团队管理", Code: "host-org", Path: "", Icon: "network", PermissionCode: "", Sort: 80, Visible: true}, + {Title: "用户管理", Code: "app-users", Path: "", Icon: "users", PermissionCode: "", Sort: 20, Visible: true}, + {Title: "团队管理", Code: "host-org", Path: "", Icon: "network", PermissionCode: "", Sort: 30, Visible: true}, + {Title: "房间管理", Code: "rooms", Path: "", Icon: "room", PermissionCode: "", Sort: 40, Visible: true}, + {Title: "APP配置", Code: "app-config", Path: "", Icon: "settings", PermissionCode: "", Sort: 50, Visible: true}, + {Title: "资源管理", Code: "resources", Path: "", Icon: "inventory", PermissionCode: "", Sort: 60, Visible: true}, + {Title: "运营管理", Code: "operations", Path: "", Icon: "operations", PermissionCode: "", Sort: 70, Visible: true}, + {Title: "支付管理", Code: "payment", Path: "", Icon: "wallet", PermissionCode: "", Sort: 80, Visible: true}, + {Title: "活动管理", Code: "activities", Path: "", Icon: "campaign", PermissionCode: "", Sort: 90, Visible: true}, + {Title: "游戏管理", Code: "games", Path: "", Icon: "sports_esports", PermissionCode: "", Sort: 100, Visible: true}, + {Title: "地区管理", Code: "geo", Path: "", Icon: "map", PermissionCode: "", Sort: 110, Visible: true}, + {Title: "后台设置", Code: "system", Path: "", Icon: "settings", PermissionCode: "", Sort: 120, Visible: true}, + {Title: "日志审计", Code: "logs", Path: "", Icon: "history", PermissionCode: "", Sort: 130, Visible: false}, } for _, menu := range menus { syncedMenu, err := s.syncDefaultMenu(s.db, menu) @@ -267,6 +271,7 @@ func (s *Store) seedMenus() error { {ParentID: &activityID, Title: "用户榜单", Code: "user-leaderboard", Path: "/activities/user-leaderboards", Icon: "leaderboard", PermissionCode: "user-leaderboard:view", Sort: 74, Visible: true}, {ParentID: &activityID, Title: "红包配置", Code: "red-packet", Path: "/activities/red-packets", Icon: "redeem", PermissionCode: "red-packet:view", Sort: 75, Visible: true}, {ParentID: &activityID, Title: "VIP配置", Code: "vip-config", Path: "/activities/vip-config", Icon: "workspace_premium", PermissionCode: "vip-config:view", Sort: 76, Visible: true}, + {ParentID: &activityID, Title: "周星配置", Code: "weekly-star", Path: "/activities/weekly-star", Icon: "star", PermissionCode: "weekly-star:view", Sort: 78, Visible: true}, {ParentID: &gameID, Title: "游戏列表", Code: "game-list", Path: "/games", Icon: "sports_esports", PermissionCode: "game:view", Sort: 70, Visible: true}, {ParentID: &geoID, Title: "国家管理", Code: "host-org-countries", Path: "/host/countries", Icon: "public", PermissionCode: "country:view", Sort: 70, Visible: true}, {ParentID: &geoID, Title: "区域管理", Code: "host-org-regions", Path: "/host/regions", Icon: "map", PermissionCode: "region:view", Sort: 71, Visible: true}, @@ -513,12 +518,13 @@ func defaultRolePermissionCodes(code string) []string { "room-rocket:view", "room-rocket:update", "red-packet:view", "red-packet:update", "vip-config:view", "vip-config:update", "vip-config:grant", + "weekly-star:view", "weekly-star:create", "weekly-star:update", "weekly-star:settle", "log:view", "job:view", "job:cancel", "export:create", "upload:create", } case "auditor": - return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view", "role:view", "permission:view", "job:view"} + return []string{"overview:view", "log:view", "user:view", "app-user:view", "level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view", "weekly-star:view", "role:view", "permission:view", "job:view"} case "readonly": return []string{ "overview:view", @@ -561,6 +567,7 @@ func defaultRolePermissionCodes(code string) []string { "room-rocket:view", "red-packet:view", "vip-config:view", + "weekly-star:view", "role:view", "permission:view", "menu:view", @@ -602,9 +609,10 @@ func defaultRolePermissionMigrationCodes(code string) []string { "room-rocket:view", "room-rocket:update", "red-packet:view", "red-packet:update", "vip-config:view", "vip-config:update", "vip-config:grant", + "weekly-star:view", "weekly-star:create", "weekly-star:update", "weekly-star:settle", } case "auditor", "readonly": - return []string{"level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view"} + return []string{"level-config:view", "region-block:view", "room:view", "room-pin:view", "room-config:view", "app-config:view", "app-version:view", "resource:view", "resource-shop:view", "resource-group:view", "resource-grant:view", "gift:view", "emoji-pack:view", "host-agency-policy:view", "team-salary-policy:view", "host-salary-settlement:view", "coin-seller:view", "coin-ledger:view", "coin-seller-ledger:view", "coin-adjustment:view", "report:view", "gift-diamond:view", "lucky-gift:view", "payment-bill:view", "payment-product:view", "game:view", "daily-task:view", "achievement:view", "seven-day-checkin:view", "room-rocket:view", "red-packet:view", "vip-config:view", "weekly-star:view"} default: return nil } diff --git a/server/admin/internal/router/router.go b/server/admin/internal/router/router.go index 40a4b2bc..2565af57 100644 --- a/server/admin/internal/router/router.go +++ b/server/admin/internal/router/router.go @@ -12,6 +12,7 @@ import ( authroutes "hyapp-admin-server/internal/modules/auth" "hyapp-admin-server/internal/modules/coinledger" "hyapp-admin-server/internal/modules/countryregion" + "hyapp-admin-server/internal/modules/cumulativerechargereward" "hyapp-admin-server/internal/modules/dailytask" "hyapp-admin-server/internal/modules/dashboard" "hyapp-admin-server/internal/modules/firstrechargereward" @@ -34,6 +35,7 @@ import ( resourcemodule "hyapp-admin-server/internal/modules/resource" "hyapp-admin-server/internal/modules/roomadmin" "hyapp-admin-server/internal/modules/roomrocket" + "hyapp-admin-server/internal/modules/roomturnoverreward" "hyapp-admin-server/internal/modules/search" "hyapp-admin-server/internal/modules/sevendaycheckin" "hyapp-admin-server/internal/modules/teamsalarypolicy" @@ -41,6 +43,7 @@ import ( "hyapp-admin-server/internal/modules/upload" "hyapp-admin-server/internal/modules/userleaderboard" "hyapp-admin-server/internal/modules/vipconfig" + "hyapp-admin-server/internal/modules/weeklystar" "hyapp-admin-server/internal/platform/logging" "hyapp-admin-server/internal/service" @@ -57,6 +60,7 @@ type Handlers struct { Auth *authroutes.Handler CoinLedger *coinledger.Handler CountryRegion *countryregion.Handler + CumulativeRecharge *cumulativerechargereward.Handler DailyTask *dailytask.Handler Dashboard *dashboard.Handler FirstRechargeReward *firstrechargereward.Handler @@ -79,6 +83,7 @@ type Handlers struct { Resource *resourcemodule.Handler RoomAdmin *roomadmin.Handler RoomRocket *roomrocket.Handler + RoomTurnoverReward *roomturnoverreward.Handler Search *search.Handler SevenDayCheckIn *sevendaycheckin.Handler TeamSalaryPolicy *teamsalarypolicy.Handler @@ -86,6 +91,7 @@ type Handlers struct { Upload *upload.Handler UserLeaderboard *userleaderboard.Handler VIPConfig *vipconfig.Handler + WeeklyStar *weeklystar.Handler } func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { @@ -112,6 +118,7 @@ func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { appregistry.RegisterRoutes(protected, h.AppRegistry) appconfig.RegisterRoutes(protected, h.AppConfig) countryregion.RegisterRoutes(protected, h.CountryRegion) + cumulativerechargereward.RegisterRoutes(protected, h.CumulativeRecharge) dailytask.RegisterRoutes(protected, h.DailyTask) firstrechargereward.RegisterRoutes(protected, h.FirstRechargeReward) registrationreward.RegisterRoutes(protected, h.RegistrationReward) @@ -120,6 +127,7 @@ func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { giftdiamond.RegisterRoutes(protected, h.GiftDiamond) roomadmin.RegisterRoutes(protected, h.RoomAdmin) roomrocket.RegisterRoutes(protected, h.RoomRocket) + roomturnoverreward.RegisterRoutes(protected, h.RoomTurnoverReward) dashboard.RegisterRoutes(protected, h.Dashboard) hostagencypolicy.RegisterRoutes(protected, h.HostAgencyPolicy) hostsalarysettlement.RegisterRoutes(protected, h.HostSalarySettlement) @@ -136,6 +144,7 @@ func New(cfg config.Config, auth *service.AuthService, h Handlers) *gin.Engine { teamsalarysettlement.RegisterRoutes(protected, h.TeamSalarySettlement) userleaderboard.RegisterRoutes(protected, h.UserLeaderboard) vipconfig.RegisterRoutes(protected, h.VIPConfig) + weeklystar.RegisterRoutes(protected, h.WeeklyStar) return engine } diff --git a/server/admin/migrations/036_room_turnover_reward_navigation.sql b/server/admin/migrations/036_room_turnover_reward_navigation.sql new file mode 100644 index 00000000..144112ea --- /dev/null +++ b/server/admin/migrations/036_room_turnover_reward_navigation.sql @@ -0,0 +1,60 @@ +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 + ('房间流水奖励查看', 'room-turnover-reward:view', 'menu', '', @now_ms, @now_ms), + ('房间流水奖励更新', 'room-turnover-reward:update', 'button', '', @now_ms, @now_ms), + ('房间流水奖励重试', 'room-turnover-reward:retry', '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, '房间流水奖励', 'room-turnover-reward', '/activities/room-turnover-reward', 'paid', 'room-turnover-reward:view', 77, 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 ('room-turnover-reward:view', 'room-turnover-reward:update', 'room-turnover-reward:retry'); + +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 ('room-turnover-reward:view', 'room-turnover-reward:update', 'room-turnover-reward:retry'); + +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 = 'room-turnover-reward:view'; diff --git a/server/admin/migrations/037_weekly_star_navigation.sql b/server/admin/migrations/037_weekly_star_navigation.sql new file mode 100644 index 00000000..a520efd7 --- /dev/null +++ b/server/admin/migrations/037_weekly_star_navigation.sql @@ -0,0 +1,61 @@ +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 + ('周星配置查看', 'weekly-star:view', 'menu', '', @now_ms, @now_ms), + ('周星配置创建', 'weekly-star:create', 'button', '', @now_ms, @now_ms), + ('周星配置更新', 'weekly-star:update', 'button', '', @now_ms, @now_ms), + ('周星结算查看', 'weekly-star:settle', '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, '周星配置', 'weekly-star', '/activities/weekly-star', 'star', 'weekly-star:view', 78, 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 ('weekly-star:view', 'weekly-star:create', 'weekly-star:update', 'weekly-star:settle'); + +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 ('weekly-star:view', 'weekly-star:create', 'weekly-star:update', 'weekly-star:settle'); + +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 = 'weekly-star:view'; diff --git a/server/admin/migrations/038_cumulative_recharge_reward_navigation.sql b/server/admin/migrations/038_cumulative_recharge_reward_navigation.sql new file mode 100644 index 00000000..a3e9ea40 --- /dev/null +++ b/server/admin/migrations/038_cumulative_recharge_reward_navigation.sql @@ -0,0 +1,59 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 累充奖励事实由 activity-service 按 UTC 周期累计和发奖;后台只维护后续事件使用的档位配置并查看发放记录。 +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 + ('累充奖励查看', 'cumulative-recharge-reward:view', 'menu', '', @now_ms, @now_ms), + ('累充奖励更新', 'cumulative-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, '累充奖励配置', 'cumulative-recharge-reward', '/activities/cumulative-recharge-reward', 'workspace_premium', 'cumulative-recharge-reward:view', 79, 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 ('cumulative-recharge-reward:view', 'cumulative-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 ('cumulative-recharge-reward:view', 'cumulative-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 = 'cumulative-recharge-reward:view'; diff --git a/server/admin/migrations/039_admin_parent_menu_order.sql b/server/admin/migrations/039_admin_parent_menu_order.sql new file mode 100644 index 00000000..946f2cc0 --- /dev/null +++ b/server/admin/migrations/039_admin_parent_menu_order.sql @@ -0,0 +1,39 @@ +SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci; + +-- 左侧父级菜单顺序直接影响后台入口效率:团队管理靠近用户管理,后台设置固定沉到底部。 +SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED); + +UPDATE admin_menus +SET sort = CASE code + WHEN 'overview' THEN 10 + WHEN 'app-users' THEN 20 + WHEN 'host-org' THEN 30 + WHEN 'rooms' THEN 40 + WHEN 'app-config' THEN 50 + WHEN 'resources' THEN 60 + WHEN 'operations' THEN 70 + WHEN 'payment' THEN 80 + WHEN 'activities' THEN 90 + WHEN 'games' THEN 100 + WHEN 'geo' THEN 110 + WHEN 'system' THEN 120 + WHEN 'logs' THEN 130 + ELSE sort + END, + updated_at_ms = @now_ms +WHERE parent_id IS NULL + AND code IN ( + 'overview', + 'app-users', + 'host-org', + 'rooms', + 'app-config', + 'resources', + 'operations', + 'payment', + 'activities', + 'games', + 'geo', + 'system', + 'logs' + ); diff --git a/services/activity-service/configs/config.docker.yaml b/services/activity-service/configs/config.docker.yaml index a3a14c1a..032186fe 100644 --- a/services/activity-service/configs/config.docker.yaml +++ b/services/activity-service/configs/config.docker.yaml @@ -12,9 +12,12 @@ health_http_addr: ":13106" mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC" user_service_addr: "user-service:13005" wallet_service_addr: "wallet-service:13004" +room_service_addr: "room-service:13001" mysql_auto_migrate: true first_recharge_reward_worker: enabled: false +cumulative_recharge_reward_worker: + enabled: true red_packet_broadcast_worker: enabled: true lucky_gift_worker: @@ -64,6 +67,7 @@ rocketmq: topic: "hyapp_wallet_outbox" realtime_topic: "hyapp_wallet_realtime_outbox" first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" + cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 user_outbox: diff --git a/services/activity-service/configs/config.tencent.example.yaml b/services/activity-service/configs/config.tencent.example.yaml index 1bedba25..c39902e7 100644 --- a/services/activity-service/configs/config.tencent.example.yaml +++ b/services/activity-service/configs/config.tencent.example.yaml @@ -12,9 +12,12 @@ health_http_addr: ":13106" mysql_dsn: "USER:PASSWORD@tcp(TENCENT_CDB_HOST:3306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC&tls=false" user_service_addr: "user-service.internal:13005" wallet_service_addr: "wallet-service.internal:13004" +room_service_addr: "room-service.internal:13001" mysql_auto_migrate: false first_recharge_reward_worker: enabled: true +cumulative_recharge_reward_worker: + enabled: true red_packet_broadcast_worker: enabled: true lucky_gift_worker: @@ -63,6 +66,7 @@ rocketmq: topic: "hyapp_wallet_outbox" realtime_topic: "hyapp_wallet_realtime_outbox" first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" + cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 user_outbox: diff --git a/services/activity-service/configs/config.yaml b/services/activity-service/configs/config.yaml index fa217608..29049def 100644 --- a/services/activity-service/configs/config.yaml +++ b/services/activity-service/configs/config.yaml @@ -12,9 +12,12 @@ health_http_addr: ":13106" mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC" user_service_addr: "127.0.0.1:13005" wallet_service_addr: "127.0.0.1:13004" +room_service_addr: "127.0.0.1:13001" mysql_auto_migrate: true first_recharge_reward_worker: enabled: false +cumulative_recharge_reward_worker: + enabled: false red_packet_broadcast_worker: enabled: false lucky_gift_worker: @@ -63,6 +66,7 @@ rocketmq: topic: "hyapp_wallet_outbox" realtime_topic: "" first_recharge_consumer_group: "hyapp-activity-first-recharge-wallet-outbox" + cumulative_recharge_consumer_group: "hyapp-activity-cumulative-recharge-wallet-outbox" red_packet_broadcast_consumer_group: "hyapp-activity-red-packet-wallet-outbox" consumer_max_reconsume_times: 16 user_outbox: 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 8192c27f..7cc95271 100644 --- a/services/activity-service/deploy/mysql/initdb/001_activity_service.sql +++ b/services/activity-service/deploy/mysql/initdb/001_activity_service.sql @@ -183,6 +183,7 @@ CREATE TABLE IF NOT EXISTS lucky_draw_records ( device_id VARCHAR(128) NOT NULL COMMENT '设备 ID', room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', anchor_id VARCHAR(96) NOT NULL COMMENT '主播关联 ID', + visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域 ID', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID', coin_spent BIGINT NOT NULL COMMENT '消耗金币', @@ -213,6 +214,7 @@ CREATE TABLE IF NOT EXISTS lucky_draw_records ( KEY idx_lucky_draw_user (app_code, user_id, created_at_ms), KEY idx_lucky_draw_gift (app_code, gift_id, created_at_ms), KEY idx_lucky_draw_room (app_code, room_id, created_at_ms), + KEY idx_lucky_draw_region_created (app_code, visible_region_id, created_at_ms, draw_id), KEY idx_lucky_draw_status (app_code, reward_status, updated_at_ms), KEY idx_lucky_draw_created (app_code, created_at_ms, draw_id), KEY idx_lucky_draw_pool_status_summary (app_code, pool_id, reward_status, created_at_ms, draw_id), @@ -239,6 +241,24 @@ CREATE TABLE IF NOT EXISTS lucky_draw_pool_stats ( PRIMARY KEY (app_code, pool_id, gift_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物池级汇总统计'; +CREATE TABLE IF NOT EXISTS lucky_draw_pool_day_stats ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + stat_day DATE NOT NULL COMMENT 'UTC 统计日', + visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域 ID', + pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', + gift_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '礼物 ID,空值表示奖池汇总', + draw_count BIGINT NOT NULL DEFAULT 0 COMMENT '抽奖次数', + turnover_coin BIGINT NOT NULL DEFAULT 0 COMMENT '消耗金币', + payout_coin BIGINT NOT NULL DEFAULT 0 COMMENT '用户可见返奖金币', + base_reward_coin BIGINT NOT NULL DEFAULT 0 COMMENT '基础 RTP 返奖', + room_atmosphere_reward_coin BIGINT NOT NULL DEFAULT 0 COMMENT '房间气氛支出', + activity_subsidy_coin 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, stat_day, visible_region_id, pool_id, gift_id), + KEY idx_lucky_draw_pool_day_overview (app_code, stat_day, pool_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物 Databi 日维度汇总'; + CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_users ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', @@ -483,6 +503,92 @@ CREATE TABLE IF NOT EXISTS first_recharge_reward_claims ( 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 cumulative_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 cumulative_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 '档位名称', + threshold_usd_minor BIGINT NOT NULL COMMENT '达标美元金额,美分', + 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_cumulative_recharge_reward_tier_code (app_code, tier_code), + KEY idx_cumulative_recharge_reward_tier_sort (app_code, status, sort_order, threshold_usd_minor) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励档位表'; + +CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_events ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + event_id VARCHAR(128) NOT NULL COMMENT 'wallet_outbox 事件 ID', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周', + user_id BIGINT NOT NULL COMMENT '用户 ID', + transaction_id VARCHAR(128) NOT NULL COMMENT '钱包交易 ID', + command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID', + recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源类型', + recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本次到账金币', + qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '本次计入累充的美元美分', + payload_json JSON NULL COMMENT 'wallet 事件 payload', + occurred_at_ms BIGINT NOT NULL COMMENT '充值发生时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_cumulative_recharge_reward_event_user_cycle (app_code, cycle_key, user_id, occurred_at_ms), + KEY idx_cumulative_recharge_reward_event_transaction (app_code, transaction_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励充值事件幂等表'; + +CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_progress ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周', + user_id BIGINT NOT NULL COMMENT '用户 ID', + total_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计美元美分', + total_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计到账金币', + first_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期首笔充值时间', + last_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期最近充值时间', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, cycle_key, user_id), + KEY idx_cumulative_recharge_reward_progress_total (app_code, cycle_key, total_usd_minor) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励用户周期累计表'; + +CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_grants ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离', + grant_id VARCHAR(128) NOT NULL COMMENT '发放 ID', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周', + user_id BIGINT NOT NULL COMMENT '用户 ID', + event_id VARCHAR(128) NOT NULL COMMENT '触发发放的 wallet_outbox 事件 ID', + transaction_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包交易 ID', + command_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包命令 ID', + tier_id BIGINT NOT NULL COMMENT '命中奖励档位 ID', + tier_code VARCHAR(64) NOT NULL COMMENT '命中奖励档位编码', + threshold_usd_minor BIGINT NOT NULL COMMENT '命中档位门槛,美分', + resource_group_id BIGINT NOT NULL COMMENT '奖励资源分组 ID', + reached_usd_minor BIGINT NOT NULL COMMENT '命中时累计金额,美分', + qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '触发事件计入金额,美分', + recharge_coin_amount BIGINT NOT NULL DEFAULT 0 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(512) NOT NULL DEFAULT '' COMMENT '失败原因', + 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, grant_id), + UNIQUE KEY uk_cumulative_recharge_reward_user_tier (app_code, cycle_key, user_id, tier_id), + UNIQUE KEY uk_cumulative_recharge_reward_wallet_command (app_code, wallet_command_id), + KEY idx_cumulative_recharge_reward_grant_event (app_code, event_id, status), + KEY idx_cumulative_recharge_reward_grant_user (app_code, cycle_key, user_id, created_at_ms), + KEY idx_cumulative_recharge_reward_grant_status (app_code, status, created_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 '启用', @@ -993,3 +1099,169 @@ INSERT IGNORE INTO lucky_gift_stage_tiers ( ('lalu', 'super_lucky', 1, 'advanced', 'advanced_1x', 1000000, 600000, 'base_rtp', false, 'none', true), ('lalu', 'super_lucky', 1, 'advanced', 'advanced_2x', 2000000, 100000, 'base_rtp', false, 'none', true), ('lalu', 'super_lucky', 1, 'advanced', 'advanced_5x', 5000000, 30000, 'base_rtp', false, 'none', true); + +CREATE TABLE IF NOT EXISTS room_turnover_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 '最后更新管理员', + 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 room_turnover_reward_tiers ( + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '档位 ID', + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + tier_code VARCHAR(64) NOT NULL COMMENT '档位编码', + tier_name VARCHAR(128) NOT NULL COMMENT '档位名称', + threshold_coin_spent BIGINT NOT NULL COMMENT '命中该档需要的房间送礼金币流水', + reward_coin_amount BIGINT NOT NULL COMMENT '奖励房主金币数', + status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', + 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', + PRIMARY KEY (tier_id), + UNIQUE KEY uk_room_turnover_reward_tier_code (app_code, tier_code), + KEY idx_room_turnover_reward_tiers_match (app_code, status, threshold_coin_spent) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励档位表'; + +CREATE TABLE IF NOT EXISTS room_turnover_reward_event_consumption ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id', + event_type VARCHAR(96) NOT NULL COMMENT '事件类型', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + coin_spent BIGINT NOT NULL COMMENT '本事件送礼金币消耗', + status VARCHAR(32) NOT NULL COMMENT '消费状态', + consumed_at_ms BIGINT NOT NULL 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, event_id), + KEY idx_room_turnover_reward_event_period (app_code, period_start_ms, room_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励事件消费幂等表'; + +CREATE TABLE IF NOT EXISTS room_turnover_reward_progress ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束', + coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '本周期房间送礼金币流水', + last_event_at_ms 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, room_id, period_start_ms), + KEY idx_room_turnover_reward_progress_period (app_code, period_start_ms, coin_spent) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励周期聚合表'; + +CREATE TABLE IF NOT EXISTS room_turnover_reward_settlements ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + settlement_id VARCHAR(96) NOT NULL COMMENT '结算 ID', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '结算收款房主', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束', + coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '周期房间流水', + tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位 ID', + tier_code VARCHAR(64) NOT NULL DEFAULT '' COMMENT '命中档位编码', + threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位阈值', + reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '发放金币', + status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/granted/failed', + wallet_command_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT 'wallet-service 幂等命令 ID', + wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID', + failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因', + settled_at_ms 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, settlement_id), + UNIQUE KEY uk_room_turnover_reward_settlement_room_period (app_code, room_id, period_start_ms), + KEY idx_room_turnover_reward_settlement_status (app_code, status, period_start_ms, created_at_ms), + KEY idx_room_turnover_reward_settlement_owner (app_code, owner_user_id, period_start_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励每周结算表'; + +CREATE TABLE IF NOT EXISTS weekly_star_cycles ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + activity_code VARCHAR(64) NOT NULL DEFAULT 'weekly_star' COMMENT '活动编码', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域 ID,0 表示默认配置', + title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '周期标题', + status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '状态', + start_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效开始,包含', + end_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效结束,不包含', + created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员', + updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员', + settled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '结算完成时间', + locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '结算 worker 锁', + lock_until_ms 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, cycle_id), + KEY idx_weekly_star_cycle_current (app_code, activity_code, status, region_id, start_ms, end_ms), + KEY idx_weekly_star_cycle_due (app_code, activity_code, status, end_ms, lock_until_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星指定礼物积分周期'; + +CREATE TABLE IF NOT EXISTS weekly_star_cycle_gifts ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + gift_id VARCHAR(96) NOT NULL COMMENT '参与计分礼物 ID', + sort_order INT NOT NULL DEFAULT 0 COMMENT '展示顺序', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, cycle_id, gift_id), + KEY idx_weekly_star_gift_match (app_code, gift_id, cycle_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期指定礼物'; + +CREATE TABLE IF NOT EXISTS weekly_star_cycle_rewards ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + rank_no INT NOT NULL COMMENT '排名,1/2/3', + resource_group_id BIGINT NOT NULL 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, cycle_id, rank_no) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期 Top 奖励'; + +CREATE TABLE IF NOT EXISTS weekly_star_user_scores ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + score BIGINT NOT NULL DEFAULT 0 COMMENT '累计积分,等于活动礼物消耗金币', + first_scored_at_ms BIGINT NOT NULL COMMENT '首次得分时间', + last_scored_at_ms BIGINT NOT NULL 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, cycle_id, user_id), + KEY idx_weekly_star_score_rank (app_code, cycle_id, score, first_scored_at_ms, user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星用户积分榜'; + +CREATE TABLE IF NOT EXISTS weekly_star_score_events ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + source_event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + user_id BIGINT NOT NULL COMMENT '送礼用户 ID', + gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID', + score_delta BIGINT NOT NULL COMMENT '本次增加积分', + occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, source_event_id), + KEY idx_weekly_star_score_event_cycle (app_code, cycle_id, user_id, occurred_at_ms) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星送礼积分事件幂等表'; + +CREATE TABLE IF NOT EXISTS weekly_star_settlements ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + settlement_id VARCHAR(96) NOT NULL COMMENT '周星结算 ID', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + rank_no INT NOT NULL COMMENT '排名,1/2/3', + user_id BIGINT NOT NULL COMMENT '获奖用户 ID', + score BIGINT NOT NULL DEFAULT 0 COMMENT '结算积分', + resource_group_id BIGINT NOT NULL COMMENT '奖励资源组 ID', + wallet_command_id VARCHAR(128) NOT NULL COMMENT 'wallet 幂等命令', + wallet_grant_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'wallet grant ID', + status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '发放状态', + failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因', + attempt_count 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', + PRIMARY KEY (app_code, settlement_id), + UNIQUE KEY uk_weekly_star_settlement_rank (app_code, cycle_id, rank_no), + UNIQUE KEY uk_weekly_star_wallet_command (app_code, wallet_command_id), + KEY idx_weekly_star_settlement_cycle (app_code, cycle_id, status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星 Top 奖励结算'; diff --git a/services/activity-service/internal/app/app.go b/services/activity-service/internal/app/app.go index 7db6a46b..d3fce4d6 100644 --- a/services/activity-service/internal/app/app.go +++ b/services/activity-service/internal/app/app.go @@ -2,7 +2,6 @@ package app import ( "context" - "encoding/json" "errors" "log/slog" "net" @@ -10,39 +9,21 @@ import ( "time" "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - healthgrpc "google.golang.org/grpc/health/grpc_health_v1" - activityv1 "hyapp.local/api/proto/activity/v1" - walletv1 "hyapp.local/api/proto/wallet/v1" - "hyapp/pkg/appcode" "hyapp/pkg/grpchealth" "hyapp/pkg/grpcshutdown" "hyapp/pkg/healthhttp" "hyapp/pkg/logx" "hyapp/pkg/rocketmqx" - "hyapp/pkg/roommq" - "hyapp/pkg/tencentim" - "hyapp/pkg/usermq" - "hyapp/pkg/walletmq" - "hyapp/services/activity-service/internal/client" "hyapp/services/activity-service/internal/config" - broadcastdomain "hyapp/services/activity-service/internal/domain/broadcast" - firstrechargedomain "hyapp/services/activity-service/internal/domain/firstrecharge" - achievementservice "hyapp/services/activity-service/internal/service/achievement" - activityservice "hyapp/services/activity-service/internal/service/activity" broadcastservice "hyapp/services/activity-service/internal/service/broadcast" + cumulativerechargeservice "hyapp/services/activity-service/internal/service/cumulativerecharge" 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" - registrationrewardservice "hyapp/services/activity-service/internal/service/registrationreward" - sevendaycheckinservice "hyapp/services/activity-service/internal/service/sevendaycheckin" - taskservice "hyapp/services/activity-service/internal/service/task" mysqlstorage "hyapp/services/activity-service/internal/storage/mysql" - grpcserver "hyapp/services/activity-service/internal/transport/grpc" ) -// App 装配 activity-service gRPC 入口和底座依赖。 +// App 装配 activity-service 的 gRPC 入口、健康检查、后台 worker 和外部连接。 +// 具体业务模块的创建和注册都放在独立文件里,避免启动入口继续膨胀成一个难维护的大函数。 type App struct { server *grpc.Server listener net.Listener @@ -52,6 +33,7 @@ type App struct { broadcast *broadcastservice.Service luckyGift *luckygiftservice.Service firstRechargeReward *firstrechargeservice.Service + cumulativeRecharge *cumulativerechargeservice.Service broadcastWorkerEnabled bool luckyGiftWorkerEnabled bool workerNodeID string @@ -59,6 +41,7 @@ type App struct { mqConsumers []*rocketmqx.Consumer userConn *grpc.ClientConn walletConn *grpc.ClientConn + roomConn *grpc.ClientConn workerCtx context.Context workerStop context.CancelFunc workerWG sync.WaitGroup @@ -70,254 +53,71 @@ func New(cfg config.Config) (*App, error) { startupCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - // activity-service 的活动状态、消费幂等和 outbox 都必须使用 MySQL。 - repository, err := mysqlstorage.Open(startupCtx, cfg.MySQLDSN) + repository, err := openRepository(startupCtx, cfg) if err != nil { return nil, err } - if cfg.MySQLAutoMigrate { - if err := repository.Migrate(startupCtx); err != nil { - _ = repository.Close() - return nil, err + var listener net.Listener + var clients externalClients + var mqConsumers []*rocketmqx.Consumer + cleanup := func() { + shutdownConsumers(mqConsumers) + clients.Close() + if listener != nil { + _ = listener.Close() } + _ = repository.Close() } - listener, err := net.Listen("tcp", cfg.GRPCAddr) + listener, err = listenGRPC(cfg.GRPCAddr) if err != nil { - _ = repository.Close() + cleanup() return nil, err } - userConn, err := grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + clients, err = dialExternalClients(cfg) if err != nil { - _ = listener.Close() - _ = repository.Close() - return nil, err - } - walletConn, err := grpc.Dial(cfg.WalletServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) - if err != nil { - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() + cleanup() return nil, err } server := grpc.NewServer(grpc.UnaryInterceptor(logx.UnaryServerInterceptor("activity-service"))) - svc := activityservice.New(activityservice.Config{NodeID: cfg.NodeID}, repository) - messageSvc := messageservice.New(messageservice.Config{NodeID: cfg.NodeID}, repository, messageservice.WithTargetSource(client.NewGRPCUserTargetSource(userConn))) - taskSvc := taskservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - registrationRewardSvc := registrationrewardservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - sevenDayCheckInSvc := sevendaycheckinservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - growthSvc := growthservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - achievementSvc := achievementservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - var tencentClient *tencentim.RESTClient - var broadcastPublisher broadcastservice.Publisher - if cfg.TencentIM.Enabled { - tencentClient, err = tencentim.NewRESTClient(cfg.TencentIM.RESTConfig()) - if err != nil { - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - broadcastPublisher = tencentClient - } - if cfg.Broadcast.Enabled && broadcastPublisher == nil { - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, errors.New("broadcast worker requires tencent_im.enabled") - } - broadcastSvc := broadcastservice.New(broadcastservice.Config{ - NodeID: cfg.NodeID, - SuperGiftMinValue: cfg.Broadcast.SuperGiftMinValue, - WorkerBatchSize: cfg.Broadcast.WorkerBatchSize, - WorkerLockTTL: cfg.Broadcast.WorkerLockTTL, - WorkerMaxRetry: cfg.Broadcast.WorkerMaxRetry, - WorkerPollInterval: cfg.Broadcast.WorkerPollInterval, - EnsureGroupsOnStartup: cfg.Broadcast.EnsureGroupsOnStartup, - GroupIDPrefix: cfg.TencentIM.GroupIDPrefix, - }, repository, broadcastPublisher, client.NewGRPCRegionSource(userConn)) - broadcastSvc.SetSenderProfileSource(client.NewGRPCUserProfileSource(userConn)) - luckyGiftSvc := luckygiftservice.New(repository, - luckygiftservice.WithWallet(walletv1.NewWalletServiceClient(walletConn)), - luckygiftservice.WithRoomPublisher(tencentClient), - luckygiftservice.WithRegionBroadcaster(broadcastSvc), - ) - activityv1.RegisterActivityServiceServer(server, grpcserver.NewServer(svc)) - activityv1.RegisterMessageInboxServiceServer(server, grpcserver.NewMessageServer(messageSvc)) - activityv1.RegisterActivityCronServiceServer(server, grpcserver.NewCronServer(messageSvc, growthSvc, achievementSvc)) - activityv1.RegisterTaskServiceServer(server, grpcserver.NewTaskServer(taskSvc)) - activityv1.RegisterAdminTaskServiceServer(server, grpcserver.NewAdminTaskServer(taskSvc)) - activityv1.RegisterGrowthLevelServiceServer(server, grpcserver.NewGrowthLevelServer(growthSvc)) - activityv1.RegisterAdminGrowthLevelServiceServer(server, grpcserver.NewAdminGrowthLevelServer(growthSvc)) - activityv1.RegisterAchievementServiceServer(server, grpcserver.NewAchievementServer(achievementSvc)) - activityv1.RegisterAdminAchievementServiceServer(server, grpcserver.NewAdminAchievementServer(achievementSvc)) - activityv1.RegisterLuckyGiftServiceServer(server, grpcserver.NewLuckyGiftServer(luckyGiftSvc)) - activityv1.RegisterAdminLuckyGiftServiceServer(server, grpcserver.NewAdminLuckyGiftServer(luckyGiftSvc)) - activityv1.RegisterRegistrationRewardServiceServer(server, grpcserver.NewRegistrationRewardServer(registrationRewardSvc)) - activityv1.RegisterAdminRegistrationRewardServiceServer(server, grpcserver.NewAdminRegistrationRewardServer(registrationRewardSvc)) - activityv1.RegisterSevenDayCheckInServiceServer(server, grpcserver.NewSevenDayCheckInServer(sevenDayCheckInSvc)) - activityv1.RegisterAdminSevenDayCheckInServiceServer(server, grpcserver.NewAdminSevenDayCheckInServer(sevenDayCheckInSvc)) - broadcastServer := grpcserver.NewBroadcastServer(broadcastSvc, growthSvc) - activityv1.RegisterBroadcastServiceServer(server, broadcastServer) - activityv1.RegisterRoomEventConsumerServiceServer(server, broadcastServer) - firstRechargeRewardSvc := firstrechargeservice.New(repository, walletv1.NewWalletServiceClient(walletConn)) - activityv1.RegisterFirstRechargeRewardServiceServer(server, grpcserver.NewFirstRechargeRewardServer(firstRechargeRewardSvc)) - activityv1.RegisterAdminFirstRechargeRewardServiceServer(server, grpcserver.NewAdminFirstRechargeRewardServer(firstRechargeRewardSvc)) - mqConsumers := make([]*rocketmqx.Consumer, 0, 4) - if cfg.RocketMQ.RoomOutbox.Enabled { - consumer, err := rocketmqx.NewConsumer(roomOutboxConsumerConfig(cfg.RocketMQ)) - if err != nil { - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - if err := consumer.Subscribe(cfg.RocketMQ.RoomOutbox.Topic, roommq.TagRoomOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { - envelope, _, err := roommq.DecodeRoomOutboxMessage(message.Body) - if err != nil { - return err - } - eventCtx := appcode.WithContext(ctx, envelope.GetAppCode()) - if _, err := broadcastSvc.HandleRoomEvent(eventCtx, envelope); err != nil { - return err - } - _, err = growthSvc.HandleRoomEvent(eventCtx, envelope) - return err - }); err != nil { - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - mqConsumers = append(mqConsumers, consumer) - } - if cfg.RocketMQ.UserOutbox.Enabled && broadcastPublisher == nil { - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, errors.New("rocketmq user_outbox consumer requires tencent_im.enabled") - } - if cfg.RocketMQ.UserOutbox.Enabled { - consumer, err := rocketmqx.NewConsumer(userOutboxConsumerConfig(cfg.RocketMQ)) - if err != nil { - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - if err := consumer.Subscribe(cfg.RocketMQ.UserOutbox.Topic, usermq.TagUserOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { - outboxMessage, err := usermq.DecodeUserOutboxMessage(message.Body) - if err != nil { - return err - } - return consumeUserRegionChangedForBroadcast(ctx, broadcastSvc, outboxMessage) - }); err != nil { - _ = consumer.Shutdown() - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - mqConsumers = append(mqConsumers, consumer) - } - if cfg.FirstRechargeRewardWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { - consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.FirstRechargeConsumerGroup)) - if err != nil { - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - if err := consumer.Subscribe(cfg.RocketMQ.WalletOutbox.Topic, walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { - event, ok, err := firstRechargeEventFromWalletMessage(message.Body) - if err != nil || !ok { - return err - } - return firstRechargeRewardSvc.ConsumeWalletRechargeEvent(appcode.WithContext(ctx, event.AppCode), event) - }); err != nil { - _ = consumer.Shutdown() - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - mqConsumers = append(mqConsumers, consumer) - } - if cfg.RedPacketBroadcastWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { - consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.RedPacketBroadcastConsumerGroup)) - if err != nil { - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - if err := consumer.Subscribe(redPacketWalletOutboxTopic(cfg.RocketMQ.WalletOutbox), walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { - event, ok, err := redPacketEventFromWalletMessage(message.Body) - if err != nil || !ok { - return err - } - return broadcastSvc.ConsumeRedPacketWalletEvent(appcode.WithContext(ctx, event.AppCode), event) - }); err != nil { - _ = consumer.Shutdown() - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() - return nil, err - } - mqConsumers = append(mqConsumers, consumer) - } - healthDependencies := []grpchealth.Dependency{{ - Name: "mysql", - Check: repository.Ping, - }} - health := grpchealth.NewServingChecker("activity-service", healthDependencies...) - healthgrpc.RegisterHealthServer(server, grpchealth.NewServer(health)) - healthHTTP, err := healthhttp.New(cfg.HealthHTTPAddr, cfg.NodeID, health) + services, err := buildServiceBundle(cfg, repository, clients) if err != nil { - shutdownConsumers(mqConsumers) - _ = walletConn.Close() - _ = userConn.Close() - _ = listener.Close() - _ = repository.Close() + cleanup() return nil, err } - workerCtx, workerStop := context.WithCancel(context.Background()) + registerGRPCServers(server, services) + mqConsumers, err = buildMQConsumers(cfg, services) + if err != nil { + cleanup() + return nil, err + } + health, healthHTTP, err := newHealthServers(cfg, server, repository) + if err != nil { + cleanup() + return nil, err + } + + workerCtx, workerStop := context.WithCancel(context.Background()) return &App{ server: server, listener: listener, health: health, healthHTTP: healthHTTP, mysqlRepo: repository, - broadcast: broadcastSvc, - luckyGift: luckyGiftSvc, - firstRechargeReward: firstRechargeRewardSvc, + broadcast: services.broadcast, + luckyGift: services.luckyGift, + firstRechargeReward: services.firstRechargeReward, + cumulativeRecharge: services.cumulativeRecharge, broadcastWorkerEnabled: cfg.Broadcast.Enabled, luckyGiftWorkerEnabled: cfg.LuckyGiftWorker.Enabled, workerNodeID: cfg.NodeID, luckyGiftWorkerOptions: luckyGiftWorkerOptions(cfg.NodeID, cfg.LuckyGiftWorker), mqConsumers: mqConsumers, - userConn: userConn, - walletConn: walletConn, + userConn: clients.userConn, + walletConn: clients.walletConn, + roomConn: clients.roomConn, workerCtx: workerCtx, workerStop: workerStop, }, nil @@ -372,6 +172,9 @@ func (a *App) Close() { if a.walletConn != nil { _ = a.walletConn.Close() } + if a.roomConn != nil { + _ = a.roomConn.Close() + } if a.mysqlRepo != nil { // MySQL 连接池最后关闭,保证 drain 中的查询或消费提交能完成。 _ = a.mysqlRepo.Close() @@ -416,247 +219,3 @@ func (a *App) shutdownMQ() { } } } - -func roomOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { - return rocketMQConsumerConfig(cfg, cfg.RoomOutbox.ConsumerGroup, cfg.RoomOutbox.ConsumerMaxReconsumeTimes) -} - -func userOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { - return rocketMQConsumerConfig(cfg, cfg.UserOutbox.ConsumerGroup, cfg.UserOutbox.ConsumerMaxReconsumeTimes) -} - -func walletOutboxConsumerConfig(cfg config.RocketMQConfig, group string) rocketmqx.ConsumerConfig { - return rocketMQConsumerConfig(cfg, group, cfg.WalletOutbox.ConsumerMaxReconsumeTimes) -} - -func redPacketWalletOutboxTopic(cfg config.WalletOutboxMQConfig) string { - // 钱包实时 topic 显式配置后,红包 worker 只消费实时通道,避免继续被普通账务 topic 的高频消息拖慢。 - if cfg.RealtimeTopic != "" { - return cfg.RealtimeTopic - } - return cfg.Topic -} - -func rocketMQConsumerConfig(cfg config.RocketMQConfig, group string, maxReconsume int32) rocketmqx.ConsumerConfig { - return rocketmqx.ConsumerConfig{ - EndpointConfig: rocketmqx.EndpointConfig{ - NameServers: cfg.NameServers, - NameServerDomain: cfg.NameServerDomain, - AccessKey: cfg.AccessKey, - SecretKey: cfg.SecretKey, - SecurityToken: cfg.SecurityToken, - Namespace: cfg.Namespace, - VIPChannel: cfg.VIPChannel, - }, - GroupName: group, - MaxReconsumeTimes: maxReconsume, - ConsumeRetryDelay: time.Second, - ConsumePullBatch: 32, - ConsumePullTimeout: 15 * time.Minute, - } -} - -func shutdownConsumers(consumers []*rocketmqx.Consumer) { - for _, consumer := range consumers { - _ = consumer.Shutdown() - } -} - -type userRegionChangedPayload struct { - UserID int64 `json:"user_id"` - OldRegionID int64 `json:"old_region_id"` - NewRegionID int64 `json:"new_region_id"` -} - -func consumeUserRegionChangedForBroadcast(ctx context.Context, service *broadcastservice.Service, message usermq.UserOutboxMessage) error { - if message.EventType != "UserRegionChanged" { - return nil - } - var payload userRegionChangedPayload - if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil { - return err - } - if payload.UserID <= 0 || payload.OldRegionID <= 0 || payload.OldRegionID == payload.NewRegionID { - return nil - } - // 区域广播群成员关系是当前读模型;用户切区后只移除旧群,下一次 UserSig 会按新 users.region_id 返回新群。 - _, _, err := service.RemoveRegionBroadcastMember(appcode.WithContext(ctx, message.AppCode), payload.UserID, payload.OldRegionID) - return err -} - -func firstRechargeEventFromWalletMessage(body []byte) (firstrechargedomain.RechargeEvent, bool, error) { - message, err := walletmq.DecodeWalletOutboxMessage(body) - if err != nil { - return firstrechargedomain.RechargeEvent{}, false, err - } - if message.EventType != firstrechargedomain.RechargeEventWalletRecorded { - return firstrechargedomain.RechargeEvent{}, false, nil - } - sequence, rechargeType := rechargeFactFromWalletPayload(message.PayloadJSON) - return firstrechargedomain.RechargeEvent{ - AppCode: appcode.Normalize(message.AppCode), - EventID: message.EventID, - EventType: message.EventType, - TransactionID: message.TransactionID, - CommandID: message.CommandID, - UserID: message.UserID, - RechargeCoinAmount: message.AvailableDelta, - RechargeSequence: sequence, - RechargeType: rechargeType, - PayloadJSON: message.PayloadJSON, - OccurredAtMS: message.OccurredAtMS, - }, true, nil -} - -func redPacketEventFromWalletMessage(body []byte) (broadcastdomain.RedPacketWalletEvent, bool, error) { - message, err := walletmq.DecodeWalletOutboxMessage(body) - if err != nil { - return broadcastdomain.RedPacketWalletEvent{}, false, err - } - if message.EventType != "WalletRedPacketCreated" && message.EventType != "WalletRedPacketClaimed" && message.EventType != "WalletRedPacketRefunded" { - return broadcastdomain.RedPacketWalletEvent{}, false, nil - } - fields := redPacketFieldsFromWalletPayload(message.PayloadJSON, message.EventType) - if fields.PacketID == "" { - return broadcastdomain.RedPacketWalletEvent{}, false, nil - } - return broadcastdomain.RedPacketWalletEvent{ - AppCode: appcode.Normalize(message.AppCode), - EventID: message.EventID, - EventType: message.EventType, - TransactionID: message.TransactionID, - CommandID: message.CommandID, - PayloadJSON: message.PayloadJSON, - PacketID: fields.PacketID, - PacketType: fields.PacketType, - RoomID: fields.RoomID, - RegionID: fields.RegionID, - RegionCode: fields.RegionCode, - SenderUserID: fields.SenderUserID, - TotalAmount: fields.TotalAmount, - TotalCount: fields.TotalCount, - RemainingAmount: fields.RemainingAmount, - RemainingCount: fields.RemainingCount, - RefundedAmount: fields.RefundedAmount, - Status: fields.Status, - OpenAtMS: fields.OpenAtMS, - ExpiresAtMS: fields.ExpiresAtMS, - CreatedAtMS: message.OccurredAtMS, - }, true, nil -} - -func rechargeFactFromWalletPayload(payload string) (int64, string) { - var decoded map[string]any - if err := json.Unmarshal([]byte(payload), &decoded); err != nil { - return 0, firstrechargedomain.RechargeTypeCoinSeller - } - var sequence int64 - switch value := decoded["recharge_sequence"].(type) { - case float64: - sequence = int64(value) - case int64: - sequence = value - case json.Number: - sequence, _ = value.Int64() - } - rechargeType := firstrechargedomain.RechargeTypeCoinSeller - if value, ok := decoded["recharge_type"].(string); ok && value != "" { - rechargeType = value - } - return sequence, rechargeType -} - -type redPacketPayloadFields struct { - PacketID string - PacketType string - RoomID string - RegionID int64 - RegionCode string - SenderUserID int64 - TotalAmount int64 - TotalCount int32 - RemainingAmount int64 - RemainingCount int32 - RefundedAmount int64 - Status string - OpenAtMS int64 - ExpiresAtMS int64 -} - -func redPacketFieldsFromWalletPayload(payload string, eventType string) redPacketPayloadFields { - var decoded map[string]any - if err := json.Unmarshal([]byte(payload), &decoded); err != nil { - return redPacketPayloadFields{} - } - packetID := stringFromDecoded(decoded, "packet_id") - if packetID == "" { - packetID = stringFromDecoded(decoded, "packetId") - } - packetType := stringFromDecoded(decoded, "packet_type") - roomID := stringFromDecoded(decoded, "room_id") - regionID := int64FromDecoded(decoded, "region_id") - status := stringFromDecoded(decoded, "status") - openAtMS := int64FromDecoded(decoded, "open_at_ms") - expiresAtMS := int64FromDecoded(decoded, "expires_at_ms") - if eventType == "WalletRedPacketClaimed" || eventType == "WalletRedPacketRefunded" { - status = stringFromDecoded(decoded, "packet_status") - } - totalCount := int32FromDecoded(decoded, "packet_count") - remainingCount := int32FromDecoded(decoded, "remaining_count") - if remainingCount == 0 && eventType == "WalletRedPacketCreated" { - remainingCount = totalCount - } - return redPacketPayloadFields{ - PacketID: packetID, - PacketType: packetType, - RoomID: roomID, - RegionID: regionID, - RegionCode: stringFromDecoded(decoded, "region_code"), - SenderUserID: int64FromDecoded(decoded, "sender_user_id"), - TotalAmount: int64FromDecoded(decoded, "total_amount"), - TotalCount: totalCount, - RemainingAmount: int64FromDecoded(decoded, "remaining_amount"), - RemainingCount: remainingCount, - RefundedAmount: int64FromDecoded(decoded, "refund_amount"), - Status: status, - OpenAtMS: openAtMS, - ExpiresAtMS: expiresAtMS, - } -} - -func stringFromDecoded(decoded map[string]any, key string) string { - value, _ := decoded[key].(string) - return value -} - -func int64FromDecoded(decoded map[string]any, key string) int64 { - switch value := decoded[key].(type) { - case float64: - return int64(value) - case int64: - return value - case json.Number: - parsed, _ := value.Int64() - return parsed - default: - return 0 - } -} - -func int32FromDecoded(decoded map[string]any, key string) int32 { - return int32(int64FromDecoded(decoded, key)) -} - -func luckyGiftWorkerOptions(nodeID string, cfg config.LuckyGiftWorkerConfig) luckygiftservice.WorkerOptions { - return luckygiftservice.WorkerOptions{ - WorkerID: nodeID + "-lucky-gift", - PollInterval: cfg.WorkerPollInterval, - BatchSize: cfg.WorkerBatchSize, - Concurrency: cfg.WorkerConcurrency, - LockTTL: cfg.WorkerLockTTL, - MaxRetry: cfg.WorkerMaxRetry, - PublishTimeout: cfg.PublishTimeout, - StatsInterval: cfg.StatsRefreshInterval, - StatsBatchSize: cfg.StatsBatchSize, - } -} diff --git a/services/activity-service/internal/app/dependencies.go b/services/activity-service/internal/app/dependencies.go new file mode 100644 index 00000000..0cbbec50 --- /dev/null +++ b/services/activity-service/internal/app/dependencies.go @@ -0,0 +1,71 @@ +package app + +import ( + "context" + "net" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "hyapp/services/activity-service/internal/config" + mysqlstorage "hyapp/services/activity-service/internal/storage/mysql" +) + +type externalClients struct { + userConn *grpc.ClientConn + walletConn *grpc.ClientConn + roomConn *grpc.ClientConn +} + +func openRepository(ctx context.Context, cfg config.Config) (*mysqlstorage.Repository, error) { + // activity-service 的活动配置、消费幂等、排行榜和 outbox 都落在 MySQL。 + // migrate 放在启动阶段执行,保证本地新增活动模块时不需要手工补表后才能启动。 + repository, err := mysqlstorage.Open(ctx, cfg.MySQLDSN) + if err != nil { + return nil, err + } + if cfg.MySQLAutoMigrate { + if err := repository.Migrate(ctx); err != nil { + _ = repository.Close() + return nil, err + } + } + return repository, nil +} + +func listenGRPC(addr string) (net.Listener, error) { + return net.Listen("tcp", addr) +} + +func dialExternalClients(cfg config.Config) (externalClients, error) { + // 三个下游连接在 App 级别统一持有;各业务 service 只拿生成后的 typed client。 + // 这样 Close 时可以按连接维度回收资源,新增模块也不会重复创建 gRPC 连接池。 + var clients externalClients + var err error + clients.userConn, err = grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return externalClients{}, err + } + clients.walletConn, err = grpc.Dial(cfg.WalletServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + clients.Close() + return externalClients{}, err + } + clients.roomConn, err = grpc.Dial(cfg.RoomServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + clients.Close() + return externalClients{}, err + } + return clients, nil +} + +func (c externalClients) Close() { + if c.roomConn != nil { + _ = c.roomConn.Close() + } + if c.walletConn != nil { + _ = c.walletConn.Close() + } + if c.userConn != nil { + _ = c.userConn.Close() + } +} diff --git a/services/activity-service/internal/app/grpc_registration.go b/services/activity-service/internal/app/grpc_registration.go new file mode 100644 index 00000000..7a19c7b3 --- /dev/null +++ b/services/activity-service/internal/app/grpc_registration.go @@ -0,0 +1,40 @@ +package app + +import ( + "google.golang.org/grpc" + activityv1 "hyapp.local/api/proto/activity/v1" + grpcserver "hyapp/services/activity-service/internal/transport/grpc" +) + +func registerGRPCServers(server *grpc.Server, services *serviceBundle) { + activityv1.RegisterActivityServiceServer(server, grpcserver.NewServer(services.activity)) + activityv1.RegisterMessageInboxServiceServer(server, grpcserver.NewMessageServer(services.message)) + // cron 入口只做调度适配;具体状态机仍在各 activity service 内部。 + // weekly-star 和 room-turnover 都依赖 wallet 发奖,所以这里必须把同一批已装配的 service 注入 cron server。 + activityv1.RegisterActivityCronServiceServer(server, grpcserver.NewCronServer(services.message, services.growth, services.achievement, services.weeklyStar, services.roomTurnoverReward)) + activityv1.RegisterTaskServiceServer(server, grpcserver.NewTaskServer(services.task)) + activityv1.RegisterAdminTaskServiceServer(server, grpcserver.NewAdminTaskServer(services.task)) + activityv1.RegisterGrowthLevelServiceServer(server, grpcserver.NewGrowthLevelServer(services.growth)) + activityv1.RegisterAdminGrowthLevelServiceServer(server, grpcserver.NewAdminGrowthLevelServer(services.growth)) + activityv1.RegisterAchievementServiceServer(server, grpcserver.NewAchievementServer(services.achievement)) + activityv1.RegisterAdminAchievementServiceServer(server, grpcserver.NewAdminAchievementServer(services.achievement)) + activityv1.RegisterLuckyGiftServiceServer(server, grpcserver.NewLuckyGiftServer(services.luckyGift)) + activityv1.RegisterAdminLuckyGiftServiceServer(server, grpcserver.NewAdminLuckyGiftServer(services.luckyGift)) + activityv1.RegisterRegistrationRewardServiceServer(server, grpcserver.NewRegistrationRewardServer(services.registrationReward)) + activityv1.RegisterAdminRegistrationRewardServiceServer(server, grpcserver.NewAdminRegistrationRewardServer(services.registrationReward)) + activityv1.RegisterSevenDayCheckInServiceServer(server, grpcserver.NewSevenDayCheckInServer(services.sevenDayCheckIn)) + activityv1.RegisterAdminSevenDayCheckInServiceServer(server, grpcserver.NewAdminSevenDayCheckInServer(services.sevenDayCheckIn)) + activityv1.RegisterWeeklyStarServiceServer(server, grpcserver.NewWeeklyStarServer(services.weeklyStar)) + activityv1.RegisterAdminWeeklyStarServiceServer(server, grpcserver.NewAdminWeeklyStarServer(services.weeklyStar)) + activityv1.RegisterRoomTurnoverRewardServiceServer(server, grpcserver.NewRoomTurnoverRewardServer(services.roomTurnoverReward)) + activityv1.RegisterAdminRoomTurnoverRewardServiceServer(server, grpcserver.NewAdminRoomTurnoverRewardServer(services.roomTurnoverReward)) + // BroadcastServer 同时承载 BroadcastService 和 RoomEventConsumerService。 + // gRPC 直连投递和 MQ 消费都必须经过相同的 room event fanout 顺序,否则本地验证会通过但线上 MQ 路径漏积分。 + broadcastServer := grpcserver.NewBroadcastServer(services.broadcast, services.growth, services.weeklyStar, services.roomTurnoverReward) + activityv1.RegisterBroadcastServiceServer(server, broadcastServer) + activityv1.RegisterRoomEventConsumerServiceServer(server, broadcastServer) + activityv1.RegisterFirstRechargeRewardServiceServer(server, grpcserver.NewFirstRechargeRewardServer(services.firstRechargeReward)) + activityv1.RegisterAdminFirstRechargeRewardServiceServer(server, grpcserver.NewAdminFirstRechargeRewardServer(services.firstRechargeReward)) + activityv1.RegisterCumulativeRechargeRewardServiceServer(server, grpcserver.NewCumulativeRechargeRewardServer(services.cumulativeRecharge)) + activityv1.RegisterAdminCumulativeRechargeRewardServiceServer(server, grpcserver.NewAdminCumulativeRechargeRewardServer(services.cumulativeRecharge)) +} diff --git a/services/activity-service/internal/app/health.go b/services/activity-service/internal/app/health.go new file mode 100644 index 00000000..faa88951 --- /dev/null +++ b/services/activity-service/internal/app/health.go @@ -0,0 +1,24 @@ +package app + +import ( + "google.golang.org/grpc" + healthgrpc "google.golang.org/grpc/health/grpc_health_v1" + "hyapp/pkg/grpchealth" + "hyapp/pkg/healthhttp" + "hyapp/services/activity-service/internal/config" + mysqlstorage "hyapp/services/activity-service/internal/storage/mysql" +) + +func newHealthServers(cfg config.Config, server *grpc.Server, repository *mysqlstorage.Repository) (*grpchealth.ServingChecker, *healthhttp.Server, error) { + // gRPC health 和 HTTP ready 共用同一个 checker,避免一个入口显示 ready、另一个入口还在 draining。 + health := grpchealth.NewServingChecker("activity-service", grpchealth.Dependency{ + Name: "mysql", + Check: repository.Ping, + }) + healthgrpc.RegisterHealthServer(server, grpchealth.NewServer(health)) + healthHTTP, err := healthhttp.New(cfg.HealthHTTPAddr, cfg.NodeID, health) + if err != nil { + return nil, nil, err + } + return health, healthHTTP, nil +} diff --git a/services/activity-service/internal/app/mq.go b/services/activity-service/internal/app/mq.go new file mode 100644 index 00000000..9db165cf --- /dev/null +++ b/services/activity-service/internal/app/mq.go @@ -0,0 +1,236 @@ +package app + +import ( + "context" + "encoding/json" + "errors" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/rocketmqx" + "hyapp/pkg/roommq" + "hyapp/pkg/usermq" + "hyapp/pkg/walletmq" + "hyapp/services/activity-service/internal/config" + broadcastservice "hyapp/services/activity-service/internal/service/broadcast" +) + +func buildMQConsumers(cfg config.Config, services *serviceBundle) ([]*rocketmqx.Consumer, error) { + mqConsumers := make([]*rocketmqx.Consumer, 0, 4) + if cfg.RocketMQ.RoomOutbox.Enabled { + consumer, err := newRoomOutboxConsumer(cfg, services) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } + if cfg.RocketMQ.UserOutbox.Enabled && !services.broadcastPublisherAvailable { + shutdownConsumers(mqConsumers) + return nil, errors.New("rocketmq user_outbox consumer requires tencent_im.enabled") + } + if cfg.RocketMQ.UserOutbox.Enabled { + consumer, err := newUserOutboxConsumer(cfg, services.broadcast) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } + if cfg.FirstRechargeRewardWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { + consumer, err := newFirstRechargeWalletConsumer(cfg, services) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } + if cfg.CumulativeRechargeRewardWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { + consumer, err := newCumulativeRechargeWalletConsumer(cfg, services) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } + if cfg.RedPacketBroadcastWorker.Enabled && cfg.RocketMQ.WalletOutbox.Enabled { + consumer, err := newRedPacketWalletConsumer(cfg, services) + if err != nil { + shutdownConsumers(mqConsumers) + return nil, err + } + mqConsumers = append(mqConsumers, consumer) + } + return mqConsumers, nil +} + +func newRoomOutboxConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { + consumer, err := rocketmqx.NewConsumer(roomOutboxConsumerConfig(cfg.RocketMQ)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.RoomOutbox.Topic, roommq.TagRoomOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + envelope, _, err := roommq.DecodeRoomOutboxMessage(message.Body) + if err != nil { + return err + } + // 一个 room outbox envelope 代表房间状态已经提交;下游模块各自写幂等消费表。 + // 任何模块失败都返回错误给 MQ,让同一个 envelope 重试,避免“播报成功但活动漏计分”的半完成状态。 + eventCtx := appcode.WithContext(ctx, envelope.GetAppCode()) + if _, err := services.broadcast.HandleRoomEvent(eventCtx, envelope); err != nil { + return err + } + if _, err := services.growth.HandleRoomEvent(eventCtx, envelope); err != nil { + return err + } + if _, err := services.weeklyStar.HandleRoomEvent(eventCtx, envelope); err != nil { + return err + } + _, err = services.roomTurnoverReward.HandleRoomEvent(eventCtx, envelope) + return err + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + +func newUserOutboxConsumer(cfg config.Config, broadcastSvc *broadcastservice.Service) (*rocketmqx.Consumer, error) { + consumer, err := rocketmqx.NewConsumer(userOutboxConsumerConfig(cfg.RocketMQ)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.UserOutbox.Topic, usermq.TagUserOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + outboxMessage, err := usermq.DecodeUserOutboxMessage(message.Body) + if err != nil { + return err + } + return consumeUserRegionChangedForBroadcast(ctx, broadcastSvc, outboxMessage) + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + +func newFirstRechargeWalletConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { + consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.FirstRechargeConsumerGroup)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.WalletOutbox.Topic, walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + event, ok, err := firstRechargeEventFromWalletMessage(message.Body) + if err != nil || !ok { + return err + } + return services.firstRechargeReward.ConsumeWalletRechargeEvent(appcode.WithContext(ctx, event.AppCode), event) + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + +func newCumulativeRechargeWalletConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { + // 累充奖励使用独立 consumer group,避免和首充奖励共享消费位点后互相影响重放和排查。 + consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.CumulativeRechargeConsumerGroup)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(cfg.RocketMQ.WalletOutbox.Topic, walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + event, ok, err := cumulativeRechargeEventFromWalletMessage(message.Body) + if err != nil || !ok { + return err + } + return services.cumulativeRecharge.ConsumeWalletRechargeEvent(appcode.WithContext(ctx, event.AppCode), event) + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + +func newRedPacketWalletConsumer(cfg config.Config, services *serviceBundle) (*rocketmqx.Consumer, error) { + consumer, err := rocketmqx.NewConsumer(walletOutboxConsumerConfig(cfg.RocketMQ, cfg.RocketMQ.WalletOutbox.RedPacketBroadcastConsumerGroup)) + if err != nil { + return nil, err + } + if err := consumer.Subscribe(redPacketWalletOutboxTopic(cfg.RocketMQ.WalletOutbox), walletmq.TagWalletOutboxEvent, func(ctx context.Context, message rocketmqx.ConsumedMessage) error { + event, ok, err := redPacketEventFromWalletMessage(message.Body) + if err != nil || !ok { + return err + } + return services.broadcast.ConsumeRedPacketWalletEvent(appcode.WithContext(ctx, event.AppCode), event) + }); err != nil { + _ = consumer.Shutdown() + return nil, err + } + return consumer, nil +} + +func roomOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { + return rocketMQConsumerConfig(cfg, cfg.RoomOutbox.ConsumerGroup, cfg.RoomOutbox.ConsumerMaxReconsumeTimes) +} + +func userOutboxConsumerConfig(cfg config.RocketMQConfig) rocketmqx.ConsumerConfig { + return rocketMQConsumerConfig(cfg, cfg.UserOutbox.ConsumerGroup, cfg.UserOutbox.ConsumerMaxReconsumeTimes) +} + +func walletOutboxConsumerConfig(cfg config.RocketMQConfig, group string) rocketmqx.ConsumerConfig { + return rocketMQConsumerConfig(cfg, group, cfg.WalletOutbox.ConsumerMaxReconsumeTimes) +} + +func redPacketWalletOutboxTopic(cfg config.WalletOutboxMQConfig) string { + // 钱包实时 topic 显式配置后,红包 worker 只消费实时通道,避免继续被普通账务 topic 的高频消息拖慢。 + if cfg.RealtimeTopic != "" { + return cfg.RealtimeTopic + } + return cfg.Topic +} + +func rocketMQConsumerConfig(cfg config.RocketMQConfig, group string, maxReconsume int32) rocketmqx.ConsumerConfig { + return rocketmqx.ConsumerConfig{ + EndpointConfig: rocketmqx.EndpointConfig{ + NameServers: cfg.NameServers, + NameServerDomain: cfg.NameServerDomain, + AccessKey: cfg.AccessKey, + SecretKey: cfg.SecretKey, + SecurityToken: cfg.SecurityToken, + Namespace: cfg.Namespace, + VIPChannel: cfg.VIPChannel, + }, + GroupName: group, + MaxReconsumeTimes: maxReconsume, + ConsumeRetryDelay: time.Second, + ConsumePullBatch: 32, + ConsumePullTimeout: 15 * time.Minute, + } +} + +func shutdownConsumers(consumers []*rocketmqx.Consumer) { + for _, consumer := range consumers { + _ = consumer.Shutdown() + } +} + +type userRegionChangedPayload struct { + UserID int64 `json:"user_id"` + OldRegionID int64 `json:"old_region_id"` + NewRegionID int64 `json:"new_region_id"` +} + +func consumeUserRegionChangedForBroadcast(ctx context.Context, service *broadcastservice.Service, message usermq.UserOutboxMessage) error { + if message.EventType != "UserRegionChanged" { + return nil + } + var payload userRegionChangedPayload + if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil { + return err + } + if payload.UserID <= 0 || payload.OldRegionID <= 0 || payload.OldRegionID == payload.NewRegionID { + return nil + } + // 区域广播群成员关系是当前读模型;用户切区后只移除旧群,下一次 UserSig 会按新 users.region_id 返回新群。 + _, _, err := service.RemoveRegionBroadcastMember(appcode.WithContext(ctx, message.AppCode), payload.UserID, payload.OldRegionID) + return err +} diff --git a/services/activity-service/internal/app/services.go b/services/activity-service/internal/app/services.go new file mode 100644 index 00000000..01ce1302 --- /dev/null +++ b/services/activity-service/internal/app/services.go @@ -0,0 +1,110 @@ +package app + +import ( + "errors" + + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/tencentim" + activityclient "hyapp/services/activity-service/internal/client" + "hyapp/services/activity-service/internal/config" + achievementservice "hyapp/services/activity-service/internal/service/achievement" + activityservice "hyapp/services/activity-service/internal/service/activity" + broadcastservice "hyapp/services/activity-service/internal/service/broadcast" + cumulativerechargeservice "hyapp/services/activity-service/internal/service/cumulativerecharge" + 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" + registrationrewardservice "hyapp/services/activity-service/internal/service/registrationreward" + roomturnoverrewardservice "hyapp/services/activity-service/internal/service/roomturnoverreward" + sevendaycheckinservice "hyapp/services/activity-service/internal/service/sevendaycheckin" + taskservice "hyapp/services/activity-service/internal/service/task" + weeklystarservice "hyapp/services/activity-service/internal/service/weeklystar" + mysqlstorage "hyapp/services/activity-service/internal/storage/mysql" +) + +type serviceBundle struct { + activity *activityservice.Service + message *messageservice.Service + task *taskservice.Service + registrationReward *registrationrewardservice.Service + sevenDayCheckIn *sevendaycheckinservice.Service + growth *growthservice.Service + achievement *achievementservice.Service + weeklyStar *weeklystarservice.Service + roomTurnoverReward *roomturnoverrewardservice.Service + broadcast *broadcastservice.Service + luckyGift *luckygiftservice.Service + firstRechargeReward *firstrechargeservice.Service + cumulativeRecharge *cumulativerechargeservice.Service + broadcastPublisherAvailable bool +} + +func buildServiceBundle(cfg config.Config, repository *mysqlstorage.Repository, clients externalClients) (*serviceBundle, error) { + walletClient := walletv1.NewWalletServiceClient(clients.walletConn) + roomClient := roomv1.NewRoomQueryServiceClient(clients.roomConn) + + activitySvc := activityservice.New(activityservice.Config{NodeID: cfg.NodeID}, repository) + messageSvc := messageservice.New(messageservice.Config{NodeID: cfg.NodeID}, repository, messageservice.WithTargetSource(activityclient.NewGRPCUserTargetSource(clients.userConn))) + taskSvc := taskservice.New(repository, walletClient) + registrationRewardSvc := registrationrewardservice.New(repository, walletClient) + sevenDayCheckInSvc := sevendaycheckinservice.New(repository, walletClient) + growthSvc := growthservice.New(repository, walletClient) + achievementSvc := achievementservice.New(repository, walletClient) + weeklyStarSvc := weeklystarservice.New(repository, walletClient) + roomTurnoverRewardSvc := roomturnoverrewardservice.New(repository, walletClient, roomClient) + + // Tencent IM 是区域广播、房间礼物播报和红包播报的外部发布器。 + // 如果配置要求启动广播 worker,就必须先确认 publisher 可用,避免 worker 启动后只写 outbox 不发消息。 + var tencentClient *tencentim.RESTClient + var broadcastPublisher broadcastservice.Publisher + if cfg.TencentIM.Enabled { + client, err := tencentim.NewRESTClient(cfg.TencentIM.RESTConfig()) + if err != nil { + return nil, err + } + tencentClient = client + broadcastPublisher = client + } + if cfg.Broadcast.Enabled && broadcastPublisher == nil { + return nil, errors.New("broadcast worker requires tencent_im.enabled") + } + + broadcastSvc := broadcastservice.New(broadcastservice.Config{ + NodeID: cfg.NodeID, + SuperGiftMinValue: cfg.Broadcast.SuperGiftMinValue, + WorkerBatchSize: cfg.Broadcast.WorkerBatchSize, + WorkerLockTTL: cfg.Broadcast.WorkerLockTTL, + WorkerMaxRetry: cfg.Broadcast.WorkerMaxRetry, + WorkerPollInterval: cfg.Broadcast.WorkerPollInterval, + EnsureGroupsOnStartup: cfg.Broadcast.EnsureGroupsOnStartup, + GroupIDPrefix: cfg.TencentIM.GroupIDPrefix, + }, repository, broadcastPublisher, activityclient.NewGRPCRegionSource(clients.userConn)) + broadcastSvc.SetSenderProfileSource(activityclient.NewGRPCUserProfileSource(clients.userConn)) + + luckyGiftSvc := luckygiftservice.New(repository, + luckygiftservice.WithWallet(walletClient), + luckygiftservice.WithRoomPublisher(tencentClient), + luckygiftservice.WithRegionBroadcaster(broadcastSvc), + ) + firstRechargeRewardSvc := firstrechargeservice.New(repository, walletClient) + cumulativeRechargeSvc := cumulativerechargeservice.New(repository, walletClient) + + return &serviceBundle{ + activity: activitySvc, + message: messageSvc, + task: taskSvc, + registrationReward: registrationRewardSvc, + sevenDayCheckIn: sevenDayCheckInSvc, + growth: growthSvc, + achievement: achievementSvc, + weeklyStar: weeklyStarSvc, + roomTurnoverReward: roomTurnoverRewardSvc, + broadcast: broadcastSvc, + luckyGift: luckyGiftSvc, + firstRechargeReward: firstRechargeRewardSvc, + cumulativeRecharge: cumulativeRechargeSvc, + broadcastPublisherAvailable: broadcastPublisher != nil, + }, nil +} diff --git a/services/activity-service/internal/app/wallet_events.go b/services/activity-service/internal/app/wallet_events.go new file mode 100644 index 00000000..08f337c3 --- /dev/null +++ b/services/activity-service/internal/app/wallet_events.go @@ -0,0 +1,296 @@ +package app + +import ( + "encoding/json" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/walletmq" + broadcastdomain "hyapp/services/activity-service/internal/domain/broadcast" + cumulativerechargedomain "hyapp/services/activity-service/internal/domain/cumulativerecharge" + firstrechargedomain "hyapp/services/activity-service/internal/domain/firstrecharge" +) + +func firstRechargeEventFromWalletMessage(body []byte) (firstrechargedomain.RechargeEvent, bool, error) { + message, err := walletmq.DecodeWalletOutboxMessage(body) + if err != nil { + return firstrechargedomain.RechargeEvent{}, false, err + } + if message.EventType != firstrechargedomain.RechargeEventWalletRecorded { + return firstrechargedomain.RechargeEvent{}, false, nil + } + sequence, rechargeType := rechargeFactFromWalletPayload(message.PayloadJSON) + return firstrechargedomain.RechargeEvent{ + AppCode: appcode.Normalize(message.AppCode), + EventID: message.EventID, + EventType: message.EventType, + TransactionID: message.TransactionID, + CommandID: message.CommandID, + UserID: message.UserID, + RechargeCoinAmount: message.AvailableDelta, + RechargeSequence: sequence, + RechargeType: rechargeType, + PayloadJSON: message.PayloadJSON, + OccurredAtMS: message.OccurredAtMS, + }, true, nil +} + +func cumulativeRechargeEventFromWalletMessage(body []byte) (cumulativerechargedomain.RechargeEvent, bool, error) { + message, err := walletmq.DecodeWalletOutboxMessage(body) + if err != nil { + return cumulativerechargedomain.RechargeEvent{}, false, err + } + if message.EventType != cumulativerechargedomain.RechargeEventWalletRecorded { + return cumulativerechargedomain.RechargeEvent{}, false, nil + } + // WalletRechargeRecorded 是累充唯一事实源;payload 里没有可折算 USD 金额时直接跳过,避免把普通钱包流水计入活动。 + fields := cumulativeRechargeFactFromWalletPayload(message.PayloadJSON, message.AvailableDelta) + if fields.qualifyingUSDMinor <= 0 { + return cumulativerechargedomain.RechargeEvent{}, false, nil + } + return cumulativerechargedomain.RechargeEvent{ + AppCode: appcode.Normalize(message.AppCode), + EventID: message.EventID, + EventType: message.EventType, + TransactionID: message.TransactionID, + CommandID: message.CommandID, + UserID: message.UserID, + RechargeCoinAmount: fields.coinAmount, + RechargeSequence: fields.sequence, + RechargeType: fields.rechargeType, + QualifyingUSDMinor: fields.qualifyingUSDMinor, + PayloadJSON: message.PayloadJSON, + OccurredAtMS: message.OccurredAtMS, + }, true, nil +} + +func redPacketEventFromWalletMessage(body []byte) (broadcastdomain.RedPacketWalletEvent, bool, error) { + message, err := walletmq.DecodeWalletOutboxMessage(body) + if err != nil { + return broadcastdomain.RedPacketWalletEvent{}, false, err + } + if message.EventType != "WalletRedPacketCreated" && message.EventType != "WalletRedPacketClaimed" && message.EventType != "WalletRedPacketRefunded" { + return broadcastdomain.RedPacketWalletEvent{}, false, nil + } + fields := redPacketFieldsFromWalletPayload(message.PayloadJSON, message.EventType) + if fields.PacketID == "" { + return broadcastdomain.RedPacketWalletEvent{}, false, nil + } + return broadcastdomain.RedPacketWalletEvent{ + AppCode: appcode.Normalize(message.AppCode), + EventID: message.EventID, + EventType: message.EventType, + TransactionID: message.TransactionID, + CommandID: message.CommandID, + PayloadJSON: message.PayloadJSON, + PacketID: fields.PacketID, + PacketType: fields.PacketType, + RoomID: fields.RoomID, + RegionID: fields.RegionID, + RegionCode: fields.RegionCode, + SenderUserID: fields.SenderUserID, + TotalAmount: fields.TotalAmount, + TotalCount: fields.TotalCount, + RemainingAmount: fields.RemainingAmount, + RemainingCount: fields.RemainingCount, + RefundedAmount: fields.RefundedAmount, + Status: fields.Status, + OpenAtMS: fields.OpenAtMS, + ExpiresAtMS: fields.ExpiresAtMS, + CreatedAtMS: message.OccurredAtMS, + }, true, nil +} + +func rechargeFactFromWalletPayload(payload string) (int64, string) { + var decoded map[string]any + if err := json.Unmarshal([]byte(payload), &decoded); err != nil { + return 0, firstrechargedomain.RechargeTypeCoinSeller + } + var sequence int64 + switch value := decoded["recharge_sequence"].(type) { + case float64: + sequence = int64(value) + case int64: + sequence = value + case json.Number: + sequence, _ = value.Int64() + } + rechargeType := firstrechargedomain.RechargeTypeCoinSeller + if value, ok := decoded["recharge_type"].(string); ok && value != "" { + rechargeType = value + } + return sequence, rechargeType +} + +type cumulativeRechargePayloadFields struct { + sequence int64 + rechargeType string + coinAmount int64 + qualifyingUSDMinor int64 +} + +func cumulativeRechargeFactFromWalletPayload(payload string, availableDelta int64) cumulativeRechargePayloadFields { + var decoded map[string]any + if err := json.Unmarshal([]byte(payload), &decoded); err != nil { + decoded = map[string]any{} + } + // 来源字段兼容 wallet 历史 payload;没有明确来源时按币商转账处理,因为币商链路通常只带金币增量。 + rechargeType := firstNonEmptyString( + stringFromDecoded(decoded, "recharge_type"), + stringFromDecoded(decoded, "channel"), + stringFromDecoded(decoded, "provider"), + cumulativerechargedomain.RechargeTypeCoinSeller, + ) + // coinAmount 用于审计和币商折算,优先使用 payload 明细,最后回退 wallet outbox 的 available_delta。 + coinAmount := firstNonZeroInt64( + int64FromDecoded(decoded, "coin_amount"), + int64FromDecoded(decoded, "amount"), + int64FromDecoded(decoded, "available_delta"), + availableDelta, + ) + qualifyingUSDMinor := cumulativeRechargeUSDMinorFromPayload(decoded, rechargeType, coinAmount) + return cumulativeRechargePayloadFields{ + sequence: int64FromDecoded(decoded, "recharge_sequence"), + rechargeType: rechargeType, + coinAmount: coinAmount, + qualifyingUSDMinor: qualifyingUSDMinor, + } +} + +func cumulativeRechargeUSDMinorFromPayload(decoded map[string]any, rechargeType string, coinAmount int64) int64 { + if isCumulativeCoinSellerRecharge(rechargeType) { + // 币商给用户转账按 90000 coins = 1 USD 折算;这里返回美分并向下取整,尾差只留在原始金币字段审计。 + return coinAmount * 100 / 90000 + } + // Google/Mifapay 充值优先使用支付侧传入的美元美分,避免用金币包配置反推造成汇率误差。 + if value := firstNonZeroInt64( + int64FromDecoded(decoded, "recharge_usd_minor"), + int64FromDecoded(decoded, "usd_minor_amount"), + int64FromDecoded(decoded, "exchange_usd_minor_amount"), + int64FromDecoded(decoded, "amount_usd_minor"), + ); value > 0 { + return value + } + if isCumulativeGoogleRecharge(rechargeType) { + // Google Billing 常见 amount_micro 是 USD 微单位,除以 10000 后得到美分。 + return int64FromDecoded(decoded, "amount_micro") / 10000 + } + return 0 +} + +func isCumulativeCoinSellerRecharge(value string) bool { + switch strings.ToLower(strings.TrimSpace(value)) { + case "coin_seller_transfer", "coin_seller": + return true + default: + return false + } +} + +func isCumulativeGoogleRecharge(value string) bool { + switch strings.ToLower(strings.TrimSpace(value)) { + case "google", "google_play": + return true + default: + return false + } +} + +type redPacketPayloadFields struct { + PacketID string + PacketType string + RoomID string + RegionID int64 + RegionCode string + SenderUserID int64 + TotalAmount int64 + TotalCount int32 + RemainingAmount int64 + RemainingCount int32 + RefundedAmount int64 + Status string + OpenAtMS int64 + ExpiresAtMS int64 +} + +func redPacketFieldsFromWalletPayload(payload string, eventType string) redPacketPayloadFields { + var decoded map[string]any + if err := json.Unmarshal([]byte(payload), &decoded); err != nil { + return redPacketPayloadFields{} + } + packetID := stringFromDecoded(decoded, "packet_id") + if packetID == "" { + packetID = stringFromDecoded(decoded, "packetId") + } + packetType := stringFromDecoded(decoded, "packet_type") + roomID := stringFromDecoded(decoded, "room_id") + regionID := int64FromDecoded(decoded, "region_id") + status := stringFromDecoded(decoded, "status") + openAtMS := int64FromDecoded(decoded, "open_at_ms") + expiresAtMS := int64FromDecoded(decoded, "expires_at_ms") + if eventType == "WalletRedPacketClaimed" || eventType == "WalletRedPacketRefunded" { + status = stringFromDecoded(decoded, "packet_status") + } + totalCount := int32FromDecoded(decoded, "packet_count") + remainingCount := int32FromDecoded(decoded, "remaining_count") + if remainingCount == 0 && eventType == "WalletRedPacketCreated" { + remainingCount = totalCount + } + return redPacketPayloadFields{ + PacketID: packetID, + PacketType: packetType, + RoomID: roomID, + RegionID: regionID, + RegionCode: stringFromDecoded(decoded, "region_code"), + SenderUserID: int64FromDecoded(decoded, "sender_user_id"), + TotalAmount: int64FromDecoded(decoded, "total_amount"), + TotalCount: totalCount, + RemainingAmount: int64FromDecoded(decoded, "remaining_amount"), + RemainingCount: remainingCount, + RefundedAmount: int64FromDecoded(decoded, "refund_amount"), + Status: status, + OpenAtMS: openAtMS, + ExpiresAtMS: expiresAtMS, + } +} + +func stringFromDecoded(decoded map[string]any, key string) string { + value, _ := decoded[key].(string) + return value +} + +func firstNonEmptyString(values ...string) string { + for _, value := range values { + if value = strings.TrimSpace(value); value != "" { + return value + } + } + return "" +} + +func firstNonZeroInt64(values ...int64) int64 { + for _, value := range values { + if value != 0 { + return value + } + } + return 0 +} + +func int64FromDecoded(decoded map[string]any, key string) int64 { + switch value := decoded[key].(type) { + case float64: + return int64(value) + case int64: + return value + case json.Number: + parsed, _ := value.Int64() + return parsed + default: + return 0 + } +} + +func int32FromDecoded(decoded map[string]any, key string) int32 { + return int32(int64FromDecoded(decoded, key)) +} diff --git a/services/activity-service/internal/app/workers.go b/services/activity-service/internal/app/workers.go new file mode 100644 index 00000000..29e8e39e --- /dev/null +++ b/services/activity-service/internal/app/workers.go @@ -0,0 +1,20 @@ +package app + +import ( + "hyapp/services/activity-service/internal/config" + luckygiftservice "hyapp/services/activity-service/internal/service/luckygift" +) + +func luckyGiftWorkerOptions(nodeID string, cfg config.LuckyGiftWorkerConfig) luckygiftservice.WorkerOptions { + return luckygiftservice.WorkerOptions{ + WorkerID: nodeID + "-lucky-gift", + PollInterval: cfg.WorkerPollInterval, + BatchSize: cfg.WorkerBatchSize, + Concurrency: cfg.WorkerConcurrency, + LockTTL: cfg.WorkerLockTTL, + MaxRetry: cfg.WorkerMaxRetry, + PublishTimeout: cfg.PublishTimeout, + StatsInterval: cfg.StatsRefreshInterval, + StatsBatchSize: cfg.StatsBatchSize, + } +} diff --git a/services/activity-service/internal/config/config.go b/services/activity-service/internal/config/config.go index 8d537842..829887d1 100644 --- a/services/activity-service/internal/config/config.go +++ b/services/activity-service/internal/config/config.go @@ -25,8 +25,12 @@ type Config struct { UserServiceAddr string `yaml:"user_service_addr"` // WalletServiceAddr 是任务奖励入账依赖;activity 只发命令,不直接写余额。 WalletServiceAddr string `yaml:"wallet_service_addr"` + // RoomServiceAddr 是房间流水奖励结算读取房主快照的内部 gRPC 地址。 + RoomServiceAddr string `yaml:"room_service_addr"` // FirstRechargeRewardWorker 控制首冲奖励对 wallet_outbox 充值事实的本地消费。 FirstRechargeRewardWorker FirstRechargeRewardWorkerConfig `yaml:"first_recharge_reward_worker"` + // CumulativeRechargeRewardWorker 控制累充奖励对 wallet_outbox 充值事实的本地消费。 + CumulativeRechargeRewardWorker CumulativeRechargeRewardWorkerConfig `yaml:"cumulative_recharge_reward_worker"` // RedPacketBroadcastWorker 控制红包创建事实转区域飘屏 outbox 的本地消费。 RedPacketBroadcastWorker RedPacketBroadcastWorkerConfig `yaml:"red_packet_broadcast_worker"` // LuckyGiftWorker 控制幸运礼物 draw outbox 的返奖和房间 IM 补偿。 @@ -61,6 +65,12 @@ type FirstRechargeRewardWorkerConfig struct { Enabled bool `yaml:"enabled"` } +// CumulativeRechargeRewardWorkerConfig 保存累充奖励钱包充值事实消费策略。 +type CumulativeRechargeRewardWorkerConfig struct { + // Enabled 控制是否启动 wallet_outbox MQ 消费;关闭后仍可通过 gRPC 消费入口补偿。 + Enabled bool `yaml:"enabled"` +} + // RedPacketBroadcastWorkerConfig 保存红包创建事实消费策略。 type RedPacketBroadcastWorkerConfig struct { // Enabled 控制是否启动 wallet_outbox MQ 消费。 @@ -150,6 +160,7 @@ type WalletOutboxMQConfig struct { Topic string `yaml:"topic"` RealtimeTopic string `yaml:"realtime_topic"` FirstRechargeConsumerGroup string `yaml:"first_recharge_consumer_group"` + CumulativeRechargeConsumerGroup string `yaml:"cumulative_recharge_consumer_group"` RedPacketBroadcastConsumerGroup string `yaml:"red_packet_broadcast_consumer_group"` ConsumerMaxReconsumeTimes int32 `yaml:"consumer_max_reconsume_times"` } @@ -173,9 +184,13 @@ 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", + RoomServiceAddr: "127.0.0.1:13001", FirstRechargeRewardWorker: FirstRechargeRewardWorkerConfig{ Enabled: false, }, + CumulativeRechargeRewardWorker: CumulativeRechargeRewardWorkerConfig{ + Enabled: false, + }, RedPacketBroadcastWorker: RedPacketBroadcastWorkerConfig{ Enabled: false, }, @@ -238,6 +253,7 @@ func defaultRocketMQConfig() RocketMQConfig { Topic: "hyapp_wallet_outbox", RealtimeTopic: "", FirstRechargeConsumerGroup: "hyapp-activity-first-recharge-wallet-outbox", + CumulativeRechargeConsumerGroup: "hyapp-activity-cumulative-recharge-wallet-outbox", RedPacketBroadcastConsumerGroup: "hyapp-activity-red-packet-wallet-outbox", ConsumerMaxReconsumeTimes: 16, }, @@ -266,6 +282,9 @@ func Load(path string) (Config, error) { if strings.TrimSpace(cfg.WalletServiceAddr) == "" { cfg.WalletServiceAddr = Default().WalletServiceAddr } + if strings.TrimSpace(cfg.RoomServiceAddr) == "" { + cfg.RoomServiceAddr = Default().RoomServiceAddr + } cfg.ServiceName = strings.TrimSpace(cfg.ServiceName) if cfg.ServiceName == "" { cfg.ServiceName = "activity-service" @@ -342,7 +361,7 @@ func Load(path string) (Config, error) { return Config{}, err } cfg.RocketMQ = rocketMQ - if (cfg.FirstRechargeRewardWorker.Enabled || cfg.RedPacketBroadcastWorker.Enabled) && !cfg.RocketMQ.WalletOutbox.Enabled { + if (cfg.FirstRechargeRewardWorker.Enabled || cfg.CumulativeRechargeRewardWorker.Enabled || cfg.RedPacketBroadcastWorker.Enabled) && !cfg.RocketMQ.WalletOutbox.Enabled { return Config{}, errors.New("wallet outbox workers require rocketmq.wallet_outbox.enabled") } if cfg.LuckyGiftWorker.Enabled && !cfg.TencentIM.Enabled { @@ -376,6 +395,9 @@ func normalizeRocketMQConfig(cfg RocketMQConfig) (RocketMQConfig, error) { if cfg.WalletOutbox.FirstRechargeConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.FirstRechargeConsumerGroup); cfg.WalletOutbox.FirstRechargeConsumerGroup == "" { cfg.WalletOutbox.FirstRechargeConsumerGroup = defaults.WalletOutbox.FirstRechargeConsumerGroup } + if cfg.WalletOutbox.CumulativeRechargeConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.CumulativeRechargeConsumerGroup); cfg.WalletOutbox.CumulativeRechargeConsumerGroup == "" { + cfg.WalletOutbox.CumulativeRechargeConsumerGroup = defaults.WalletOutbox.CumulativeRechargeConsumerGroup + } if cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = strings.TrimSpace(cfg.WalletOutbox.RedPacketBroadcastConsumerGroup); cfg.WalletOutbox.RedPacketBroadcastConsumerGroup == "" { cfg.WalletOutbox.RedPacketBroadcastConsumerGroup = defaults.WalletOutbox.RedPacketBroadcastConsumerGroup } diff --git a/services/activity-service/internal/domain/cumulativerecharge/cumulative_recharge.go b/services/activity-service/internal/domain/cumulativerecharge/cumulative_recharge.go new file mode 100644 index 00000000..4eb4bff3 --- /dev/null +++ b/services/activity-service/internal/domain/cumulativerecharge/cumulative_recharge.go @@ -0,0 +1,130 @@ +package cumulativerecharge + +const ( + TierStatusActive = "active" + TierStatusInactive = "inactive" + + GrantStatusPending = "pending" + GrantStatusGranted = "granted" + GrantStatusFailed = "failed" + + ReasonEligible = "eligible" + ReasonNotConfigured = "not_configured" + ReasonDisabled = "disabled" + ReasonNoQualifyingValue = "no_qualifying_value" + ReasonAlreadyConsumed = "already_consumed" + ReasonNoTierMatched = "no_tier_matched" + ReasonPendingReward = "pending_reward" + + RechargeEventWalletRecorded = "WalletRechargeRecorded" + RechargeTypeCoinSeller = "coin_seller_transfer" +) + +// Tier 是累充奖励的 USD 档位,金额统一用美分保存,避免后台小数金额和发放判断出现精度漂移。 +type Tier struct { + TierID int64 + TierCode string + TierName string + ThresholdUSDMinor int64 + ResourceGroupID int64 + Status string + SortOrder int32 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Config 是当前 App 的累充奖励配置;activity-service 保存档位快照并负责后续充值事件判定。 +type Config struct { + AppCode string + Enabled bool + Tiers []Tier + UpdatedByAdminID int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Progress 是用户在一个 UTC 自然周内的累充累计投影。 +type Progress struct { + AppCode string + CycleKey string + UserID int64 + TotalUSDMinor int64 + TotalCoinAmount int64 + FirstRechargedAtMS int64 + LastRechargedAtMS int64 + UpdatedAtMS int64 +} + +// Grant 是用户命中某个累充档位后的资源组发放事实;event 字段用于 MQ 重试复用原命令。 +type Grant struct { + GrantID string + AppCode string + CycleKey string + UserID int64 + EventID string + TransactionID string + CommandID string + TierID int64 + TierCode string + ThresholdUSDMinor int64 + ResourceGroupID int64 + ReachedUSDMinor int64 + QualifyingUSDMinor int64 + RechargeCoinAmount int64 + RechargeType string + Status string + WalletCommandID string + WalletGrantID string + FailureReason string + GrantedAtMS int64 + CreatedAtMS int64 + UpdatedAtMS 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 + QualifyingUSDMinor int64 + PayloadJSON string + OccurredAtMS int64 +} + +// Cycle 表达 UTC 自然周周期边界。 +type Cycle struct { + Key string + StartMS int64 + EndMS int64 +} + +// StatusResult 是 App H5 页面读取的完整累充状态。 +type StatusResult struct { + Config Config + Progress Progress + Grants []Grant + Cycle Cycle + ServerTimeMS int64 +} + +// PrepareResult 表达一次充值事实在 MySQL 事务内是否产生了需要执行的发放命令。 +type PrepareResult struct { + Grants []Grant + Consumed bool + Reason string +} + +// GrantQuery 是后台发放记录分页查询条件。 +type GrantQuery struct { + Status string + UserID int64 + CycleKey string + Page int32 + PageSize int32 +} diff --git a/services/activity-service/internal/domain/registrationreward/registration_reward.go b/services/activity-service/internal/domain/registrationreward/registration_reward.go index b9ff9393..e10328ef 100644 --- a/services/activity-service/internal/domain/registrationreward/registration_reward.go +++ b/services/activity-service/internal/domain/registrationreward/registration_reward.go @@ -77,10 +77,12 @@ type PrepareResult struct { Reason string } -// ClaimQuery 是后台领取记录分页查询条件;用户搜索由 admin-server 先解析成 user_id。 +// ClaimQuery 是后台领取记录分页查询条件;用户搜索由 admin-server 先解析成 user_id,领取时间筛选按 claimed_at_ms 优先、created_at_ms 兜底的页面展示口径执行。 type ClaimQuery struct { - Status string - UserID int64 - Page int32 - PageSize int32 + Status string + UserID int64 + ClaimedStartMS int64 + ClaimedEndMS int64 + Page int32 + PageSize int32 } diff --git a/services/activity-service/internal/domain/roomturnoverreward/room_turnover_reward.go b/services/activity-service/internal/domain/roomturnoverreward/room_turnover_reward.go new file mode 100644 index 00000000..04cfab4b --- /dev/null +++ b/services/activity-service/internal/domain/roomturnoverreward/room_turnover_reward.go @@ -0,0 +1,120 @@ +package roomturnoverreward + +const ( + TierStatusActive = "active" + TierStatusInactive = "inactive" + + SettlementStatusPending = "pending" + SettlementStatusGranted = "granted" + SettlementStatusFailed = "failed" + + EventStatusConsumed = "consumed" + EventStatusDuplicate = "duplicate" + EventStatusSkipped = "skipped" +) + +// Tier 是后台配置的房间流水奖励档位,结算只发命中的最高有效档。 +type Tier struct { + TierID int64 + TierCode string + TierName string + ThresholdCoinSpent int64 + RewardCoinAmount int64 + Status string + SortOrder int32 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Config 是当前 App 的房间流水奖励配置。 +type Config struct { + AppCode string + Enabled bool + Tiers []Tier + UpdatedByAdminID int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// Progress 是单房间单 UTC 周期的金币流水聚合。 +type Progress struct { + AppCode string + RoomID string + PeriodStartMS int64 + PeriodEndMS int64 + CoinSpent int64 + LastEventAtMS int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// RoomGiftEvent 是 room-service RoomGiftSent 事实映射后的最小聚合输入。 +type RoomGiftEvent struct { + EventID string + EventType string + AppCode string + RoomID string + CoinSpent int64 + OccurredAtMS int64 +} + +// EventResult 表达房间礼物事件是否参与流水聚合。 +type EventResult struct { + EventID string + Status string +} + +// Settlement 是某个房间单个 UTC 周期的奖励发放事实。 +type Settlement struct { + SettlementID string + AppCode string + RoomID string + OwnerUserID int64 + PeriodStartMS int64 + PeriodEndMS int64 + CoinSpent int64 + TierID int64 + TierCode string + ThresholdCoinSpent int64 + RewardCoinAmount int64 + Status string + WalletCommandID string + WalletTransactionID string + FailureReason string + SettledAtMS int64 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// StatusResult 是 H5 查询当前用户房间流水奖励活动时的展示投影。 +type StatusResult struct { + Config Config + RoomID string + OwnerUserID int64 + PeriodStartMS int64 + PeriodEndMS int64 + CurrentCoinSpent int64 + ExpectedRewardCoinAmount int64 + MatchedTier Tier + LatestSettlement Settlement + ServerTimeMS int64 +} + +// SettlementQuery 是后台结算记录分页筛选条件。 +type SettlementQuery struct { + Status string + RoomID string + OwnerUserID int64 + PeriodStartMS int64 + Page int32 + PageSize int32 +} + +// BatchResult 汇总 cron 一次处理的 settlement 创建和发币结果。 +type BatchResult struct { + ClaimedCount int32 + ProcessedCount int32 + SuccessCount int32 + FailureCount int32 + HasMore bool +} diff --git a/services/activity-service/internal/domain/weeklystar/weekly_star.go b/services/activity-service/internal/domain/weeklystar/weekly_star.go new file mode 100644 index 00000000..2edb51c2 --- /dev/null +++ b/services/activity-service/internal/domain/weeklystar/weekly_star.go @@ -0,0 +1,126 @@ +package weeklystar + +const ( + // ActivityCode 是通用指定礼物积分活动框架中用于承载周星的活动编码。 + ActivityCode = "weekly_star" + + StatusDraft = "draft" + StatusActive = "active" + StatusDisabled = "disabled" + StatusSettling = "settling" + StatusSettled = "settled" + + EventStatusConsumed = "consumed" + EventStatusSkipped = "skipped" + EventStatusDuplicate = "duplicate" + + SettlementStatusPending = "pending" + SettlementStatusRunning = "running" + SettlementStatusGranted = "granted" + SettlementStatusFailed = "failed" + + GrantSourceWeeklyStar = "weekly_star" +) + +// Gift describes one gift that can add score inside a weekly star cycle. +type Gift struct { + AppCode string + CycleID string + GiftID string + SortOrder int32 +} + +// Reward maps one weekly star rank to the resource group granted at settlement time. +type Reward struct { + AppCode string + CycleID string + RankNo int32 + ResourceGroupID int64 +} + +// Cycle is the region-scoped UTC time window that controls weekly star scoring and rewards. +type Cycle struct { + AppCode string + CycleID string + ActivityCode string + RegionID int64 + Title string + Status string + StartMS int64 + EndMS int64 + CreatedByAdminID int64 + UpdatedByAdminID int64 + SettledAtMS int64 + CreatedAtMS int64 + UpdatedAtMS int64 + Gifts []Gift + Rewards []Reward +} + +// CycleCommand is the admin mutation input after transport normalization. +type CycleCommand struct { + Cycle Cycle + OperatorAdminID int64 + RequireNewRecord bool +} + +// ListQuery filters admin cycle list reads. Region 0 is a real filter for default cycles. +type ListQuery struct { + RegionID *int64 + Status string + StartMS int64 + EndMS int64 + Page int32 + PageSize int32 +} + +// GiftEvent is the committed room-service gift fact consumed by weekly star. +type GiftEvent struct { + EventID string + UserID int64 + GiftID string + ScoreDelta int64 + RegionID int64 + OccurredAtMS int64 +} + +// EventResult describes idempotent score consumption for one source event. +type EventResult struct { + EventID string + Status string + CycleID string + ScoreDelta int64 +} + +// LeaderboardEntry is the score row plus deterministic rank within a cycle. +type LeaderboardEntry struct { + RankNo int32 + UserID int64 + Score int64 + FirstScoredAtMS int64 + LastScoredAtMS int64 +} + +// Settlement is one resource-group grant job for a settled Top rank. +type Settlement struct { + AppCode string + SettlementID string + CycleID string + RankNo int32 + UserID int64 + Score int64 + ResourceGroupID int64 + WalletCommandID string + WalletGrantID string + Status string + FailureReason string + AttemptCount int32 + CreatedAtMS int64 + UpdatedAtMS int64 +} + +// HistoryCycle groups a completed cycle with its Top entries for H5 history reads. +type HistoryCycle struct { + Cycle Cycle + TopEntries []LeaderboardEntry +} diff --git a/services/activity-service/internal/service/cumulativerecharge/service.go b/services/activity-service/internal/service/cumulativerecharge/service.go new file mode 100644 index 00000000..caa93dca --- /dev/null +++ b/services/activity-service/internal/service/cumulativerecharge/service.go @@ -0,0 +1,356 @@ +package cumulativerecharge + +import ( + "context" + "fmt" + "sort" + "strings" + "time" + + "google.golang.org/grpc" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/cumulativerecharge" +) + +const ( + grantSource = "cumulative_recharge_reward" + grantReason = "cumulative_recharge_reward" +) + +// Repository 是累充奖励配置、周期累计、event 幂等和发放事实的唯一持久化边界。 +type Repository interface { + GetCumulativeRechargeRewardConfig(ctx context.Context) (domain.Config, bool, error) + UpdateCumulativeRechargeRewardConfig(ctx context.Context, config domain.Config, nowMS int64) (domain.Config, error) + GetCumulativeRechargeRewardProgress(ctx context.Context, cycleKey string, userID int64) (domain.Progress, bool, error) + ListCumulativeRechargeRewardGrantsByUserCycle(ctx context.Context, cycleKey string, userID int64) ([]domain.Grant, error) + PrepareCumulativeRechargeRewardGrants(ctx context.Context, event domain.RechargeEvent, cycle domain.Cycle, nowMS int64) (domain.PrepareResult, error) + MarkCumulativeRechargeRewardGrantGranted(ctx context.Context, grantID string, walletGrantID string, grantedAtMS int64) (domain.Grant, error) + MarkCumulativeRechargeRewardGrantFailed(ctx context.Context, grantID string, failureReason string, nowMS int64) error + ListCumulativeRechargeRewardGrants(ctx context.Context, query domain.GrantQuery) ([]domain.Grant, int64, error) +} + +// WalletClient 是累充奖励唯一外部副作用;资源组展开仍由 wallet-service 原子完成。 +type WalletClient interface { + GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) +} + +// Service 承载累充奖励 App 查询、后台配置和 wallet 充值事实消费用例。 +type Service struct { + repository Repository + wallet WalletClient + now func() time.Time +} + +func New(repository Repository, wallet WalletClient) *Service { + return &Service{repository: repository, wallet: wallet, now: time.Now} +} + +func (s *Service) SetClock(now func() time.Time) { + if now != nil { + s.now = now + } +} + +// GetStatus 返回当前 UTC 自然周内的用户累计、档位和发放状态;未配置时返回空配置而不是错误。 +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") + } + now := s.now().UTC() + cycle := CycleForTime(now) + result := domain.StatusResult{Cycle: cycle, ServerTimeMS: now.UnixMilli()} + + // H5 只展示当前生效配置里的 active 档位;inactive 档位保留给后台编辑和历史 grant 审计。 + config, exists, err := s.repository.GetCumulativeRechargeRewardConfig(ctx) + if err != nil { + return domain.StatusResult{}, err + } + if exists { + config.Tiers = activeTiers(config.Tiers) + result.Config = config + } else { + result.Config = domain.Config{AppCode: appcode.FromContext(ctx)} + } + progress, _, err := s.repository.GetCumulativeRechargeRewardProgress(ctx, cycle.Key, userID) + if err != nil { + return domain.StatusResult{}, err + } + if progress.UserID == 0 { + progress = domain.Progress{AppCode: appcode.FromContext(ctx), CycleKey: cycle.Key, UserID: userID} + } + result.Progress = progress + grants, err := s.repository.ListCumulativeRechargeRewardGrantsByUserCycle(ctx, cycle.Key, userID) + if err != nil { + return domain.StatusResult{}, err + } + result.Grants = grants + 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.GetCumulativeRechargeRewardConfig(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 + } + // 后台配置是“未来事件规则”:保存时不扫描历史充值,也不改写已经创建的 grant 快照。 + config.AppCode = appcode.FromContext(ctx) + config.Tiers = normalizeTiers(config.Tiers) + if err := validateConfig(config); err != nil { + return domain.Config{}, err + } + return s.repository.UpdateCumulativeRechargeRewardConfig(ctx, config, s.now().UTC().UnixMilli()) +} + +// Consume 处理成功充值事实;一次充值可能让用户跨过多个累充档位,所以会返回多条 grant。 +func (s *Service) Consume(ctx context.Context, event domain.RechargeEvent) ([]domain.Grant, bool, string, error) { + if err := s.requireRepository(); err != nil { + return nil, false, "", err + } + event = normalizeRechargeEvent(event) + if err := validateRechargeEvent(event); err != nil { + return nil, false, "", err + } + cycle := CycleForTime(time.UnixMilli(event.OccurredAtMS).UTC()) + + // Prepare 在一个 MySQL 事务里完成 event 幂等、周期累计和待发放 grant 创建; + // 这里不直接发资源,避免外部 wallet 副作用进入数据库事务导致长锁或半提交。 + prepared, err := s.repository.PrepareCumulativeRechargeRewardGrants(ctx, event, cycle, s.now().UTC().UnixMilli()) + if err != nil { + return nil, false, "", err + } + if len(prepared.Grants) == 0 { + return nil, prepared.Consumed, prepared.Reason, nil + } + if s.wallet == nil { + return nil, false, "", xerr.New(xerr.Unavailable, "wallet client is not configured") + } + + granted := make([]domain.Grant, 0, len(prepared.Grants)) + for _, grant := range prepared.Grants { + // 每个档位使用稳定 wallet command id;MQ 重投或上次发放失败时复用同一命令,交给 wallet-service 幂等。 + resp, err := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ + CommandId: grant.WalletCommandID, + AppCode: appcode.FromContext(ctx), + TargetUserId: grant.UserID, + GroupId: grant.ResourceGroupID, + Reason: grantReason, + OperatorUserId: grant.UserID, + GrantSource: grantSource, + }) + if err != nil { + // wallet 调用失败只把 grant 标记为 failed,不删除记录;下一次同 event 重试会重新置回 pending 后继续发放。 + _ = s.repository.MarkCumulativeRechargeRewardGrantFailed(ctx, grant.GrantID, xerr.MessageOf(err), s.now().UTC().UnixMilli()) + return granted, false, prepared.Reason, err + } + walletGrantID := "" + if resp.GetGrant() != nil { + walletGrantID = resp.GetGrant().GetGrantId() + } + // 只有拿到 wallet 回执后才落 granted,后台记录因此可以区分“已命中但未到账”和“已到账”。 + updated, err := s.repository.MarkCumulativeRechargeRewardGrantGranted(ctx, grant.GrantID, walletGrantID, s.now().UTC().UnixMilli()) + if err != nil { + return granted, false, prepared.Reason, err + } + granted = append(granted, updated) + } + return granted, true, domain.ReasonEligible, nil +} + +func (s *Service) ListGrants(ctx context.Context, query domain.GrantQuery) ([]domain.Grant, int64, error) { + if err := s.requireRepository(); err != nil { + return nil, 0, err + } + query.Status = strings.TrimSpace(query.Status) + query.CycleKey = strings.TrimSpace(query.CycleKey) + if query.Page <= 0 { + query.Page = 1 + } + if query.PageSize <= 0 { + query.PageSize = 20 + } + if query.PageSize > 100 { + query.PageSize = 100 + } + return s.repository.ListCumulativeRechargeRewardGrants(ctx, query) +} + +// ConsumeWalletRechargeEvent handles one MQ-delivered wallet recharge fact. +func (s *Service) ConsumeWalletRechargeEvent(ctx context.Context, event domain.RechargeEvent) error { + if s == nil || s.repository == nil { + return xerr.New(xerr.Unavailable, "cumulative recharge reward repository is not configured") + } + if event.EventType != domain.RechargeEventWalletRecorded { + return nil + } + _, _, _, err := s.Consume(appcode.WithContext(ctx, event.AppCode), event) + return err +} + +func (s *Service) requireRepository() error { + if s == nil || s.repository == nil { + return xerr.New(xerr.Unavailable, "cumulative recharge reward repository is not configured") + } + return nil +} + +// CycleForTime returns the UTC natural-week cycle that contains value. +func CycleForTime(value time.Time) domain.Cycle { + utc := value.UTC() + dayStart := time.Date(utc.Year(), utc.Month(), utc.Day(), 0, 0, 0, 0, time.UTC) + // Go 的 Weekday 从 Sunday 开始,这里转换成 Monday=0,用于计算 UTC 自然周起点。 + daysSinceMonday := (int(dayStart.Weekday()) + 6) % 7 + start := dayStart.AddDate(0, 0, -daysSinceMonday) + end := start.AddDate(0, 0, 7) + isoYear, isoWeek := start.ISOWeek() + return domain.Cycle{ + Key: fmt.Sprintf("%04d-W%02d", isoYear, isoWeek), + StartMS: start.UnixMilli(), + EndMS: end.UnixMilli() - 1, + } +} + +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), + ThresholdUSDMinor: tier.ThresholdUSDMinor, + ResourceGroupID: tier.ResourceGroupID, + Status: status, + SortOrder: tier.SortOrder, + }) + } + // 排序同时服务后台回显和 H5 展示;sort_order 相同则按门槛金额升序保证跨档发放顺序稳定。 + sort.SliceStable(items, func(i, j int) bool { + if items[i].SortOrder == items[j].SortOrder { + return items[i].ThresholdUSDMinor < items[j].ThresholdUSDMinor + } + 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 { + // tier_code 是后台编辑和审计展示标识,不参与唯一发放;真正的发放唯一性由 tier_id 绑定。 + 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.ThresholdUSDMinor <= 0 { + return xerr.New(xerr.InvalidArgument, "threshold_usd_minor must be greater than zero") + } + 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") + } + // 同一个生效配置里 active 门槛不能重复,否则用户达标后无法用金额判断哪个档位先展示。 + if hasDuplicateThreshold(active) { + return xerr.New(xerr.InvalidArgument, "active tier threshold_usd_minor is duplicated") + } + return nil +} + +func hasDuplicateThreshold(tiers []domain.Tier) bool { + seen := make(map[int64]struct{}, len(tiers)) + for _, tier := range tiers { + if _, exists := seen[tier.ThresholdUSDMinor]; exists { + return true + } + seen[tier.ThresholdUSDMinor] = struct{}{} + } + return false +} + +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.ToLower(strings.TrimSpace(event.RechargeType)) + if event.RechargeType == "" { + event.RechargeType = domain.RechargeTypeCoinSeller + } + if strings.TrimSpace(event.PayloadJSON) == "" { + event.PayloadJSON = "{}" + } + return event +} + +func validateRechargeEvent(event domain.RechargeEvent) error { + if event.AppCode == "" || event.EventID == "" || event.TransactionID == "" || event.CommandID == "" { + return xerr.New(xerr.InvalidArgument, "recharge event identity is incomplete") + } + if event.UserID <= 0 { + return xerr.New(xerr.InvalidArgument, "user_id is required") + } + if event.QualifyingUSDMinor <= 0 { + return xerr.New(xerr.InvalidArgument, "qualifying_usd_minor must be greater than zero") + } + if event.OccurredAtMS <= 0 { + return xerr.New(xerr.InvalidArgument, "occurred_at_ms is required") + } + return nil +} + +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) + } + } + sort.SliceStable(items, func(i, j int) bool { + if items[i].SortOrder == items[j].SortOrder { + return items[i].ThresholdUSDMinor < items[j].ThresholdUSDMinor + } + return items[i].SortOrder < items[j].SortOrder + }) + return items +} diff --git a/services/activity-service/internal/service/luckygift/service.go b/services/activity-service/internal/service/luckygift/service.go index 9471b555..18038397 100644 --- a/services/activity-service/internal/service/luckygift/service.go +++ b/services/activity-service/internal/service/luckygift/service.go @@ -36,6 +36,7 @@ type Repository interface { MarkLuckyGiftOutboxRetryable(ctx context.Context, event domain.DrawOutbox, retryCount int, nextRetryAtMS int64, lastErr string, nowMS int64) error MarkLuckyGiftOutboxFailed(ctx context.Context, event domain.DrawOutbox, retryCount int, lastErr string, nowMS int64) error RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, nowMS int64, batchSize int) (int, error) + RefreshLuckyGiftDatabiStatsSnapshots(ctx context.Context, nowMS int64, batchSize int) (int, error) MarkLuckyGiftDrawGranted(ctx context.Context, appCode string, drawID string, walletTransactionID string, nowMS int64) error MarkLuckyGiftDrawFailed(ctx context.Context, appCode string, drawID string, failureReason string, nowMS int64) error // 批量抽奖只产生一条聚合 outbox;worker 处理后需要用 draw_ids 一次性收敛所有明细状态。 @@ -172,6 +173,9 @@ func (s *Service) RunWorker(ctx context.Context, options WorkerOptions) { if _, err := s.repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, now.UnixMilli(), options.StatsBatchSize); err != nil && ctx.Err() == nil { logx.Error(ctx, "lucky_gift_admin_stats_refresh_failed", err, slog.String("worker_id", options.WorkerID)) } + if _, err := s.repository.RefreshLuckyGiftDatabiStatsSnapshots(ctx, now.UnixMilli(), options.StatsBatchSize); err != nil && ctx.Err() == nil { + logx.Error(ctx, "lucky_gift_databi_stats_refresh_failed", err, slog.String("worker_id", options.WorkerID)) + } nextStatsRefresh = now.Add(options.StatsInterval) } select { diff --git a/services/activity-service/internal/service/luckygift/service_test.go b/services/activity-service/internal/service/luckygift/service_test.go index ec2a6555..a54aba35 100644 --- a/services/activity-service/internal/service/luckygift/service_test.go +++ b/services/activity-service/internal/service/luckygift/service_test.go @@ -491,6 +491,10 @@ func (r *fakeLuckyGiftRepository) RefreshLuckyGiftAdminStatsSnapshots(context.Co return 0, nil } +func (r *fakeLuckyGiftRepository) RefreshLuckyGiftDatabiStatsSnapshots(context.Context, int64, int) (int, error) { + return 0, nil +} + func (r *fakeLuckyGiftRepository) MarkLuckyGiftDrawGranted(_ context.Context, _ string, drawID string, _ string, _ int64) error { r.grantedDrawID = drawID return nil diff --git a/services/activity-service/internal/service/registrationreward/service.go b/services/activity-service/internal/service/registrationreward/service.go index e4d0a256..f6731cab 100644 --- a/services/activity-service/internal/service/registrationreward/service.go +++ b/services/activity-service/internal/service/registrationreward/service.go @@ -26,6 +26,7 @@ type Repository interface { MarkRegistrationRewardClaimGranted(ctx context.Context, claimID string, walletTransactionID string, resourceGrantID string, grantedAtMS int64) (domain.Claim, error) MarkRegistrationRewardClaimFailed(ctx context.Context, claimID string, failureReason string, nowMS int64) error ListRegistrationRewardClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, error) + CountRegistrationRewardGrantedByDay(ctx context.Context, rewardDay string) (int64, error) } // WalletClient 是注册奖励发放的唯一外部副作用;金币和资源组都依赖 wallet-service 幂等命令。 @@ -176,9 +177,9 @@ func (s *Service) IssueRegistrationReward(ctx context.Context, command domain.Is return claim, eligibility, true, nil } -func (s *Service) ListClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, error) { +func (s *Service) ListClaims(ctx context.Context, query domain.ClaimQuery) ([]domain.Claim, int64, int64, error) { if err := s.requireRepository(); err != nil { - return nil, 0, err + return nil, 0, 0, err } query.Status = strings.TrimSpace(query.Status) if query.Page <= 0 { @@ -190,7 +191,16 @@ func (s *Service) ListClaims(ctx context.Context, query domain.ClaimQuery) ([]do if query.PageSize > 100 { query.PageSize = 100 } - return s.repository.ListRegistrationRewardClaims(ctx, query) + claims, total, err := s.repository.ListRegistrationRewardClaims(ctx, query) + if err != nil { + return nil, 0, 0, err + } + // 今日已领数量用于后台配置页展示,它必须使用同一套 UTC reward_day 口径,避免后台本地时区和发放额度统计出现错位。 + todayClaimedCount, err := s.repository.CountRegistrationRewardGrantedByDay(ctx, rewardDay(s.now())) + if err != nil { + return nil, 0, 0, err + } + return claims, total, todayClaimedCount, nil } func (s *Service) requireRepository() error { diff --git a/services/activity-service/internal/service/roomturnoverreward/service.go b/services/activity-service/internal/service/roomturnoverreward/service.go new file mode 100644 index 00000000..9a8afbae --- /dev/null +++ b/services/activity-service/internal/service/roomturnoverreward/service.go @@ -0,0 +1,517 @@ +package roomturnoverreward + +import ( + "context" + "sort" + "strings" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/roomturnoverreward" +) + +const rewardReason = "room_turnover_reward" + +// Repository 是房间流水奖励配置、周期聚合和结算记录的唯一持久化边界。 +type Repository interface { + GetRoomTurnoverRewardConfig(ctx context.Context) (domain.Config, bool, error) + UpdateRoomTurnoverRewardConfig(ctx context.Context, config domain.Config, nowMS int64) (domain.Config, error) + ConsumeRoomTurnoverGiftEvent(ctx context.Context, event domain.RoomGiftEvent, periodStartMS int64, periodEndMS int64, nowMS int64) (domain.EventResult, error) + GetRoomTurnoverRewardProgress(ctx context.Context, roomID string, periodStartMS int64) (domain.Progress, bool, error) + GetLatestRoomTurnoverRewardSettlement(ctx context.Context, roomID string) (domain.Settlement, bool, error) + ListRoomTurnoverRewardSettlements(ctx context.Context, query domain.SettlementQuery) ([]domain.Settlement, int64, error) + ListUnsettledRoomTurnoverRewardProgress(ctx context.Context, periodStartMS int64, limit int) ([]domain.Progress, error) + InsertRoomTurnoverRewardSettlement(ctx context.Context, settlement domain.Settlement, nowMS int64) (domain.Settlement, bool, error) + ListPendingRoomTurnoverRewardSettlements(ctx context.Context, limit int) ([]domain.Settlement, error) + GetRoomTurnoverRewardSettlement(ctx context.Context, settlementID string) (domain.Settlement, bool, error) + ResetRoomTurnoverRewardSettlementForRetry(ctx context.Context, settlementID string, ownerUserID int64, nowMS int64) (domain.Settlement, error) + MarkRoomTurnoverRewardSettlementGranted(ctx context.Context, settlementID string, walletTransactionID string, grantedAtMS int64) (domain.Settlement, error) + MarkRoomTurnoverRewardSettlementFailed(ctx context.Context, settlementID string, reason string, nowMS int64) error +} + +// WalletClient 是房间流水奖励唯一外部发币副作用。 +type WalletClient interface { + CreditRoomTurnoverReward(ctx context.Context, req *walletv1.CreditRoomTurnoverRewardRequest, opts ...grpc.CallOption) (*walletv1.CreditRoomTurnoverRewardResponse, error) +} + +// RoomQueryClient 只读取 room-service 的房主快照,不拥有房间状态。 +type RoomQueryClient interface { + AdminGetRoom(ctx context.Context, req *roomv1.AdminGetRoomRequest, opts ...grpc.CallOption) (*roomv1.AdminGetRoomResponse, error) +} + +// Service 承载房间流水奖励 App 查询、后台配置、事件聚合和每周结算。 +type Service struct { + repository Repository + wallet WalletClient + room RoomQueryClient + now func() time.Time +} + +func New(repository Repository, wallet WalletClient, room RoomQueryClient) *Service { + return &Service{repository: repository, wallet: wallet, room: room, now: time.Now} +} + +func (s *Service) SetClock(now func() time.Time) { + if now != nil { + s.now = now + } +} + +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.GetRoomTurnoverRewardConfig(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.UpdateRoomTurnoverRewardConfig(ctx, config, s.now().UTC().UnixMilli()) +} + +func (s *Service) GetStatus(ctx context.Context, userID int64, roomID string, ownerUserID 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") + } + // App 展示和每周结算必须使用同一套 UTC 周窗口;这里用 service clock 统一可测试时间源,避免 H5、本地测试和 cron 看到不同周期。 + now := s.now().UTC() + start, end := WeekWindow(now) + result := domain.StatusResult{ + RoomID: strings.TrimSpace(roomID), + OwnerUserID: ownerUserID, + PeriodStartMS: start.UnixMilli(), + PeriodEndMS: end.UnixMilli(), + ServerTimeMS: now.UnixMilli(), + } + config, exists, err := s.repository.GetRoomTurnoverRewardConfig(ctx) + if err != nil { + return domain.StatusResult{}, err + } + if exists { + config.Tiers = sortTiersForDisplay(config.Tiers) + result.Config = config + } else { + // 未配置不是异常:后台首次进入或活动未上线时,H5 仍需要周期时间和空档位来渲染默认态。 + result.Config = domain.Config{AppCode: appcode.FromContext(ctx)} + } + if result.RoomID == "" { + // 当前用户没有自己的房间时不能查询流水聚合;直接返回配置和周期,让 H5 显示无房间/未参与状态。 + return result, nil + } + progress, found, err := s.repository.GetRoomTurnoverRewardProgress(ctx, result.RoomID, result.PeriodStartMS) + if err != nil { + return domain.StatusResult{}, err + } + if found { + result.CurrentCoinSpent = progress.CoinSpent + } + if tier, matched := MatchHighestTier(activeTiers(result.Config.Tiers), result.CurrentCoinSpent); matched { + result.MatchedTier = tier + result.ExpectedRewardCoinAmount = tier.RewardCoinAmount + } + if settlement, found, err := s.repository.GetLatestRoomTurnoverRewardSettlement(ctx, result.RoomID); err != nil { + return domain.StatusResult{}, err + } else if found { + // 最近结算不限定当前周期;周切换后当前流水会清零,但 H5 仍要展示上一周期是否已经发奖或失败。 + result.LatestSettlement = settlement + } + return result, nil +} + +// HandleRoomEvent 把 room-service 已提交送礼事实聚合到对应 UTC 周期房间流水。 +func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (domain.EventResult, error) { + if err := s.requireRepository(); err != nil { + return domain.EventResult{}, err + } + if envelope == nil { + return domain.EventResult{}, xerr.New(xerr.InvalidArgument, "room event envelope is required") + } + if envelope.GetEventType() != "RoomGiftSent" { + // activity-service 订阅的是 room outbox 大类事件;非送礼事实不参与流水奖励,直接标记 skipped,避免无意义重试。 + return domain.EventResult{EventID: envelope.GetEventId(), Status: domain.EventStatusSkipped}, nil + } + var gift roomeventsv1.RoomGiftSent + if err := proto.Unmarshal(envelope.GetBody(), &gift); err != nil { + return domain.EventResult{}, err + } + if strings.TrimSpace(envelope.GetRoomId()) == "" || gift.GetCoinSpent() <= 0 { + // 缺房间或 0 金币不会形成有效房间贡献;这类事件本身没有可补偿数据,跳过比失败重放更安全。 + return domain.EventResult{EventID: envelope.GetEventId(), Status: domain.EventStatusSkipped}, nil + } + occurred := time.UnixMilli(envelope.GetOccurredAtMs()).UTC() + if envelope.GetOccurredAtMs() <= 0 { + // 老事件缺 occurred_at 时使用消费时间兜底,只影响本地兼容,正常 outbox 事件仍以事实发生时间归属周期。 + occurred = s.now().UTC() + } + start, end := WeekWindow(occurred) + // AppCode 以事件信封为准,防止消费者默认上下文把不同 App 的房间流水写进同一组配置和聚合表。 + eventCtx := appcode.WithContext(ctx, envelope.GetAppCode()) + return s.repository.ConsumeRoomTurnoverGiftEvent(eventCtx, domain.RoomGiftEvent{ + EventID: envelope.GetEventId(), + EventType: envelope.GetEventType(), + AppCode: envelope.GetAppCode(), + RoomID: strings.TrimSpace(envelope.GetRoomId()), + CoinSpent: gift.GetCoinSpent(), + OccurredAtMS: occurred.UnixMilli(), + }, start.UnixMilli(), end.UnixMilli(), s.now().UTC().UnixMilli()) +} + +func (s *Service) ListSettlements(ctx context.Context, query domain.SettlementQuery) ([]domain.Settlement, int64, error) { + if err := s.requireRepository(); err != nil { + return nil, 0, err + } + query.Status = strings.TrimSpace(query.Status) + query.RoomID = strings.TrimSpace(query.RoomID) + if query.Page <= 0 { + query.Page = 1 + } + if query.PageSize <= 0 { + query.PageSize = 20 + } + if query.PageSize > 100 { + query.PageSize = 100 + } + return s.repository.ListRoomTurnoverRewardSettlements(ctx, query) +} + +// ProcessSettlementBatch 先为上一 UTC 周期补齐 settlement,再处理 pending 发币。 +func (s *Service) ProcessSettlementBatch(ctx context.Context, batchSize int) (domain.BatchResult, error) { + if err := s.requireRepository(); err != nil { + return domain.BatchResult{}, err + } + if batchSize <= 0 { + batchSize = 100 + } + config, exists, err := s.repository.GetRoomTurnoverRewardConfig(ctx) + if err != nil { + return domain.BatchResult{}, err + } + if !exists || !config.Enabled { + // 活动未配置或关闭时不创建 settlement,也不触碰历史 pending;运营重新开启后再由 cron 正常补偿。 + return domain.BatchResult{}, nil + } + // 只结算上一个完整 UTC 周期;当前周仍在持续接收 RoomGiftSent,不能提前冻结或清空。 + periodStart, periodEnd := PreviousWeekWindow(s.now().UTC()) + result := domain.BatchResult{} + progresses, err := s.repository.ListUnsettledRoomTurnoverRewardProgress(ctx, periodStart.UnixMilli(), batchSize) + if err != nil { + return domain.BatchResult{}, err + } + nowMS := s.now().UTC().UnixMilli() + for _, progress := range progresses { + // settlement 先固化当周流水和命中档位快照,后续运营改配置不会改变已经进入结算队列的周期结果。 + settlement := s.settlementFromProgress(ctx, progress, periodEnd.UnixMilli(), activeTiers(config.Tiers), nowMS) + if settlement.TierID <= 0 { + // 有流水但未达档位也要落失败记录,后台可以解释为什么该房间本周期没有发奖。 + settlement.Status = domain.SettlementStatusFailed + settlement.FailureReason = "tier_not_matched" + } + if settlement.TierID > 0 && settlement.OwnerUserID <= 0 { + // 房主归属以结算时 room-service 快照为准;activity-service 不复制房间 owner 状态,只在需要发奖时同步读取。 + ownerID, ownerErr := s.fetchRoomOwner(ctx, progress.RoomID) + if ownerErr != nil || ownerID <= 0 { + settlement.Status = domain.SettlementStatusFailed + settlement.FailureReason = "room_owner_not_found" + } else { + settlement.OwnerUserID = ownerID + } + } + if _, created, err := s.repository.InsertRoomTurnoverRewardSettlement(ctx, settlement, nowMS); err != nil { + return result, err + } else if created { + // Insert 使用 room_id + period_start_ms 唯一键兜底;重复 cron 只会读回旧记录,不会重复认领同一周期。 + result.ClaimedCount++ + } + } + remaining := batchSize - int(result.ClaimedCount) + if remaining <= 0 { + remaining = batchSize + } + pending, err := s.repository.ListPendingRoomTurnoverRewardSettlements(ctx, remaining) + if err != nil { + return result, err + } + for _, settlement := range pending { + result.ProcessedCount++ + if _, err := s.grantSettlement(ctx, settlement); err != nil { + // grantSettlement 已把失败原因写回 settlement;batch 继续处理后续房间,避免单房间阻塞整周结算。 + result.FailureCount++ + continue + } + result.SuccessCount++ + } + result.HasMore = len(progresses) >= batchSize || len(pending) >= remaining + return result, nil +} + +func (s *Service) RetrySettlement(ctx context.Context, settlementID string) (domain.Settlement, error) { + if err := s.requireRepository(); err != nil { + return domain.Settlement{}, err + } + settlementID = strings.TrimSpace(settlementID) + if settlementID == "" { + return domain.Settlement{}, xerr.New(xerr.InvalidArgument, "settlement_id is required") + } + settlement, exists, err := s.repository.GetRoomTurnoverRewardSettlement(ctx, settlementID) + if err != nil { + return domain.Settlement{}, err + } + if !exists { + return domain.Settlement{}, xerr.New(xerr.NotFound, "room turnover reward settlement not found") + } + if settlement.Status == domain.SettlementStatusGranted { + // 已发奖记录直接返回,后台重复点击 retry 不会再次调用钱包。 + return settlement, nil + } + if settlement.TierID <= 0 { + // tier_not_matched 不是外部依赖失败,而是该房间当周没有达到任何档位;retry 不能把这类 0 档位记录重置成 granted。 + return settlement, xerr.New(xerr.InvalidArgument, "room turnover reward settlement is not grantable") + } + ownerID := settlement.OwnerUserID + if ownerID <= 0 { + // 失败记录可能是当时没读到房主;retry 时重新取 room-service 快照,允许房间修复后继续发奖。 + ownerID, err = s.fetchRoomOwner(ctx, settlement.RoomID) + if err != nil || ownerID <= 0 { + _ = s.repository.MarkRoomTurnoverRewardSettlementFailed(ctx, settlement.SettlementID, "room_owner_not_found", s.now().UTC().UnixMilli()) + return domain.Settlement{}, xerr.New(xerr.NotFound, "room owner not found") + } + } + settlement, err = s.repository.ResetRoomTurnoverRewardSettlementForRetry(ctx, settlement.SettlementID, ownerID, s.now().UTC().UnixMilli()) + if err != nil { + return domain.Settlement{}, err + } + return s.grantSettlement(ctx, settlement) +} + +func (s *Service) settlementFromProgress(ctx context.Context, progress domain.Progress, periodEndMS int64, tiers []domain.Tier, nowMS int64) domain.Settlement { + tier, matched := MatchHighestTier(tiers, progress.CoinSpent) + settlement := domain.Settlement{ + AppCode: appcode.FromContext(ctx), + RoomID: progress.RoomID, + PeriodStartMS: progress.PeriodStartMS, + PeriodEndMS: periodEndMS, + CoinSpent: progress.CoinSpent, + Status: domain.SettlementStatusPending, + CreatedAtMS: nowMS, + UpdatedAtMS: nowMS, + } + if matched { + // 结算记录保存档位快照;后续配置变更不反推历史奖励金额。 + settlement.TierID = tier.TierID + settlement.TierCode = tier.TierCode + settlement.ThresholdCoinSpent = tier.ThresholdCoinSpent + settlement.RewardCoinAmount = tier.RewardCoinAmount + } + return settlement +} + +func (s *Service) grantSettlement(ctx context.Context, settlement domain.Settlement) (domain.Settlement, error) { + if settlement.Status == domain.SettlementStatusGranted { + // 发奖入口保持幂等,避免 cron 和人工 retry 同时进来时重复入账。 + return settlement, nil + } + if settlement.OwnerUserID <= 0 || settlement.RewardCoinAmount < 0 || settlement.WalletCommandID == "" { + err := xerr.New(xerr.InvalidArgument, "room turnover reward settlement is not grantable") + _ = s.repository.MarkRoomTurnoverRewardSettlementFailed(ctx, settlement.SettlementID, xerr.MessageOf(err), s.now().UTC().UnixMilli()) + return domain.Settlement{}, err + } + if settlement.RewardCoinAmount == 0 { + // 0 金币档位是合法配置,用于运营只记录达标但不发币的周期;钱包不接受 0 金额命令,所以这里直接收敛结算状态。 + nowMS := s.now().UTC().UnixMilli() + return s.repository.MarkRoomTurnoverRewardSettlementGranted(ctx, settlement.SettlementID, "", nowMS) + } + if s.wallet == nil { + err := xerr.New(xerr.Unavailable, "wallet client is not configured") + _ = s.repository.MarkRoomTurnoverRewardSettlementFailed(ctx, settlement.SettlementID, xerr.MessageOf(err), s.now().UTC().UnixMilli()) + return domain.Settlement{}, err + } + // 钱包 command_id 使用 app + 周期 + room_id,保证同一房间同一周期无论 cron 重跑还是 retry,都只产生一笔账务交易。 + resp, err := s.wallet.CreditRoomTurnoverReward(ctx, &walletv1.CreditRoomTurnoverRewardRequest{ + CommandId: settlement.WalletCommandID, + AppCode: appcode.FromContext(ctx), + TargetUserId: settlement.OwnerUserID, + Amount: settlement.RewardCoinAmount, + SettlementId: settlement.SettlementID, + RoomId: settlement.RoomID, + PeriodStartMs: settlement.PeriodStartMS, + PeriodEndMs: settlement.PeriodEndMS, + CoinSpent: settlement.CoinSpent, + TierId: settlement.TierID, + TierCode: settlement.TierCode, + Reason: rewardReason, + }) + if err != nil { + _ = s.repository.MarkRoomTurnoverRewardSettlementFailed(ctx, settlement.SettlementID, xerr.MessageOf(err), s.now().UTC().UnixMilli()) + return domain.Settlement{}, err + } + return s.repository.MarkRoomTurnoverRewardSettlementGranted(ctx, settlement.SettlementID, resp.GetTransactionId(), resp.GetGrantedAtMs()) +} + +func (s *Service) fetchRoomOwner(ctx context.Context, roomID string) (int64, error) { + if s.room == nil { + return 0, xerr.New(xerr.Unavailable, "room query client is not configured") + } + roomID = strings.TrimSpace(roomID) + if roomID == "" { + return 0, xerr.New(xerr.InvalidArgument, "room_id is required") + } + resp, err := s.room.AdminGetRoom(ctx, &roomv1.AdminGetRoomRequest{ + Meta: &roomv1.RequestMeta{ + // 这里不是用户请求链路,使用可读的内部 request_id 方便按房间追踪结算时的 owner 查询。 + RequestId: "room-turnover-reward-owner:" + roomID, + AppCode: appcode.FromContext(ctx), + SentAtMs: s.now().UTC().UnixMilli(), + }, + RoomId: roomID, + }) + if err != nil { + return 0, err + } + return resp.GetRoom().GetOwnerUserId(), nil +} + +func (s *Service) requireRepository() error { + if s == nil || s.repository == nil { + return xerr.New(xerr.Unavailable, "room turnover 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;默认 active 保持配置体验简单,但 validate 仍会拦截非法状态。 + status = domain.TierStatusActive + } + items = append(items, domain.Tier{ + TierID: tier.TierID, + TierCode: strings.TrimSpace(tier.TierCode), + TierName: strings.TrimSpace(tier.TierName), + ThresholdCoinSpent: tier.ThresholdCoinSpent, + RewardCoinAmount: tier.RewardCoinAmount, + Status: status, + SortOrder: tier.SortOrder, + }) + } + return sortTiersForDisplay(items) +} + +func sortTiersForDisplay(tiers []domain.Tier) []domain.Tier { + items := append([]domain.Tier(nil), tiers...) + sort.SliceStable(items, func(i, j int) bool { + if items[i].SortOrder == items[j].SortOrder { + return items[i].ThresholdCoinSpent < items[j].ThresholdCoinSpent + } + 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") + } + // tier_code 是后台配置稳定标识,阈值和奖励可以修改,但同一 App 内不能出现两个相同编码。 + seen := make(map[string]struct{}, len(config.Tiers)) + activeCount := 0 + 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.ThresholdCoinSpent <= 0 { + return xerr.New(xerr.InvalidArgument, "threshold_coin_spent must be greater than zero") + } + if tier.RewardCoinAmount < 0 { + return xerr.New(xerr.InvalidArgument, "reward_coin_amount must not be negative") + } + switch tier.Status { + case domain.TierStatusActive: + activeCount++ + case domain.TierStatusInactive: + default: + return xerr.New(xerr.InvalidArgument, "tier status is invalid") + } + } + if config.Enabled && activeCount == 0 { + // 开启活动但没有有效档位会让 H5 显示可参与却永远无法发奖,直接在配置入口拒绝。 + return xerr.New(xerr.InvalidArgument, "enabled config requires at least one active tier") + } + return nil +} + +func activeTiers(tiers []domain.Tier) []domain.Tier { + out := make([]domain.Tier, 0, len(tiers)) + for _, tier := range tiers { + if tier.Status == domain.TierStatusActive { + out = append(out, tier) + } + } + return out +} + +// MatchHighestTier 返回达到流水阈值的最高有效档。 +func MatchHighestTier(tiers []domain.Tier, coinSpent int64) (domain.Tier, bool) { + var matched domain.Tier + found := false + for _, tier := range tiers { + if tier.Status != domain.TierStatusActive || tier.ThresholdCoinSpent <= 0 || tier.RewardCoinAmount < 0 { + continue + } + if coinSpent >= tier.ThresholdCoinSpent && (!found || tier.ThresholdCoinSpent > matched.ThresholdCoinSpent) { + matched = tier + found = true + } + } + return matched, found +} + +// WeekWindow 返回给定时间所在 UTC 周一 00:00 到下一周一 00:00 的左闭右开窗口。 +func WeekWindow(now time.Time) (time.Time, time.Time) { + utc := now.UTC() + dayStart := time.Date(utc.Year(), utc.Month(), utc.Day(), 0, 0, 0, 0, time.UTC) + weekday := int(dayStart.Weekday()) + if weekday == 0 { + weekday = 7 + } + start := dayStart.AddDate(0, 0, 1-weekday) + return start, start.AddDate(0, 0, 7) +} + +// PreviousWeekWindow 返回当前时间之前的完整 UTC 周期。 +func PreviousWeekWindow(now time.Time) (time.Time, time.Time) { + start, _ := WeekWindow(now) + previousStart := start.AddDate(0, 0, -7) + return previousStart, start +} diff --git a/services/activity-service/internal/service/roomturnoverreward/service_test.go b/services/activity-service/internal/service/roomturnoverreward/service_test.go new file mode 100644 index 00000000..2858fe66 --- /dev/null +++ b/services/activity-service/internal/service/roomturnoverreward/service_test.go @@ -0,0 +1,219 @@ +package roomturnoverreward + +import ( + "context" + "testing" + "time" + + "google.golang.org/grpc" + roomv1 "hyapp.local/api/proto/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + domain "hyapp/services/activity-service/internal/domain/roomturnoverreward" +) + +func TestWeekWindowUsesUTCMondayBoundary(t *testing.T) { + cases := []struct { + name string + now string + wantStart string + wantEnd string + }{ + { + name: "monday zero belongs to new week", + now: "2026-06-01T00:00:00Z", + wantStart: "2026-06-01T00:00:00Z", + wantEnd: "2026-06-08T00:00:00Z", + }, + { + name: "sunday belongs to current week", + now: "2026-06-07T23:59:59Z", + wantStart: "2026-06-01T00:00:00Z", + wantEnd: "2026-06-08T00:00:00Z", + }, + { + name: "cross month keeps utc week", + now: "2026-07-01T12:30:00Z", + wantStart: "2026-06-29T00:00:00Z", + wantEnd: "2026-07-06T00:00:00Z", + }, + { + name: "cross year keeps utc week", + now: "2027-01-01T08:00:00Z", + wantStart: "2026-12-28T00:00:00Z", + wantEnd: "2027-01-04T00:00:00Z", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + now := mustParseTime(t, tc.now) + start, end := WeekWindow(now) + if got := start.Format(time.RFC3339); got != tc.wantStart { + t.Fatalf("unexpected start: got %s want %s", got, tc.wantStart) + } + if got := end.Format(time.RFC3339); got != tc.wantEnd { + t.Fatalf("unexpected end: got %s want %s", got, tc.wantEnd) + } + }) + } +} + +func TestPreviousWeekWindowReturnsCompletedUTCWeek(t *testing.T) { + start, end := PreviousWeekWindow(mustParseTime(t, "2026-06-08T00:00:00Z")) + if got := start.Format(time.RFC3339); got != "2026-06-01T00:00:00Z" { + t.Fatalf("unexpected previous start: %s", got) + } + if got := end.Format(time.RFC3339); got != "2026-06-08T00:00:00Z" { + t.Fatalf("unexpected previous end: %s", got) + } +} + +func TestMatchHighestTierReturnsHighestThreshold(t *testing.T) { + tiers := []domain.Tier{ + {TierID: 1, TierCode: "bronze", ThresholdCoinSpent: 100, RewardCoinAmount: 10, Status: domain.TierStatusActive}, + {TierID: 2, TierCode: "silver", ThresholdCoinSpent: 500, RewardCoinAmount: 60, Status: domain.TierStatusActive}, + {TierID: 3, TierCode: "gold", ThresholdCoinSpent: 1000, RewardCoinAmount: 160, Status: domain.TierStatusActive}, + {TierID: 4, TierCode: "hidden", ThresholdCoinSpent: 700, RewardCoinAmount: 90, Status: domain.TierStatusInactive}, + } + + tier, ok := MatchHighestTier(tiers, 850) + if !ok { + t.Fatal("expected a matched tier") + } + if tier.TierCode != "silver" { + t.Fatalf("unexpected tier: got %s want silver", tier.TierCode) + } +} + +func TestRetrySettlementRejectsTierNotMatchedWithoutGrantSideEffects(t *testing.T) { + repo := &retryBoundaryRepository{ + settlement: domain.Settlement{ + SettlementID: "settlement-tier-not-matched", + RoomID: "room-1", + Status: domain.SettlementStatusFailed, + FailureReason: "tier_not_matched", + WalletCommandID: "room_turnover_reward:lalu:1:room-1", + RewardCoinAmount: 0, + }, + } + room := &retryBoundaryRoom{ownerID: 10001} + wallet := &retryBoundaryWallet{} + svc := New(repo, wallet, room) + + got, err := svc.RetrySettlement(context.Background(), repo.settlement.SettlementID) + if err == nil { + t.Fatal("expected retry to reject tier_not_matched settlement") + } + if got.Status != domain.SettlementStatusFailed || got.FailureReason != "tier_not_matched" { + t.Fatalf("retry should return original failed settlement, got %+v", got) + } + if repo.resetCalls != 0 || repo.grantCalls != 0 || repo.failCalls != 0 { + t.Fatalf("tier_not_matched retry must not mutate settlement: reset=%d grant=%d fail=%d", repo.resetCalls, repo.grantCalls, repo.failCalls) + } + if room.calls != 0 { + t.Fatalf("tier_not_matched retry must not fetch room owner, calls=%d", room.calls) + } + if wallet.calls != 0 { + t.Fatalf("tier_not_matched retry must not call wallet, calls=%d", wallet.calls) + } +} + +func mustParseTime(t *testing.T, value string) time.Time { + t.Helper() + parsed, err := time.Parse(time.RFC3339, value) + if err != nil { + t.Fatalf("parse time %q: %v", value, err) + } + return parsed +} + +type retryBoundaryRepository struct { + settlement domain.Settlement + resetCalls int + grantCalls int + failCalls int +} + +func (r *retryBoundaryRepository) GetRoomTurnoverRewardConfig(context.Context) (domain.Config, bool, error) { + panic("unexpected GetRoomTurnoverRewardConfig") +} + +func (r *retryBoundaryRepository) UpdateRoomTurnoverRewardConfig(context.Context, domain.Config, int64) (domain.Config, error) { + panic("unexpected UpdateRoomTurnoverRewardConfig") +} + +func (r *retryBoundaryRepository) ConsumeRoomTurnoverGiftEvent(context.Context, domain.RoomGiftEvent, int64, int64, int64) (domain.EventResult, error) { + panic("unexpected ConsumeRoomTurnoverGiftEvent") +} + +func (r *retryBoundaryRepository) GetRoomTurnoverRewardProgress(context.Context, string, int64) (domain.Progress, bool, error) { + panic("unexpected GetRoomTurnoverRewardProgress") +} + +func (r *retryBoundaryRepository) GetLatestRoomTurnoverRewardSettlement(context.Context, string) (domain.Settlement, bool, error) { + panic("unexpected GetLatestRoomTurnoverRewardSettlement") +} + +func (r *retryBoundaryRepository) ListRoomTurnoverRewardSettlements(context.Context, domain.SettlementQuery) ([]domain.Settlement, int64, error) { + panic("unexpected ListRoomTurnoverRewardSettlements") +} + +func (r *retryBoundaryRepository) ListUnsettledRoomTurnoverRewardProgress(context.Context, int64, int) ([]domain.Progress, error) { + panic("unexpected ListUnsettledRoomTurnoverRewardProgress") +} + +func (r *retryBoundaryRepository) InsertRoomTurnoverRewardSettlement(context.Context, domain.Settlement, int64) (domain.Settlement, bool, error) { + panic("unexpected InsertRoomTurnoverRewardSettlement") +} + +func (r *retryBoundaryRepository) ListPendingRoomTurnoverRewardSettlements(context.Context, int) ([]domain.Settlement, error) { + panic("unexpected ListPendingRoomTurnoverRewardSettlements") +} + +func (r *retryBoundaryRepository) GetRoomTurnoverRewardSettlement(_ context.Context, settlementID string) (domain.Settlement, bool, error) { + if settlementID != r.settlement.SettlementID { + return domain.Settlement{}, false, nil + } + return r.settlement, true, nil +} + +func (r *retryBoundaryRepository) ResetRoomTurnoverRewardSettlementForRetry(_ context.Context, _ string, ownerUserID int64, _ int64) (domain.Settlement, error) { + r.resetCalls++ + r.settlement.Status = domain.SettlementStatusPending + r.settlement.OwnerUserID = ownerUserID + r.settlement.FailureReason = "" + return r.settlement, nil +} + +func (r *retryBoundaryRepository) MarkRoomTurnoverRewardSettlementGranted(_ context.Context, _ string, walletTransactionID string, _ int64) (domain.Settlement, error) { + r.grantCalls++ + r.settlement.Status = domain.SettlementStatusGranted + r.settlement.WalletTransactionID = walletTransactionID + return r.settlement, nil +} + +func (r *retryBoundaryRepository) MarkRoomTurnoverRewardSettlementFailed(_ context.Context, _ string, reason string, _ int64) error { + r.failCalls++ + r.settlement.Status = domain.SettlementStatusFailed + r.settlement.FailureReason = reason + return nil +} + +type retryBoundaryRoom struct { + ownerID int64 + calls int +} + +func (r *retryBoundaryRoom) AdminGetRoom(context.Context, *roomv1.AdminGetRoomRequest, ...grpc.CallOption) (*roomv1.AdminGetRoomResponse, error) { + r.calls++ + return &roomv1.AdminGetRoomResponse{Room: &roomv1.AdminRoomListItem{OwnerUserId: r.ownerID}}, nil +} + +type retryBoundaryWallet struct { + calls int +} + +func (w *retryBoundaryWallet) CreditRoomTurnoverReward(context.Context, *walletv1.CreditRoomTurnoverRewardRequest, ...grpc.CallOption) (*walletv1.CreditRoomTurnoverRewardResponse, error) { + w.calls++ + return &walletv1.CreditRoomTurnoverRewardResponse{TransactionId: "wallet-tx-1", GrantedAtMs: 1234}, nil +} diff --git a/services/activity-service/internal/service/weeklystar/service.go b/services/activity-service/internal/service/weeklystar/service.go new file mode 100644 index 00000000..4904ac66 --- /dev/null +++ b/services/activity-service/internal/service/weeklystar/service.go @@ -0,0 +1,359 @@ +package weeklystar + +import ( + "context" + "log/slog" + "sort" + "strings" + "time" + + "google.golang.org/grpc" + "google.golang.org/protobuf/proto" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/logx" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/weeklystar" +) + +const weeklyStarRewardReason = "weekly star reward" + +// Repository is the storage boundary for weekly-star configuration, score and settlement facts. +type Repository interface { + ListWeeklyStarCycles(ctx context.Context, query domain.ListQuery) ([]domain.Cycle, int64, error) + GetWeeklyStarCycle(ctx context.Context, cycleID string) (domain.Cycle, error) + UpsertWeeklyStarCycle(ctx context.Context, command domain.CycleCommand, nowMS int64) (domain.Cycle, bool, error) + SetWeeklyStarCycleStatus(ctx context.Context, cycleID string, status string, operatorAdminID int64, nowMS int64) (domain.Cycle, error) + FindCurrentWeeklyStarCycle(ctx context.Context, regionID int64, nowMS int64) (domain.Cycle, bool, error) + ConsumeWeeklyStarGiftEvent(ctx context.Context, event domain.GiftEvent, nowMS int64) (domain.EventResult, error) + ListWeeklyStarLeaderboard(ctx context.Context, cycleID string, regionID int64, pageSize int32, pageToken string, nowMS int64) (domain.Cycle, []domain.LeaderboardEntry, string, int64, error) + GetWeeklyStarUserEntry(ctx context.Context, cycleID string, userID int64) (domain.LeaderboardEntry, bool, error) + ListWeeklyStarHistory(ctx context.Context, regionID int64, limit int32, nowMS int64) ([]domain.HistoryCycle, error) + ListWeeklyStarSettlements(ctx context.Context, cycleID string) ([]domain.Settlement, error) + ClaimDueWeeklyStarCycles(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int32) ([]domain.Cycle, error) + PrepareWeeklyStarSettlements(ctx context.Context, cycleID string, nowMS int64) ([]domain.Settlement, error) + MarkWeeklyStarSettlementGranted(ctx context.Context, settlementID string, walletGrantID string, nowMS int64) error + MarkWeeklyStarSettlementFailed(ctx context.Context, settlementID string, reason string, nowMS int64) error + FinishWeeklyStarCycleIfComplete(ctx context.Context, cycleID string, nowMS int64) (bool, error) +} + +// WalletClient is the small wallet-service surface needed by weekly-star settlement. +type WalletClient interface { + GrantResourceGroup(ctx context.Context, req *walletv1.GrantResourceGroupRequest, opts ...grpc.CallOption) (*walletv1.ResourceGrantResponse, error) +} + +// Service owns weekly-star business rules; transports and cron only adapt inputs into this API. +type Service struct { + repository Repository + wallet WalletClient + now func() time.Time +} + +// New creates the weekly-star service with activity-service storage as the source of truth. +func New(repository Repository, wallet WalletClient) *Service { + return &Service{ + repository: repository, + wallet: wallet, + now: time.Now, + } +} + +// ListCycles returns configured cycles for admin pages without leaking storage paging rules to transport. +func (s *Service) ListCycles(ctx context.Context, query domain.ListQuery) ([]domain.Cycle, int64, error) { + if err := s.requireRepository(); err != nil { + return nil, 0, err + } + query.Status = normalizeStatus(query.Status) + return s.repository.ListWeeklyStarCycles(ctx, query) +} + +// GetCycle returns a single admin cycle, including the three gifts and Top rewards. +func (s *Service) GetCycle(ctx context.Context, cycleID string) (domain.Cycle, error) { + if err := s.requireRepository(); err != nil { + return domain.Cycle{}, err + } + cycleID = strings.TrimSpace(cycleID) + if cycleID == "" { + return domain.Cycle{}, xerr.New(xerr.InvalidArgument, "cycle_id is required") + } + return s.repository.GetWeeklyStarCycle(ctx, cycleID) +} + +// CreateCycle validates the full weekly-star contract and stores a new UTC cycle. +func (s *Service) CreateCycle(ctx context.Context, command domain.CycleCommand) (domain.Cycle, bool, error) { + command.RequireNewRecord = true + return s.upsertCycle(ctx, command) +} + +// UpdateCycle replaces an existing weekly-star cycle after the same create-time validations pass. +func (s *Service) UpdateCycle(ctx context.Context, command domain.CycleCommand) (domain.Cycle, bool, error) { + command.RequireNewRecord = false + return s.upsertCycle(ctx, command) +} + +// SetCycleStatus switches admin-visible status; active cycles are the only ones matched by gift events. +func (s *Service) SetCycleStatus(ctx context.Context, cycleID string, status string, operatorAdminID int64) (domain.Cycle, error) { + if err := s.requireRepository(); err != nil { + return domain.Cycle{}, err + } + status = normalizeStatus(status) + if !validStatus(status) || status == domain.StatusSettling { + return domain.Cycle{}, xerr.New(xerr.InvalidArgument, "status is invalid") + } + if operatorAdminID <= 0 { + return domain.Cycle{}, xerr.New(xerr.InvalidArgument, "operator_admin_id is required") + } + return s.repository.SetWeeklyStarCycleStatus(ctx, strings.TrimSpace(cycleID), status, operatorAdminID, s.now().UnixMilli()) +} + +// GetCurrent resolves the current cycle by region, using the storage-level concrete-region-first/default fallback. +func (s *Service) GetCurrent(ctx context.Context, userID int64, regionID int64) (domain.Cycle, []domain.LeaderboardEntry, domain.LeaderboardEntry, bool, error) { + if err := s.requireRepository(); err != nil { + return domain.Cycle{}, nil, domain.LeaderboardEntry{}, false, err + } + cycle, ok, err := s.repository.FindCurrentWeeklyStarCycle(ctx, regionID, s.now().UnixMilli()) + if err != nil || !ok { + return cycle, nil, domain.LeaderboardEntry{}, false, err + } + _, top, _, _, err := s.repository.ListWeeklyStarLeaderboard(ctx, cycle.CycleID, regionID, 50, "", s.now().UnixMilli()) + if err != nil { + return domain.Cycle{}, nil, domain.LeaderboardEntry{}, false, err + } + myEntry, found, err := s.repository.GetWeeklyStarUserEntry(ctx, cycle.CycleID, userID) + return cycle, top, myEntry, found, err +} + +// ListLeaderboard returns deterministic score order for either a concrete cycle or current region cycle. +func (s *Service) ListLeaderboard(ctx context.Context, cycleID string, regionID int64, pageSize int32, pageToken string) (domain.Cycle, []domain.LeaderboardEntry, string, int64, error) { + if err := s.requireRepository(); err != nil { + return domain.Cycle{}, nil, "", 0, err + } + return s.repository.ListWeeklyStarLeaderboard(ctx, strings.TrimSpace(cycleID), regionID, pageSize, strings.TrimSpace(pageToken), s.now().UnixMilli()) +} + +// ListHistory returns settled cycles for the user region with default-cycle fallback handled by storage. +func (s *Service) ListHistory(ctx context.Context, regionID int64, limit int32) ([]domain.HistoryCycle, error) { + if err := s.requireRepository(); err != nil { + return nil, err + } + return s.repository.ListWeeklyStarHistory(ctx, regionID, limit, s.now().UnixMilli()) +} + +// ListSettlements returns admin-visible settlement grant facts for one cycle. +func (s *Service) ListSettlements(ctx context.Context, cycleID string) ([]domain.Settlement, error) { + if err := s.requireRepository(); err != nil { + return nil, err + } + cycleID = strings.TrimSpace(cycleID) + if cycleID == "" { + return nil, xerr.New(xerr.InvalidArgument, "cycle_id is required") + } + return s.repository.ListWeeklyStarSettlements(ctx, cycleID) +} + +// HandleRoomEvent consumes room-service committed gift facts; score always equals the actual coin_spent. +// 这里不读取 gift 配置价格,也不相信客户端传入积分,因为钱包扣费后的 room outbox 才是送礼成功事实。 +// 非 RoomGiftSent、无用户、无礼物或无扣费金额的 envelope 直接跳过,避免让普通房间事件污染活动积分表。 +func (s *Service) HandleRoomEvent(ctx context.Context, envelope *roomeventsv1.EventEnvelope) (int32, error) { + if s == nil || s.repository == nil || envelope == nil || envelope.GetEventType() != "RoomGiftSent" { + return 0, nil + } + var gift roomeventsv1.RoomGiftSent + if err := proto.Unmarshal(envelope.GetBody(), &gift); err != nil { + return 0, err + } + if gift.GetSenderUserId() <= 0 || gift.GetGiftId() == "" || gift.GetCoinSpent() <= 0 { + return 0, nil + } + // region_id 和 occurred_at_ms 都来自 room-service 的稳定事实;repository 会按事件发生时间匹配 [start_ms,end_ms) 周期。 + // source_event_id 是幂等键,同一个 room outbox 重试时只会插入一次 score event,并且不会重复累加榜单分数。 + event := domain.GiftEvent{ + EventID: strings.TrimSpace(envelope.GetEventId()), + UserID: gift.GetSenderUserId(), + GiftID: strings.TrimSpace(gift.GetGiftId()), + ScoreDelta: gift.GetCoinSpent(), + RegionID: gift.GetVisibleRegionId(), + OccurredAtMS: envelope.GetOccurredAtMs(), + } + result, err := s.repository.ConsumeWeeklyStarGiftEvent(appcode.WithContext(ctx, envelope.GetAppCode()), event, s.now().UnixMilli()) + if err != nil { + return 0, err + } + if result.Status == domain.EventStatusConsumed { + return 1, nil + } + return 0, nil +} + +// ProcessSettlementBatch locks due cycles, materializes Top1/Top2/Top3, and grants each resource group idempotently. +// 状态机是 active -> settling -> settled:先锁到期周期,再把榜单快照固化为 settlement,最后逐条调用 wallet 发资源组。 +// wallet_command_id 使用 cycle/rank/user 组成,cron 重试同一 settlement 时只会命中 wallet 幂等,不会重复发奖励。 +func (s *Service) ProcessSettlementBatch(ctx context.Context, runID string, workerID string, batchSize int32, lockTTL time.Duration) (claimed int32, processed int32, success int32, failure int32, hasMore bool, err error) { + if err := s.requireRepository(); err != nil { + return 0, 0, 0, 0, false, err + } + if s.wallet == nil { + return 0, 0, 0, 0, false, xerr.New(xerr.Unavailable, "wallet client is not configured") + } + if batchSize <= 0 { + batchSize = 50 + } + if lockTTL <= 0 { + lockTTL = 30 * time.Second + } + if strings.TrimSpace(workerID) == "" { + workerID = "activity-weekly-star" + } + cycles, err := s.repository.ClaimDueWeeklyStarCycles(ctx, workerID, s.now().UnixMilli(), lockTTL, batchSize) + if err != nil { + return 0, 0, 0, 0, false, err + } + for _, cycle := range cycles { + settlements, prepareErr := s.repository.PrepareWeeklyStarSettlements(ctx, cycle.CycleID, s.now().UnixMilli()) + if prepareErr != nil { + logx.Error(ctx, "weekly_star_prepare_settlements_failed", prepareErr, slog.String("cycle_id", cycle.CycleID), slog.String("run_id", runID), slog.String("worker_id", workerID)) + failure++ + continue + } + if len(settlements) == 0 { + // 没有人得分的周期不会生成 settlement;只要没有 pending 记录,就可以安全标记为 settled。 + if _, finishErr := s.repository.FinishWeeklyStarCycleIfComplete(ctx, cycle.CycleID, s.now().UnixMilli()); finishErr != nil { + failure++ + continue + } + success++ + processed++ + continue + } + for _, settlement := range settlements { + processed++ + // activity-service 只决定获奖人和资源组,真实发放由 wallet-service 原子展开资源组并写 grant/账务流水。 + // 如果 wallet 临时失败,settlement 会退回 failed 状态,下一轮 cron 继续用同一个 wallet_command_id 重试。 + resp, grantErr := s.wallet.GrantResourceGroup(ctx, &walletv1.GrantResourceGroupRequest{ + CommandId: settlement.WalletCommandID, + AppCode: appcode.FromContext(ctx), + TargetUserId: settlement.UserID, + GroupId: settlement.ResourceGroupID, + Reason: weeklyStarRewardReason, + OperatorUserId: settlement.UserID, + GrantSource: domain.GrantSourceWeeklyStar, + }) + if grantErr != nil { + logx.Error(ctx, "weekly_star_grant_resource_group_failed", grantErr, slog.String("cycle_id", cycle.CycleID), slog.String("settlement_id", settlement.SettlementID), slog.String("wallet_command_id", settlement.WalletCommandID)) + failure++ + _ = s.repository.MarkWeeklyStarSettlementFailed(ctx, settlement.SettlementID, xerr.MessageOf(grantErr), s.now().UnixMilli()) + continue + } + walletGrantID := "" + if resp.GetGrant() != nil { + walletGrantID = resp.GetGrant().GetGrantId() + } + if markErr := s.repository.MarkWeeklyStarSettlementGranted(ctx, settlement.SettlementID, walletGrantID, s.now().UnixMilli()); markErr != nil { + logx.Error(ctx, "weekly_star_mark_settlement_granted_failed", markErr, slog.String("cycle_id", cycle.CycleID), slog.String("settlement_id", settlement.SettlementID), slog.String("wallet_grant_id", walletGrantID)) + failure++ + continue + } + success++ + } + if _, finishErr := s.repository.FinishWeeklyStarCycleIfComplete(ctx, cycle.CycleID, s.now().UnixMilli()); finishErr != nil { + // Finish 会再次检查所有 settlement 是否 granted,防止部分奖励失败时把周期提前关掉。 + failure++ + } + } + return int32(len(cycles)), processed, success, failure, len(cycles) == int(batchSize), nil +} + +func (s *Service) upsertCycle(ctx context.Context, command domain.CycleCommand) (domain.Cycle, bool, error) { + if err := s.requireRepository(); err != nil { + return domain.Cycle{}, false, err + } + command.Cycle = normalizeCycle(command.Cycle) + command.OperatorAdminID = command.OperatorAdminID + if command.OperatorAdminID <= 0 { + return domain.Cycle{}, false, xerr.New(xerr.InvalidArgument, "operator_admin_id is required") + } + if err := validateCycle(command.Cycle); err != nil { + return domain.Cycle{}, false, err + } + return s.repository.UpsertWeeklyStarCycle(ctx, command, s.now().UnixMilli()) +} + +func (s *Service) requireRepository() error { + if s == nil || s.repository == nil { + return xerr.New(xerr.Unavailable, "weekly star repository is not configured") + } + return nil +} + +func normalizeCycle(cycle domain.Cycle) domain.Cycle { + cycle.ActivityCode = domain.ActivityCode + cycle.CycleID = strings.TrimSpace(cycle.CycleID) + cycle.Title = strings.TrimSpace(cycle.Title) + cycle.Status = normalizeStatus(cycle.Status) + if cycle.Status == "" { + cycle.Status = domain.StatusDraft + } + seenGifts := map[string]bool{} + gifts := make([]domain.Gift, 0, len(cycle.Gifts)) + for _, gift := range cycle.Gifts { + gift.GiftID = strings.TrimSpace(gift.GiftID) + if gift.GiftID == "" || seenGifts[gift.GiftID] { + continue + } + seenGifts[gift.GiftID] = true + gifts = append(gifts, gift) + } + sort.SliceStable(gifts, func(i, j int) bool { return gifts[i].SortOrder < gifts[j].SortOrder }) + for index := range gifts { + if gifts[index].SortOrder <= 0 { + gifts[index].SortOrder = int32(index + 1) + } + } + cycle.Gifts = gifts + sort.SliceStable(cycle.Rewards, func(i, j int) bool { return cycle.Rewards[i].RankNo < cycle.Rewards[j].RankNo }) + return cycle +} + +func validateCycle(cycle domain.Cycle) error { + if cycle.Title == "" { + return xerr.New(xerr.InvalidArgument, "title is required") + } + if cycle.RegionID < 0 { + return xerr.New(xerr.InvalidArgument, "region_id is invalid") + } + if cycle.StartMS <= 0 || cycle.EndMS <= cycle.StartMS { + return xerr.New(xerr.InvalidArgument, "start_ms and end_ms are invalid") + } + if !validStatus(cycle.Status) || cycle.Status == domain.StatusSettling || cycle.Status == domain.StatusSettled { + return xerr.New(xerr.InvalidArgument, "status is invalid") + } + if len(cycle.Gifts) != 3 { + return xerr.New(xerr.InvalidArgument, "weekly star requires exactly 3 gifts") + } + rankToGroup := map[int32]int64{} + for _, reward := range cycle.Rewards { + if reward.RankNo >= 1 && reward.RankNo <= 3 && reward.ResourceGroupID > 0 { + rankToGroup[reward.RankNo] = reward.ResourceGroupID + } + } + for rank := int32(1); rank <= 3; rank++ { + if rankToGroup[rank] <= 0 { + return xerr.New(xerr.InvalidArgument, "top1/top2/top3 resource groups are required") + } + } + return nil +} + +func normalizeStatus(value string) string { + return strings.ToLower(strings.TrimSpace(value)) +} + +func validStatus(value string) bool { + switch value { + case domain.StatusDraft, domain.StatusActive, domain.StatusDisabled, domain.StatusSettling, domain.StatusSettled: + return true + default: + return false + } +} diff --git a/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_migration.go b/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_migration.go new file mode 100644 index 00000000..80b507b3 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_migration.go @@ -0,0 +1,96 @@ +package mysql + +import "context" + +func (r *Repository) ensureCumulativeRechargeRewardTables(ctx context.Context) error { + statements := []string{ + `CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_configs ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否启用累充奖励', + updated_by_admin_id 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) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励配置'`, + `CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_tiers ( + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '档位自增 ID', + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + tier_code VARCHAR(64) NOT NULL COMMENT '档位编码', + tier_name VARCHAR(128) NOT NULL COMMENT '档位展示名称', + threshold_usd_minor BIGINT NOT NULL COMMENT '达标美元金额,美分', + resource_group_id BIGINT NOT NULL COMMENT '达标后发放资源组 ID', + status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', + 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', + PRIMARY KEY (tier_id), + UNIQUE KEY uk_cumulative_recharge_reward_tier_code (app_code, tier_code), + KEY idx_cumulative_recharge_reward_tier_sort (app_code, status, sort_order, threshold_usd_minor) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励档位'`, + `CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_events ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + event_id VARCHAR(128) NOT NULL COMMENT 'wallet_outbox event_id', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周,如 2026-W23', + user_id BIGINT NOT NULL COMMENT '充值用户', + transaction_id VARCHAR(128) NOT NULL COMMENT '钱包交易 ID', + command_id VARCHAR(128) NOT NULL COMMENT '钱包命令 ID', + recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '充值来源', + recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '本次到账金币', + qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '本次计入累充的美元美分', + payload_json JSON NULL COMMENT '原 wallet payload', + occurred_at_ms BIGINT NOT NULL COMMENT '充值发生时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, event_id), + KEY idx_cumulative_recharge_reward_event_user_cycle (app_code, cycle_key, user_id, occurred_at_ms), + KEY idx_cumulative_recharge_reward_event_transaction (app_code, transaction_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励充值事件幂等表'`, + `CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_progress ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周,如 2026-W23', + user_id BIGINT NOT NULL COMMENT '用户 ID', + total_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计美元美分', + total_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计到账金币', + first_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期首笔充值时间', + last_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '周期最近充值时间', + updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', + PRIMARY KEY (app_code, cycle_key, user_id), + KEY idx_cumulative_recharge_reward_progress_total (app_code, cycle_key, total_usd_minor) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励用户周期累计'`, + `CREATE TABLE IF NOT EXISTS cumulative_recharge_reward_grants ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + grant_id VARCHAR(128) NOT NULL COMMENT '累充奖励发放 ID', + cycle_key VARCHAR(16) NOT NULL COMMENT 'UTC 自然周,如 2026-W23', + user_id BIGINT NOT NULL COMMENT '用户 ID', + event_id VARCHAR(128) NOT NULL COMMENT '触发发放的 wallet event_id', + transaction_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包交易 ID', + command_id VARCHAR(128) NOT NULL COMMENT '触发发放的钱包命令 ID', + tier_id BIGINT NOT NULL COMMENT '命中档位 ID', + tier_code VARCHAR(64) NOT NULL COMMENT '命中档位编码', + threshold_usd_minor BIGINT NOT NULL COMMENT '命中档位门槛,美分', + resource_group_id BIGINT NOT NULL COMMENT '发放资源组 ID', + reached_usd_minor BIGINT NOT NULL COMMENT '命中时周期累计金额,美分', + qualifying_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '触发事件计入金额,美分', + recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '触发事件到账金币', + recharge_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '触发事件充值来源', + status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/granted/failed', + wallet_command_id VARCHAR(128) NOT NULL COMMENT 'wallet 资源组发放命令', + wallet_grant_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'wallet 发放回执', + failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因', + granted_at_ms 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, grant_id), + UNIQUE KEY uk_cumulative_recharge_reward_user_tier (app_code, cycle_key, user_id, tier_id), + UNIQUE KEY uk_cumulative_recharge_reward_wallet_command (app_code, wallet_command_id), + KEY idx_cumulative_recharge_reward_grant_event (app_code, event_id, status), + KEY idx_cumulative_recharge_reward_grant_user (app_code, cycle_key, user_id, created_at_ms), + KEY idx_cumulative_recharge_reward_grant_status (app_code, status, created_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='累充奖励资源组发放记录'`, + } + for _, statement := range statements { + if _, err := r.db.ExecContext(ctx, statement); err != nil { + return err + } + } + return nil +} diff --git a/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_repository.go b/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_repository.go new file mode 100644 index 00000000..caf6f9ec --- /dev/null +++ b/services/activity-service/internal/storage/mysql/cumulative_recharge_reward_repository.go @@ -0,0 +1,696 @@ +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/cumulativerecharge" +) + +// GetCumulativeRechargeRewardConfig 读取累充奖励当前配置;未配置时后台可展示空草稿。 +func (r *Repository) GetCumulativeRechargeRewardConfig(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, cumulativeRechargeRewardConfigSelectSQL()+` + WHERE app_code = ?`, + appcode.FromContext(ctx), + ) + config, err := scanCumulativeRechargeRewardConfig(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Config{}, false, nil + } + if err != nil { + return domain.Config{}, false, err + } + tiers, err := r.listCumulativeRechargeRewardTiers(ctx, nil) + if err != nil { + return domain.Config{}, false, err + } + config.Tiers = tiers + return config, true, nil +} + +// UpdateCumulativeRechargeRewardConfig 原子替换配置档位;已创建的 grant 保留命中时的档位快照。 +func (r *Repository) UpdateCumulativeRechargeRewardConfig(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 cumulative_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 + } + // 配置保存采用整组替换,避免后台删除/重排档位时保留脏行;历史 grant 已保存 tier 快照,不依赖当前档位表。 + if _, err := tx.ExecContext(ctx, ` + DELETE FROM cumulative_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 cumulative_recharge_reward_tiers ( + tier_id, app_code, tier_code, tier_name, threshold_usd_minor, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + tier.TierID, appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.ThresholdUSDMinor, + tier.ResourceGroupID, tier.Status, tier.SortOrder, tier.CreatedAtMS, tier.UpdatedAtMS, + ); err != nil { + return domain.Config{}, err + } + continue + } + result, err := tx.ExecContext(ctx, ` + INSERT INTO cumulative_recharge_reward_tiers ( + app_code, tier_code, tier_name, threshold_usd_minor, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.ThresholdUSDMinor, + 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.GetCumulativeRechargeRewardConfig(ctx) + if err != nil { + return domain.Config{}, err + } + if !exists { + return domain.Config{}, xerr.New(xerr.NotFound, "cumulative recharge reward config not found") + } + return updated, nil +} + +// GetCumulativeRechargeRewardProgress 读取用户当前周期累计;缺失代表本周还没有符合条件的充值。 +func (r *Repository) GetCumulativeRechargeRewardProgress(ctx context.Context, cycleKey string, userID int64) (domain.Progress, bool, error) { + if r == nil || r.db == nil { + return domain.Progress{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, cumulativeRechargeRewardProgressSelectSQL()+` + WHERE app_code = ? AND cycle_key = ? AND user_id = ?`, + appcode.FromContext(ctx), cycleKey, userID, + ) + progress, err := scanCumulativeRechargeRewardProgress(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Progress{}, false, nil + } + return progress, err == nil, err +} + +// ListCumulativeRechargeRewardGrantsByUserCycle 返回 H5 当前周期需要展示的用户发放状态。 +func (r *Repository) ListCumulativeRechargeRewardGrantsByUserCycle(ctx context.Context, cycleKey string, userID int64) ([]domain.Grant, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + rows, err := r.db.QueryContext(ctx, cumulativeRechargeRewardGrantSelectSQL()+` + WHERE app_code = ? AND cycle_key = ? AND user_id = ? + ORDER BY threshold_usd_minor ASC, created_at_ms ASC, grant_id ASC`, + appcode.FromContext(ctx), cycleKey, userID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + grants, _, err := scanCumulativeRechargeRewardGrants(rows, 0) + return grants, err +} + +// PrepareCumulativeRechargeRewardGrants 在 activity 事务内完成 event 幂等、周期累计和待发放 grant 创建。 +func (r *Repository) PrepareCumulativeRechargeRewardGrants(ctx context.Context, event domain.RechargeEvent, cycle domain.Cycle, 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() }() + + // event_id 是 wallet_outbox 事实源幂等键;重复 MQ 消息不能再次增加 progress。 + inserted, err := r.insertCumulativeRechargeRewardEvent(ctx, tx, event, cycle.Key, nowMS) + if err != nil { + return domain.PrepareResult{}, err + } + if !inserted { + // 重复 event 只恢复该 event 上还没成功的 grant,不重新计算累计,也不根据新配置补发历史档位。 + grants, err := r.pendingCumulativeRechargeRewardGrantsByEventForUpdate(ctx, tx, event.EventID, nowMS) + if err != nil { + return domain.PrepareResult{}, err + } + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + if len(grants) > 0 { + return domain.PrepareResult{Grants: grants, Consumed: true, Reason: domain.ReasonPendingReward}, nil + } + return domain.PrepareResult{Consumed: true, Reason: domain.ReasonAlreadyConsumed}, nil + } + + config, exists, err := r.getCumulativeRechargeRewardConfigForUpdate(ctx, tx) + if err != nil { + return domain.PrepareResult{}, err + } + if !exists { + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + // 未配置时只记录 event 幂等事实,保证之后同一 event 不会因为补配置而被误当成新充值。 + return domain.PrepareResult{Consumed: true, Reason: domain.ReasonNotConfigured}, nil + } + if !config.Enabled { + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + // 禁用期间的充值不会进入累计;这是配置只影响后续事件的明确边界。 + return domain.PrepareResult{Consumed: true, Reason: domain.ReasonDisabled}, nil + } + tiers, err := r.listCumulativeRechargeRewardTiersForUpdate(ctx, tx) + if err != nil { + return domain.PrepareResult{}, err + } + // 只有配置存在且启用后才累加 progress,避免后台开启活动时追溯禁用期事件。 + progress, err := r.upsertCumulativeRechargeRewardProgress(ctx, tx, event, cycle.Key, nowMS) + if err != nil { + return domain.PrepareResult{}, err + } + // 当前充值可能一次跨过多个档位,所有命中的 active 档位都会在同一事务里创建 pending grant。 + grants, err := r.prepareMatchedCumulativeRechargeRewardGrants(ctx, tx, event, progress, tiers, nowMS) + if err != nil { + return domain.PrepareResult{}, err + } + if err := tx.Commit(); err != nil { + return domain.PrepareResult{}, err + } + if len(grants) == 0 { + return domain.PrepareResult{Consumed: true, Reason: domain.ReasonNoTierMatched}, nil + } + return domain.PrepareResult{Grants: grants, Consumed: true, Reason: domain.ReasonEligible}, nil +} + +// MarkCumulativeRechargeRewardGrantGranted 写回 wallet-service 资源组发放回执。 +func (r *Repository) MarkCumulativeRechargeRewardGrantGranted(ctx context.Context, grantID string, walletGrantID string, grantedAtMS int64) (domain.Grant, error) { + if r == nil || r.db == nil { + return domain.Grant{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + _, err := r.db.ExecContext(ctx, ` + UPDATE cumulative_recharge_reward_grants + SET status = 'granted', + wallet_grant_id = ?, + failure_reason = '', + granted_at_ms = ?, + updated_at_ms = ? + WHERE app_code = ? AND grant_id = ? AND status <> 'granted'`, + walletGrantID, grantedAtMS, grantedAtMS, appcode.FromContext(ctx), grantID, + ) + if err != nil { + return domain.Grant{}, err + } + grant, exists, err := r.getCumulativeRechargeRewardGrantByID(ctx, grantID) + if err != nil { + return domain.Grant{}, err + } + if !exists { + return domain.Grant{}, xerr.New(xerr.NotFound, "cumulative recharge reward grant not found") + } + return grant, nil +} + +// MarkCumulativeRechargeRewardGrantFailed 保留 grant,后续同一 wallet event 重试会复用原钱包命令。 +func (r *Repository) MarkCumulativeRechargeRewardGrantFailed(ctx context.Context, grantID 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 cumulative_recharge_reward_grants + SET status = 'failed', failure_reason = ?, updated_at_ms = ? + WHERE app_code = ? AND grant_id = ? AND status <> 'granted'`, + truncateTaskFailure(failureReason), nowMS, appcode.FromContext(ctx), grantID, + ) + return err +} + +// ListCumulativeRechargeRewardGrants 返回后台发放记录,按创建时间倒序。 +func (r *Repository) ListCumulativeRechargeRewardGrants(ctx context.Context, query domain.GrantQuery) ([]domain.Grant, int64, error) { + if r == nil || r.db == nil { + return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + where, args := cumulativeRechargeRewardGrantWhere(ctx, query) + var total int64 + if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM cumulative_recharge_reward_grants `+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, cumulativeRechargeRewardGrantSelectSQL()+` + `+where+` + ORDER BY created_at_ms DESC, grant_id DESC + LIMIT ? OFFSET ?`, args...) + if err != nil { + return nil, 0, err + } + defer rows.Close() + return scanCumulativeRechargeRewardGrants(rows, total) +} + +func (r *Repository) insertCumulativeRechargeRewardEvent(ctx context.Context, tx *sql.Tx, event domain.RechargeEvent, cycleKey string, nowMS int64) (bool, error) { + // INSERT IGNORE 让 wallet event 成为幂等边界:插入成功才允许进入累计和档位判定。 + result, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO cumulative_recharge_reward_events ( + app_code, event_id, cycle_key, user_id, transaction_id, command_id, + recharge_type, recharge_coin_amount, qualifying_usd_minor, payload_json, + occurred_at_ms, created_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), event.EventID, cycleKey, event.UserID, event.TransactionID, event.CommandID, + event.RechargeType, event.RechargeCoinAmount, event.QualifyingUSDMinor, event.PayloadJSON, event.OccurredAtMS, nowMS, + ) + if err != nil { + return false, err + } + affected, err := result.RowsAffected() + if err != nil { + return false, err + } + return affected > 0, nil +} + +func (r *Repository) upsertCumulativeRechargeRewardProgress(ctx context.Context, tx *sql.Tx, event domain.RechargeEvent, cycleKey string, nowMS int64) (domain.Progress, error) { + // progress 是按 app + UTC 周 + user 聚合的金额投影;event 表先幂等后,这里可以安全做增量累加。 + _, err := tx.ExecContext(ctx, ` + INSERT INTO cumulative_recharge_reward_progress ( + app_code, cycle_key, user_id, total_usd_minor, total_coin_amount, + first_recharged_at_ms, last_recharged_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + total_usd_minor = total_usd_minor + VALUES(total_usd_minor), + total_coin_amount = total_coin_amount + VALUES(total_coin_amount), + last_recharged_at_ms = GREATEST(last_recharged_at_ms, VALUES(last_recharged_at_ms)), + updated_at_ms = VALUES(updated_at_ms)`, + appcode.FromContext(ctx), cycleKey, event.UserID, event.QualifyingUSDMinor, event.RechargeCoinAmount, + event.OccurredAtMS, event.OccurredAtMS, nowMS, + ) + if err != nil { + return domain.Progress{}, err + } + row := tx.QueryRowContext(ctx, cumulativeRechargeRewardProgressSelectSQL()+` + WHERE app_code = ? AND cycle_key = ? AND user_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), cycleKey, event.UserID, + ) + return scanCumulativeRechargeRewardProgress(row) +} + +func (r *Repository) prepareMatchedCumulativeRechargeRewardGrants(ctx context.Context, tx *sql.Tx, event domain.RechargeEvent, progress domain.Progress, tiers []domain.Tier, nowMS int64) ([]domain.Grant, error) { + prepared := make([]domain.Grant, 0) + for _, tier := range tiers { + // 只有 active 且资源组有效的档位可以发放;inactive 档位仍保留给后台展示和历史审计。 + if tier.Status != domain.TierStatusActive || tier.ResourceGroupID <= 0 || tier.ThresholdUSDMinor <= 0 { + continue + } + if progress.TotalUSDMinor < tier.ThresholdUSDMinor { + continue + } + // 唯一键 app/cycle/user/tier 保证每个 UTC 周每个档位最多创建一条 grant。 + existing, exists, err := r.getCumulativeRechargeRewardGrantByTierForUpdate(ctx, tx, progress.CycleKey, event.UserID, tier.TierID) + if err != nil { + return nil, err + } + if exists { + if existing.Status == domain.GrantStatusFailed { + // failed grant 代表 wallet 副作用没有确认成功,可以更新触发事件快照后再次尝试同一档位。 + if err := r.updateCumulativeRechargeRewardGrantPending(ctx, tx, existing.GrantID, event, progress.TotalUSDMinor, nowMS); err != nil { + return nil, err + } + existing.Status = domain.GrantStatusPending + existing.EventID = event.EventID + existing.TransactionID = event.TransactionID + existing.CommandID = event.CommandID + existing.ReachedUSDMinor = progress.TotalUSDMinor + existing.QualifyingUSDMinor = event.QualifyingUSDMinor + existing.RechargeCoinAmount = event.RechargeCoinAmount + existing.RechargeType = event.RechargeType + existing.FailureReason = "" + existing.UpdatedAtMS = nowMS + prepared = append(prepared, existing) + } + if existing.Status == domain.GrantStatusPending { + // pending grant 可能来自上次 MQ 消费已建单但还未完成 wallet 发放,直接返回给调用方继续执行。 + prepared = append(prepared, existing) + } + continue + } + grant := domain.Grant{ + GrantID: idgen.New("crgrant"), + AppCode: appcode.FromContext(ctx), + CycleKey: progress.CycleKey, + UserID: event.UserID, + EventID: event.EventID, + TransactionID: event.TransactionID, + CommandID: event.CommandID, + TierID: tier.TierID, + TierCode: tier.TierCode, + ThresholdUSDMinor: tier.ThresholdUSDMinor, + ResourceGroupID: tier.ResourceGroupID, + ReachedUSDMinor: progress.TotalUSDMinor, + QualifyingUSDMinor: event.QualifyingUSDMinor, + RechargeCoinAmount: event.RechargeCoinAmount, + RechargeType: event.RechargeType, + Status: domain.GrantStatusPending, + CreatedAtMS: nowMS, + UpdatedAtMS: nowMS, + } + // wallet_command_id 从 grant_id 派生,数据库唯一键和 wallet 幂等命令共同防止重复到账。 + grant.WalletCommandID = walletCumulativeRechargeRewardCommandID(grant.GrantID) + if err := r.insertCumulativeRechargeRewardGrant(ctx, tx, grant); err != nil { + return nil, err + } + prepared = append(prepared, grant) + } + return prepared, nil +} + +func (r *Repository) pendingCumulativeRechargeRewardGrantsByEventForUpdate(ctx context.Context, tx *sql.Tx, eventID string, nowMS int64) ([]domain.Grant, error) { + // 重复 event 只查同一 event 创建过的 pending/failed grant,避免借 MQ 重投触发新配置下的额外发放。 + rows, err := tx.QueryContext(ctx, cumulativeRechargeRewardGrantSelectSQL()+` + WHERE app_code = ? AND event_id = ? AND status IN ('pending', 'failed') + ORDER BY threshold_usd_minor ASC, grant_id ASC + FOR UPDATE`, + appcode.FromContext(ctx), eventID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + grants, _, err := scanCumulativeRechargeRewardGrants(rows, 0) + if err != nil { + return nil, err + } + for index := range grants { + if grants[index].Status != domain.GrantStatusFailed { + continue + } + // failed 回到 pending 时不生成新 grant_id 或新 wallet_command_id,重试路径仍保持幂等。 + if err := r.updateCumulativeRechargeRewardGrantPendingByID(ctx, tx, grants[index].GrantID, nowMS); err != nil { + return nil, err + } + grants[index].Status = domain.GrantStatusPending + grants[index].FailureReason = "" + grants[index].UpdatedAtMS = nowMS + } + return grants, nil +} + +func (r *Repository) getCumulativeRechargeRewardConfigForUpdate(ctx context.Context, tx *sql.Tx) (domain.Config, bool, error) { + row := tx.QueryRowContext(ctx, cumulativeRechargeRewardConfigSelectSQL()+` + WHERE app_code = ? + FOR UPDATE`, + appcode.FromContext(ctx), + ) + config, err := scanCumulativeRechargeRewardConfig(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Config{}, false, nil + } + return config, err == nil, err +} + +func (r *Repository) listCumulativeRechargeRewardTiers(ctx context.Context, tx *sql.Tx) ([]domain.Tier, error) { + query := cumulativeRechargeRewardTierSelectSQL() + ` + WHERE app_code = ? + ORDER BY sort_order ASC, threshold_usd_minor ASC, tier_id ASC` + var rows *sql.Rows + var err error + if tx != nil { + rows, err = tx.QueryContext(ctx, query, appcode.FromContext(ctx)) + } else { + rows, err = r.db.QueryContext(ctx, query, appcode.FromContext(ctx)) + } + if err != nil { + return nil, err + } + defer rows.Close() + return scanCumulativeRechargeRewardTiers(rows) +} + +func (r *Repository) listCumulativeRechargeRewardTiersForUpdate(ctx context.Context, tx *sql.Tx) ([]domain.Tier, error) { + rows, err := tx.QueryContext(ctx, cumulativeRechargeRewardTierSelectSQL()+` + WHERE app_code = ? + ORDER BY sort_order ASC, threshold_usd_minor ASC, tier_id ASC + FOR UPDATE`, + appcode.FromContext(ctx), + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanCumulativeRechargeRewardTiers(rows) +} + +func (r *Repository) getCumulativeRechargeRewardGrantByTierForUpdate(ctx context.Context, tx *sql.Tx, cycleKey string, userID int64, tierID int64) (domain.Grant, bool, error) { + row := tx.QueryRowContext(ctx, cumulativeRechargeRewardGrantSelectSQL()+` + WHERE app_code = ? AND cycle_key = ? AND user_id = ? AND tier_id = ? + FOR UPDATE`, + appcode.FromContext(ctx), cycleKey, userID, tierID, + ) + grant, err := scanCumulativeRechargeRewardGrant(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Grant{}, false, nil + } + return grant, err == nil, err +} + +func (r *Repository) getCumulativeRechargeRewardGrantByID(ctx context.Context, grantID string) (domain.Grant, bool, error) { + row := r.db.QueryRowContext(ctx, cumulativeRechargeRewardGrantSelectSQL()+` + WHERE app_code = ? AND grant_id = ?`, + appcode.FromContext(ctx), grantID, + ) + grant, err := scanCumulativeRechargeRewardGrant(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Grant{}, false, nil + } + return grant, err == nil, err +} + +func (r *Repository) insertCumulativeRechargeRewardGrant(ctx context.Context, tx *sql.Tx, grant domain.Grant) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO cumulative_recharge_reward_grants ( + app_code, grant_id, cycle_key, user_id, event_id, transaction_id, command_id, + tier_id, tier_code, threshold_usd_minor, resource_group_id, reached_usd_minor, + qualifying_usd_minor, recharge_coin_amount, recharge_type, status, wallet_command_id, + wallet_grant_id, failure_reason, granted_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', '', 0, ?, ?)`, + appcode.FromContext(ctx), grant.GrantID, grant.CycleKey, grant.UserID, grant.EventID, grant.TransactionID, grant.CommandID, + grant.TierID, grant.TierCode, grant.ThresholdUSDMinor, grant.ResourceGroupID, grant.ReachedUSDMinor, + grant.QualifyingUSDMinor, grant.RechargeCoinAmount, grant.RechargeType, grant.Status, grant.WalletCommandID, + grant.CreatedAtMS, grant.UpdatedAtMS, + ) + return err +} + +func (r *Repository) updateCumulativeRechargeRewardGrantPending(ctx context.Context, tx *sql.Tx, grantID string, event domain.RechargeEvent, reachedUSDMinor int64, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + UPDATE cumulative_recharge_reward_grants + SET event_id = ?, + transaction_id = ?, + command_id = ?, + reached_usd_minor = ?, + qualifying_usd_minor = ?, + recharge_coin_amount = ?, + recharge_type = ?, + status = 'pending', + wallet_grant_id = '', + failure_reason = '', + granted_at_ms = 0, + updated_at_ms = ? + WHERE app_code = ? AND grant_id = ? AND status = 'failed'`, + event.EventID, event.TransactionID, event.CommandID, reachedUSDMinor, event.QualifyingUSDMinor, + event.RechargeCoinAmount, event.RechargeType, nowMS, appcode.FromContext(ctx), grantID, + ) + return err +} + +func (r *Repository) updateCumulativeRechargeRewardGrantPendingByID(ctx context.Context, tx *sql.Tx, grantID string, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + UPDATE cumulative_recharge_reward_grants + SET status = 'pending', + wallet_grant_id = '', + failure_reason = '', + granted_at_ms = 0, + updated_at_ms = ? + WHERE app_code = ? AND grant_id = ? AND status = 'failed'`, + nowMS, appcode.FromContext(ctx), grantID, + ) + return err +} + +func scanCumulativeRechargeRewardConfig(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 scanCumulativeRechargeRewardTiers(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.ThresholdUSDMinor, + &item.ResourceGroupID, + &item.Status, + &item.SortOrder, + &item.CreatedAtMS, + &item.UpdatedAtMS, + ); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +func scanCumulativeRechargeRewardProgress(row rowScanner) (domain.Progress, error) { + var item domain.Progress + err := row.Scan( + &item.AppCode, + &item.CycleKey, + &item.UserID, + &item.TotalUSDMinor, + &item.TotalCoinAmount, + &item.FirstRechargedAtMS, + &item.LastRechargedAtMS, + &item.UpdatedAtMS, + ) + return item, err +} + +func scanCumulativeRechargeRewardGrants(rows *sql.Rows, total int64) ([]domain.Grant, int64, error) { + items := make([]domain.Grant, 0) + for rows.Next() { + item, err := scanCumulativeRechargeRewardGrant(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 scanCumulativeRechargeRewardGrant(row rowScanner) (domain.Grant, error) { + var item domain.Grant + err := row.Scan( + &item.GrantID, + &item.AppCode, + &item.CycleKey, + &item.UserID, + &item.EventID, + &item.TransactionID, + &item.CommandID, + &item.TierID, + &item.TierCode, + &item.ThresholdUSDMinor, + &item.ResourceGroupID, + &item.ReachedUSDMinor, + &item.QualifyingUSDMinor, + &item.RechargeCoinAmount, + &item.RechargeType, + &item.Status, + &item.WalletCommandID, + &item.WalletGrantID, + &item.FailureReason, + &item.GrantedAtMS, + &item.CreatedAtMS, + &item.UpdatedAtMS, + ) + return item, err +} + +func cumulativeRechargeRewardConfigSelectSQL() string { + return `SELECT app_code, enabled, updated_by_admin_id, created_at_ms, updated_at_ms + FROM cumulative_recharge_reward_configs ` +} + +func cumulativeRechargeRewardTierSelectSQL() string { + return `SELECT tier_id, tier_code, tier_name, threshold_usd_minor, + resource_group_id, status, sort_order, created_at_ms, updated_at_ms + FROM cumulative_recharge_reward_tiers ` +} + +func cumulativeRechargeRewardProgressSelectSQL() string { + return `SELECT app_code, cycle_key, user_id, total_usd_minor, total_coin_amount, + first_recharged_at_ms, last_recharged_at_ms, updated_at_ms + FROM cumulative_recharge_reward_progress ` +} + +func cumulativeRechargeRewardGrantSelectSQL() string { + return `SELECT grant_id, app_code, cycle_key, user_id, event_id, transaction_id, command_id, + tier_id, tier_code, threshold_usd_minor, resource_group_id, reached_usd_minor, + qualifying_usd_minor, recharge_coin_amount, recharge_type, status, wallet_command_id, + wallet_grant_id, failure_reason, granted_at_ms, created_at_ms, updated_at_ms + FROM cumulative_recharge_reward_grants ` +} + +func cumulativeRechargeRewardGrantWhere(ctx context.Context, query domain.GrantQuery) (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) + } + if query.CycleKey != "" { + conditions = append(conditions, "cycle_key = ?") + args = append(args, query.CycleKey) + } + return "WHERE " + strings.Join(conditions, " AND "), args +} + +func walletCumulativeRechargeRewardCommandID(grantID string) string { + // 前缀区分累充奖励和其他 wallet 资源组发放来源,便于钱包侧排查命令来源。 + return fmt.Sprintf("wcr_%s", grantID) +} diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go index fc10e550..b81c11f3 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository.go @@ -184,7 +184,7 @@ func (r *Repository) CheckLuckyGift(ctx context.Context, cmd domain.CheckCommand return domain.CheckResult{ Enabled: config.Enabled, Reason: luckyEnabledReason(config.Enabled), - PoolID: config.GiftID, + PoolID: config.PoolID, GiftID: cmd.GiftID, GiftPrice: config.GiftPrice, RuleVersion: config.RuleVersion, @@ -466,7 +466,7 @@ func (r *Repository) stageLuckyBatchDraw(appCode string, baseConfig domain.Confi return domain.DrawResult{ DrawID: drawID, CommandID: cmd.CommandID, - PoolID: config.GiftID, + PoolID: config.PoolID, GiftID: cmd.GiftID, RuleVersion: config.RuleVersion, ExperiencePool: experiencePool, @@ -627,15 +627,15 @@ func (r *Repository) insertLuckyDrawRecords(ctx context.Context, tx *sql.Tx, rec var sqlBuilder strings.Builder sqlBuilder.WriteString(` INSERT INTO lucky_draw_records ( - app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, pool_id, gift_id, + app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, visible_region_id, pool_id, gift_id, coin_spent, rule_version, experience_pool, rtp_window_index, gift_rtp_window_index, selected_tier_id, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, effective_reward_coins, budget_sources_json, stage_feedback, high_multiplier, candidate_tiers_json, pool_snapshot_json, rtp_snapshot_json, reward_status, reward_transaction_id, reward_failure_reason, paid_at_ms, created_at_ms, updated_at_ms ) VALUES `) - args := make([]any, 0, len(batch)*31) - rowPlaceholders := "(" + luckySQLPlaceholders(31) + ")" + args := make([]any, 0, len(batch)*32) + rowPlaceholders := "(" + luckySQLPlaceholders(32) + ")" for index, record := range batch { if index > 0 { sqlBuilder.WriteString(",") @@ -741,6 +741,7 @@ type luckyDrawStatsRecord struct { DrawID string PoolID string GiftID string + VisibleRegionID int64 UserID int64 RoomID string TotalSpentCoins int64 @@ -875,6 +876,148 @@ func (r *Repository) RefreshLuckyGiftAdminStatsSnapshots(ctx context.Context, no return len(records), nil } +type luckyDrawPoolDayStatKey struct { + AppCode string + StatDay string + VisibleRegionID int64 + PoolID string + GiftID string +} + +type luckyDrawPoolDayStatDelta struct { + DrawCount int64 + TurnoverCoin int64 + PayoutCoin int64 + BaseRewardCoin int64 + RoomAtmosphereRewardCoin int64 + ActivitySubsidyCoin int64 +} + +// RefreshLuckyGiftDatabiStatsSnapshots 用独立游标把抽奖事实小批量转成 Databi 日维度汇总。 +// Databi 页面只读 lucky_draw_pool_day_stats,不直接扫 lucky_draw_records,避免页面访问把事实表打成查询热点。 +func (r *Repository) RefreshLuckyGiftDatabiStatsSnapshots(ctx context.Context, nowMS int64, batchSize int) (int, error) { + if r == nil || r.db == nil { + return 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if batchSize <= 0 { + batchSize = 5000 + } + if batchSize > 50000 { + batchSize = 50000 + } + appCode := appcode.FromContext(ctx) + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return 0, err + } + defer func() { _ = tx.Rollback() }() + + cursor, err := r.lockLuckyDrawDatabiStatsCursor(ctx, tx, appCode, nowMS) + if err != nil { + return 0, err + } + rows, err := tx.QueryContext(ctx, ` + SELECT app_code, draw_id, visible_region_id, pool_id, gift_id, user_id, room_id, coin_spent, + effective_reward_coins, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, + reward_status, + created_at_ms + FROM lucky_draw_records FORCE INDEX (idx_lucky_draw_created) + WHERE app_code = ? + AND (created_at_ms > ? OR (created_at_ms = ? AND draw_id > ?)) + ORDER BY created_at_ms ASC, draw_id ASC + LIMIT ?`, appCode, cursor.LastDrawCreatedAtMS, cursor.LastDrawCreatedAtMS, cursor.LastDrawID, batchSize) + if err != nil { + return 0, err + } + defer rows.Close() + records := make([]luckyDrawStatsRecord, 0, batchSize) + for rows.Next() { + var record luckyDrawStatsRecord + if err := rows.Scan(&record.AppCode, &record.DrawID, &record.VisibleRegionID, &record.PoolID, &record.GiftID, &record.UserID, &record.RoomID, + &record.TotalSpentCoins, &record.TotalRewardCoins, &record.BaseRewardCoins, + &record.RoomAtmosphereRewardCoins, &record.ActivitySubsidyCoins, &record.RewardStatus, &record.CreatedAtMS); err != nil { + return 0, err + } + records = append(records, record) + } + if err := rows.Err(); err != nil { + return 0, err + } + if len(records) == 0 { + if err := tx.Commit(); err != nil { + return 0, err + } + return 0, nil + } + grouped := map[luckyDrawPoolDayStatKey]*luckyDrawPoolDayStatDelta{} + last := records[len(records)-1] + for _, record := range records { + regionID := record.VisibleRegionID + if regionID < 0 { + regionID = 0 + } + day := luckyDrawStatDay(record.CreatedAtMS) + keys := []luckyDrawPoolDayStatKey{{AppCode: record.AppCode, StatDay: day, VisibleRegionID: regionID, PoolID: record.PoolID, GiftID: ""}} + if giftID := strings.TrimSpace(record.GiftID); giftID != "" { + keys = append(keys, luckyDrawPoolDayStatKey{AppCode: record.AppCode, StatDay: day, VisibleRegionID: regionID, PoolID: record.PoolID, GiftID: giftID}) + } + for _, key := range keys { + delta := grouped[key] + if delta == nil { + delta = &luckyDrawPoolDayStatDelta{} + grouped[key] = delta + } + delta.DrawCount++ + delta.TurnoverCoin += record.TotalSpentCoins + delta.PayoutCoin += record.TotalRewardCoins + delta.BaseRewardCoin += record.BaseRewardCoins + delta.RoomAtmosphereRewardCoin += record.RoomAtmosphereRewardCoins + delta.ActivitySubsidyCoin += record.ActivitySubsidyCoins + } + } + for key, delta := range grouped { + if err := r.upsertLuckyDrawPoolDayStatsDelta(ctx, tx, key, *delta, nowMS); err != nil { + return 0, err + } + } + if _, err := tx.ExecContext(ctx, ` + UPDATE lucky_draw_pool_stat_cursors + SET last_draw_created_at_ms = ?, last_draw_id = ?, updated_at_ms = ? + WHERE app_code = ? AND cursor_name = 'draw_records_databi_day'`, + last.CreatedAtMS, last.DrawID, nowMS, appCode, + ); err != nil { + return 0, err + } + if err := tx.Commit(); err != nil { + return 0, err + } + return len(records), nil +} + +func (r *Repository) upsertLuckyDrawPoolDayStatsDelta(ctx context.Context, tx *sql.Tx, key luckyDrawPoolDayStatKey, delta luckyDrawPoolDayStatDelta, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO lucky_draw_pool_day_stats ( + app_code, stat_day, visible_region_id, pool_id, gift_id, draw_count, turnover_coin, payout_coin, + base_reward_coin, room_atmosphere_reward_coin, activity_subsidy_coin, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + draw_count = draw_count + VALUES(draw_count), + turnover_coin = turnover_coin + VALUES(turnover_coin), + payout_coin = payout_coin + VALUES(payout_coin), + base_reward_coin = base_reward_coin + VALUES(base_reward_coin), + room_atmosphere_reward_coin = room_atmosphere_reward_coin + VALUES(room_atmosphere_reward_coin), + activity_subsidy_coin = activity_subsidy_coin + VALUES(activity_subsidy_coin), + updated_at_ms = VALUES(updated_at_ms)`, + key.AppCode, key.StatDay, key.VisibleRegionID, key.PoolID, key.GiftID, delta.DrawCount, delta.TurnoverCoin, delta.PayoutCoin, + delta.BaseRewardCoin, delta.RoomAtmosphereRewardCoin, delta.ActivitySubsidyCoin, nowMS, nowMS, + ) + return err +} + +func luckyDrawStatDay(ms int64) string { + return time.UnixMilli(ms).UTC().Format("2006-01-02") +} + func (r *Repository) lockLuckyDrawStatsCursor(ctx context.Context, tx *sql.Tx, appCode string, nowMS int64) (luckyDrawStatsCursor, bool, error) { var cursor luckyDrawStatsCursor err := tx.QueryRowContext(ctx, ` @@ -909,12 +1052,38 @@ func (r *Repository) lockLuckyDrawStatsCursor(ctx context.Context, tx *sql.Tx, a return cursor, true, nil } +func (r *Repository) lockLuckyDrawDatabiStatsCursor(ctx context.Context, tx *sql.Tx, appCode string, nowMS int64) (luckyDrawStatsCursor, error) { + var cursor luckyDrawStatsCursor + err := tx.QueryRowContext(ctx, ` + SELECT last_draw_created_at_ms, last_draw_id + FROM lucky_draw_pool_stat_cursors + WHERE app_code = ? AND cursor_name = 'draw_records_databi_day' + FOR UPDATE`, appCode, + ).Scan(&cursor.LastDrawCreatedAtMS, &cursor.LastDrawID) + if err == nil { + return cursor, nil + } + if !errors.Is(err, sql.ErrNoRows) { + return luckyDrawStatsCursor{}, err + } + // Databi 日汇总是后加的统计口径,首次启动必须从 0 游标小批量回补;不要像后台全量汇总那样跳到最新记录。 + if _, err := tx.ExecContext(ctx, ` + INSERT INTO lucky_draw_pool_stat_cursors ( + app_code, cursor_name, last_draw_created_at_ms, last_draw_id, created_at_ms, updated_at_ms + ) VALUES (?, 'draw_records_databi_day', 0, '', ?, ?)`, + appCode, nowMS, nowMS, + ); err != nil { + return luckyDrawStatsCursor{}, err + } + return cursor, nil +} + // luckyDrawRecordArgs 固定 lucky_draw_records 的列顺序;集中维护可以避免批量 INSERT 和单条 INSERT 语义漂移。 func luckyDrawRecordArgs(input luckyDrawRecordInput) []any { candidateSnapshot, poolSnapshot, rtpSnapshot := luckyDrawRecordSnapshots(input) return []any{ input.AppCode, input.DrawID, input.Command.CommandID, input.Command.UserID, input.Command.DeviceID, - input.Command.RoomID, input.Command.AnchorID, input.Config.GiftID, input.Command.GiftID, input.Command.CoinSpent, + input.Command.RoomID, input.Command.AnchorID, input.Command.VisibleRegionID, input.Config.PoolID, input.Command.GiftID, input.Command.CoinSpent, input.Config.RuleVersion, input.ExperiencePool, input.GlobalWindow.WindowIndex, input.GiftWindow.WindowIndex, input.Candidate.TierID, input.Candidate.BaseReward, input.Candidate.RoomReward, input.Candidate.ActivityReward, input.Candidate.effectiveReward(), input.BudgetSourcesJSON, input.StageFeedback, input.Candidate.HighMultiplier, @@ -1102,7 +1271,7 @@ func (r *Repository) executeSingleLuckyGiftDraw(ctx context.Context, tx *sql.Tx, return domain.DrawResult{ DrawID: drawID, CommandID: cmd.CommandID, - PoolID: config.GiftID, + PoolID: config.PoolID, GiftID: cmd.GiftID, RuleVersion: config.RuleVersion, ExperiencePool: experiencePool, @@ -1370,15 +1539,15 @@ func (r *Repository) applyLuckyDraw(ctx context.Context, tx *sql.Tx, input lucky }) if _, err := tx.ExecContext(ctx, ` INSERT INTO lucky_draw_records ( - app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, pool_id, gift_id, + app_code, draw_id, command_id, user_id, device_id, room_id, anchor_id, visible_region_id, pool_id, gift_id, coin_spent, rule_version, experience_pool, rtp_window_index, gift_rtp_window_index, selected_tier_id, base_reward_coins, room_atmosphere_reward_coins, activity_subsidy_coins, effective_reward_coins, budget_sources_json, stage_feedback, high_multiplier, candidate_tiers_json, pool_snapshot_json, rtp_snapshot_json, reward_status, reward_transaction_id, reward_failure_reason, paid_at_ms, created_at_ms, updated_at_ms - ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, + ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, input.AppCode, input.DrawID, input.Command.CommandID, input.Command.UserID, input.Command.DeviceID, - input.Command.RoomID, input.Command.AnchorID, input.Config.GiftID, input.Command.GiftID, input.Command.CoinSpent, + input.Command.RoomID, input.Command.AnchorID, input.Command.VisibleRegionID, input.Config.PoolID, input.Command.GiftID, input.Command.CoinSpent, input.Config.RuleVersion, input.ExperiencePool, input.GlobalWindow.WindowIndex, input.GiftWindow.WindowIndex, input.Candidate.TierID, input.Candidate.BaseReward, input.Candidate.RoomReward, input.Candidate.ActivityReward, input.Candidate.effectiveReward(), input.BudgetSourcesJSON, input.StageFeedback, input.Candidate.HighMultiplier, @@ -1395,7 +1564,7 @@ func (r *Repository) applyLuckyDraw(ctx context.Context, tx *sql.Tx, input lucky "app_code": input.AppCode, "draw_id": input.DrawID, "command_id": input.Command.CommandID, - "pool_id": input.Config.GiftID, + "pool_id": input.Config.PoolID, "user_id": input.Command.UserID, "sender_user_id": input.Command.UserID, "target_user_id": input.Command.TargetUserID, diff --git a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go index e8909bd6..ba546c0e 100644 --- a/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go +++ b/services/activity-service/internal/storage/mysql/lucky_gift_repository_test.go @@ -117,6 +117,14 @@ func TestRefreshLuckyGiftAdminStatsSnapshotsAdvancesCursorByBatch(t *testing.T) assertLuckyStatsTotal(t, repository, "", 1, 100, 300) assertLuckyStatsStatus(t, repository, "", 0, 1, 0) assertLuckyStatsCursor(t, repository, 100, "draw_001") + processed, err = repository.RefreshLuckyGiftDatabiStatsSnapshots(ctx, 310, 1) + if err != nil { + t.Fatalf("first databi refresh failed: %v", err) + } + if processed != 1 { + t.Fatalf("first databi refresh should process one row, got %d", processed) + } + assertLuckyDatabiDayStatsTotal(t, repository, "1970-01-01", "", 1, 100, 300) processed, err = repository.RefreshLuckyGiftAdminStatsSnapshots(ctx, 400, 10) if err != nil { @@ -128,6 +136,14 @@ func TestRefreshLuckyGiftAdminStatsSnapshotsAdvancesCursorByBatch(t *testing.T) assertLuckyStatsTotal(t, repository, "", 2, 250, 300) assertLuckyStatsStatus(t, repository, "", 1, 1, 0) assertLuckyStatsCursor(t, repository, 200, "draw_002") + processed, err = repository.RefreshLuckyGiftDatabiStatsSnapshots(ctx, 410, 10) + if err != nil { + t.Fatalf("second databi refresh failed: %v", err) + } + if processed != 1 { + t.Fatalf("second databi refresh should process remaining row, got %d", processed) + } + assertLuckyDatabiDayStatsTotal(t, repository, "1970-01-01", "", 2, 250, 300) } func seedLuckyDrawRecordForStats(t *testing.T, repository *Repository, drawID string, commandID string, status string, createdAtMS int64, spent int64, reward int64) { @@ -183,6 +199,21 @@ func assertLuckyStatsStatus(t *testing.T, repository *Repository, giftID string, } } +func assertLuckyDatabiDayStatsTotal(t *testing.T, repository *Repository, day string, giftID string, wantDraws int64, wantSpent int64, wantReward int64) { + t.Helper() + var draws, spent, reward int64 + if err := repository.db.QueryRowContext(context.Background(), ` + SELECT draw_count, turnover_coin, payout_coin + FROM lucky_draw_pool_day_stats + WHERE app_code = 'lalu' AND stat_day = ? AND visible_region_id = 0 AND pool_id = 'lucky' AND gift_id = ?`, day, giftID, + ).Scan(&draws, &spent, &reward); err != nil { + t.Fatalf("read databi day stats total: %v", err) + } + if draws != wantDraws || spent != wantSpent || reward != wantReward { + t.Fatalf("databi day stats mismatch: draws=%d spent=%d reward=%d want draws=%d spent=%d reward=%d", draws, spent, reward, wantDraws, wantSpent, wantReward) + } +} + func assertLuckyStatsCursor(t *testing.T, repository *Repository, wantCreatedAtMS int64, wantDrawID string) { t.Helper() var createdAtMS int64 diff --git a/services/activity-service/internal/storage/mysql/registration_reward_repository.go b/services/activity-service/internal/storage/mysql/registration_reward_repository.go index 6af3bf8f..ee8532c6 100644 --- a/services/activity-service/internal/storage/mysql/registration_reward_repository.go +++ b/services/activity-service/internal/storage/mysql/registration_reward_repository.go @@ -13,6 +13,8 @@ import ( domain "hyapp/services/activity-service/internal/domain/registrationreward" ) +const registrationRewardClaimDisplayTimeSQL = "COALESCE(NULLIF(claimed_at_ms, 0), created_at_ms)" + // GetRegistrationRewardConfig 读取注册奖励当前配置;未配置是正常后台首屏状态。 func (r *Repository) GetRegistrationRewardConfig(ctx context.Context) (domain.Config, bool, error) { if r == nil || r.db == nil { @@ -335,7 +337,7 @@ func (r *Repository) ListRegistrationRewardClaims(ctx context.Context, query dom args = append(args, pageSize, (page-1)*pageSize) rows, err := r.db.QueryContext(ctx, registrationRewardClaimSelectSQL()+` `+where+` - ORDER BY created_at_ms DESC, claim_id DESC + ORDER BY `+registrationRewardClaimDisplayTimeSQL+` DESC, claim_id DESC LIMIT ? OFFSET ?`, args...) if err != nil { return nil, 0, err @@ -344,6 +346,28 @@ func (r *Repository) ListRegistrationRewardClaims(ctx context.Context, query dom return scanRegistrationRewardClaims(rows, total) } +// CountRegistrationRewardGrantedByDay 读取 UTC 当天已发放份数;后台只展示成功发放数量,不把 pending 预留量算作已领取。 +func (r *Repository) CountRegistrationRewardGrantedByDay(ctx context.Context, rewardDay string) (int64, error) { + if r == nil || r.db == nil { + return 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + rewardDay = strings.TrimSpace(rewardDay) + if rewardDay == "" { + return 0, nil + } + var count int64 + err := r.db.QueryRowContext(ctx, ` + SELECT granted_count + FROM registration_reward_daily_counters + WHERE app_code = ? AND reward_day = ?`, + appcode.FromContext(ctx), rewardDay, + ).Scan(&count) + if errors.Is(err, sql.ErrNoRows) { + return 0, nil + } + return count, err +} + func (r *Repository) getRegistrationRewardConfigForUpdate(ctx context.Context, tx *sql.Tx) (domain.Config, bool, error) { row := tx.QueryRowContext(ctx, registrationRewardConfigSelectSQL()+` WHERE app_code = ? @@ -571,6 +595,14 @@ func registrationRewardClaimWhere(ctx context.Context, query domain.ClaimQuery) conditions = append(conditions, "user_id = ?") args = append(args, query.UserID) } + if query.ClaimedStartMS > 0 { + conditions = append(conditions, registrationRewardClaimDisplayTimeSQL+" >= ?") + args = append(args, query.ClaimedStartMS) + } + if query.ClaimedEndMS > 0 { + conditions = append(conditions, registrationRewardClaimDisplayTimeSQL+" <= ?") + args = append(args, query.ClaimedEndMS) + } return "WHERE " + strings.Join(conditions, " AND "), args } diff --git a/services/activity-service/internal/storage/mysql/repository.go b/services/activity-service/internal/storage/mysql/repository.go index 2bebaebc..b2e19581 100644 --- a/services/activity-service/internal/storage/mysql/repository.go +++ b/services/activity-service/internal/storage/mysql/repository.go @@ -45,6 +45,9 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureLuckyDrawPoolID(ctx); err != nil { return err } + if err := r.ensureLuckyDrawVisibleRegion(ctx); err != nil { + return err + } if err := r.ensureLuckyGiftOutboxColumns(ctx); err != nil { return err } @@ -63,12 +66,21 @@ func (r *Repository) Migrate(ctx context.Context) error { if err := r.ensureLuckyGiftRuleVersionTables(ctx); err != nil { return err } + if err := r.ensureWeeklyStarTables(ctx); err != nil { + return err + } if err := r.ensureLuckyUserStateFlowColumns(ctx); err != nil { return err } if err := r.ensureDefaultLuckyGiftRules(ctx); err != nil { return err } + if err := r.ensureRoomTurnoverRewardTables(ctx); err != nil { + return err + } + if err := r.ensureCumulativeRechargeRewardTables(ctx); err != nil { + return err + } return nil } @@ -93,6 +105,23 @@ func (r *Repository) ensureLuckyDrawPoolStatsTables(ctx context.Context) error { updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, pool_id, gift_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物池级汇总统计'`, + `CREATE TABLE IF NOT EXISTS lucky_draw_pool_day_stats ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + stat_day DATE NOT NULL COMMENT 'UTC 统计日', + visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域 ID', + pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', + gift_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '礼物 ID,空值表示奖池汇总', + draw_count BIGINT NOT NULL DEFAULT 0 COMMENT '抽奖次数', + turnover_coin BIGINT NOT NULL DEFAULT 0 COMMENT '消耗金币', + payout_coin BIGINT NOT NULL DEFAULT 0 COMMENT '用户可见返奖金币', + base_reward_coin BIGINT NOT NULL DEFAULT 0 COMMENT '基础 RTP 返奖', + room_atmosphere_reward_coin BIGINT NOT NULL DEFAULT 0 COMMENT '房间气氛支出', + activity_subsidy_coin 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, stat_day, visible_region_id, pool_id, gift_id), + KEY idx_lucky_draw_pool_day_overview (app_code, stat_day, pool_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物 Databi 日维度汇总'`, `CREATE TABLE IF NOT EXISTS lucky_draw_pool_stat_users ( app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', @@ -216,6 +245,31 @@ func (r *Repository) ensureLuckyDrawPoolID(ctx context.Context) error { return nil } +func (r *Repository) ensureLuckyDrawVisibleRegion(ctx context.Context) error { + const table = "lucky_draw_records" + hasVisibleRegion, err := r.columnExists(ctx, table, "visible_region_id") + if err != nil { + return err + } + if !hasVisibleRegion { + if _, err := r.db.ExecContext(ctx, ` + ALTER TABLE lucky_draw_records + ADD COLUMN visible_region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域 ID' AFTER anchor_id`); err != nil { + return err + } + } + hasIndex, err := r.indexExists(ctx, table, "idx_lucky_draw_region_created") + if err != nil { + return err + } + if !hasIndex { + if _, err := r.db.ExecContext(ctx, `CREATE INDEX idx_lucky_draw_region_created ON lucky_draw_records (app_code, visible_region_id, created_at_ms, draw_id)`); err != nil { + return err + } + } + return nil +} + func (r *Repository) ensureLuckyGiftOutboxColumns(ctx context.Context) error { additions := []struct { name string diff --git a/services/activity-service/internal/storage/mysql/repository_migration_test.go b/services/activity-service/internal/storage/mysql/repository_migration_test.go index 76e8b8b4..accc5985 100644 --- a/services/activity-service/internal/storage/mysql/repository_migration_test.go +++ b/services/activity-service/internal/storage/mysql/repository_migration_test.go @@ -19,6 +19,15 @@ func TestMigrateAddsLuckyDrawPoolIDToLegacyTable(t *testing.T) { if _, err := schema.DB.ExecContext(context.Background(), `ALTER TABLE lucky_draw_records DROP COLUMN pool_id`); err != nil { t.Fatalf("drop legacy pool column: %v", err) } + if _, err := schema.DB.ExecContext(context.Background(), `ALTER TABLE lucky_draw_records DROP INDEX idx_lucky_draw_region_created`); err != nil { + t.Fatalf("drop legacy region index: %v", err) + } + if _, err := schema.DB.ExecContext(context.Background(), `ALTER TABLE lucky_draw_records DROP COLUMN visible_region_id`); err != nil { + t.Fatalf("drop legacy region column: %v", err) + } + if _, err := schema.DB.ExecContext(context.Background(), `DROP TABLE lucky_draw_pool_day_stats`); err != nil { + t.Fatalf("drop legacy databi day stats table: %v", err) + } repository, err := Open(context.Background(), schema.DSN) if err != nil { @@ -34,4 +43,23 @@ func TestMigrateAddsLuckyDrawPoolIDToLegacyTable(t *testing.T) { if hasIndex, err := repository.indexExists(context.Background(), "lucky_draw_records", "idx_lucky_draw_pool"); err != nil || !hasIndex { t.Fatalf("idx_lucky_draw_pool missing after migrate: has=%v err=%v", hasIndex, err) } + if hasColumn, err := repository.columnExists(context.Background(), "lucky_draw_records", "visible_region_id"); err != nil || !hasColumn { + t.Fatalf("visible_region_id column missing after migrate: has=%v err=%v", hasColumn, err) + } + if hasIndex, err := repository.indexExists(context.Background(), "lucky_draw_records", "idx_lucky_draw_region_created"); err != nil || !hasIndex { + t.Fatalf("idx_lucky_draw_region_created missing after migrate: has=%v err=%v", hasIndex, err) + } + if hasTable, err := activityTableExists(context.Background(), repository, "lucky_draw_pool_day_stats"); err != nil || !hasTable { + t.Fatalf("lucky_draw_pool_day_stats table missing after migrate: has=%v err=%v", hasTable, err) + } +} + +func activityTableExists(ctx context.Context, repository *Repository, tableName string) (bool, error) { + var count int + err := repository.db.QueryRowContext(ctx, ` + SELECT COUNT(*) + FROM information_schema.tables + WHERE table_schema = DATABASE() AND table_name = ?`, tableName, + ).Scan(&count) + return count > 0, err } diff --git a/services/activity-service/internal/storage/mysql/room_turnover_reward_migration.go b/services/activity-service/internal/storage/mysql/room_turnover_reward_migration.go new file mode 100644 index 00000000..bbebcdee --- /dev/null +++ b/services/activity-service/internal/storage/mysql/room_turnover_reward_migration.go @@ -0,0 +1,87 @@ +package mysql + +import "context" + +func (r *Repository) ensureRoomTurnoverRewardTables(ctx context.Context) error { + statements := []string{ + `CREATE TABLE IF NOT EXISTS room_turnover_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 '最后更新管理员', + 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 room_turnover_reward_tiers ( + tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '档位 ID', + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + tier_code VARCHAR(64) NOT NULL COMMENT '档位编码', + tier_name VARCHAR(128) NOT NULL COMMENT '档位名称', + threshold_coin_spent BIGINT NOT NULL COMMENT '命中该档需要的房间送礼金币流水', + reward_coin_amount BIGINT NOT NULL COMMENT '奖励房主金币数', + status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', + 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', + PRIMARY KEY (tier_id), + UNIQUE KEY uk_room_turnover_reward_tier_code (app_code, tier_code), + KEY idx_room_turnover_reward_tiers_match (app_code, status, threshold_coin_spent) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励档位表'`, + `CREATE TABLE IF NOT EXISTS room_turnover_reward_event_consumption ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id', + event_type VARCHAR(96) NOT NULL COMMENT '事件类型', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + coin_spent BIGINT NOT NULL COMMENT '本事件送礼金币消耗', + status VARCHAR(32) NOT NULL COMMENT '消费状态', + consumed_at_ms BIGINT NOT NULL 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, event_id), + KEY idx_room_turnover_reward_event_period (app_code, period_start_ms, room_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励事件消费幂等表'`, + `CREATE TABLE IF NOT EXISTS room_turnover_reward_progress ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束', + coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '本周期房间送礼金币流水', + last_event_at_ms 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, room_id, period_start_ms), + KEY idx_room_turnover_reward_progress_period (app_code, period_start_ms, coin_spent) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励周期聚合表'`, + `CREATE TABLE IF NOT EXISTS room_turnover_reward_settlements ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + settlement_id VARCHAR(96) NOT NULL COMMENT '结算 ID', + room_id VARCHAR(96) NOT NULL COMMENT '房间 ID', + owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '结算收款房主', + period_start_ms BIGINT NOT NULL COMMENT 'UTC 周期开始', + period_end_ms BIGINT NOT NULL COMMENT 'UTC 周期结束', + coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '周期房间流水', + tier_id BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位 ID', + tier_code VARCHAR(64) NOT NULL DEFAULT '' COMMENT '命中档位编码', + threshold_coin_spent BIGINT NOT NULL DEFAULT 0 COMMENT '命中档位阈值', + reward_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '发放金币', + status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT 'pending/granted/failed', + wallet_command_id VARCHAR(160) NOT NULL DEFAULT '' COMMENT 'wallet-service 幂等命令 ID', + wallet_transaction_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '钱包交易 ID', + failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因', + settled_at_ms 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, settlement_id), + UNIQUE KEY uk_room_turnover_reward_settlement_room_period (app_code, room_id, period_start_ms), + KEY idx_room_turnover_reward_settlement_status (app_code, status, period_start_ms, created_at_ms), + KEY idx_room_turnover_reward_settlement_owner (app_code, owner_user_id, period_start_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='房间流水奖励每周结算表'`, + } + for _, statement := range statements { + if _, err := r.db.ExecContext(ctx, statement); err != nil { + return err + } + } + return nil +} diff --git a/services/activity-service/internal/storage/mysql/room_turnover_reward_repository.go b/services/activity-service/internal/storage/mysql/room_turnover_reward_repository.go new file mode 100644 index 00000000..ced3f976 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/room_turnover_reward_repository.go @@ -0,0 +1,562 @@ +package mysql + +import ( + "context" + "database/sql" + "errors" + "strconv" + "strings" + + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/roomturnoverreward" +) + +// GetRoomTurnoverRewardConfig 读取房间流水奖励当前配置;未配置是后台首屏正常状态。 +func (r *Repository) GetRoomTurnoverRewardConfig(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, roomTurnoverRewardConfigSelectSQL()+` + WHERE app_code = ?`, + appcode.FromContext(ctx), + ) + config, err := scanRoomTurnoverRewardConfig(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Config{}, false, nil + } + if err != nil { + return domain.Config{}, false, err + } + tiers, err := r.listRoomTurnoverRewardTiers(ctx, nil) + if err != nil { + return domain.Config{}, false, err + } + config.Tiers = tiers + return config, true, nil +} + +// UpdateRoomTurnoverRewardConfig 原子替换配置档位;已生成的 settlement 保留命中档位快照。 +func (r *Repository) UpdateRoomTurnoverRewardConfig(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() }() + + if _, err := tx.ExecContext(ctx, ` + INSERT INTO room_turnover_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, + ); err != nil { + return domain.Config{}, err + } + if _, err := tx.ExecContext(ctx, ` + DELETE FROM room_turnover_reward_tiers + WHERE app_code = ?`, + appcode.FromContext(ctx), + ); err != nil { + return domain.Config{}, err + } + // 配置保存采用“配置行 upsert + 档位整组替换”,让后台表单提交成为完整快照,避免删除档位后旧行继续参与后续匹配。 + 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 room_turnover_reward_tiers ( + tier_id, app_code, tier_code, tier_name, threshold_coin_spent, + reward_coin_amount, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + tier.TierID, appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.ThresholdCoinSpent, + tier.RewardCoinAmount, tier.Status, tier.SortOrder, tier.CreatedAtMS, tier.UpdatedAtMS, + ); err != nil { + return domain.Config{}, err + } + continue + } + result, err := tx.ExecContext(ctx, ` + INSERT INTO room_turnover_reward_tiers ( + app_code, tier_code, tier_name, threshold_coin_spent, + reward_coin_amount, status, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), tier.TierCode, tier.TierName, tier.ThresholdCoinSpent, + tier.RewardCoinAmount, 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.GetRoomTurnoverRewardConfig(ctx) + if err != nil { + return domain.Config{}, err + } + if !exists { + return domain.Config{}, xerr.New(xerr.NotFound, "room turnover reward config not found") + } + return updated, nil +} + +// ConsumeRoomTurnoverGiftEvent 幂等消费 RoomGiftSent,并累加到房间所在 UTC 周期流水。 +func (r *Repository) ConsumeRoomTurnoverGiftEvent(ctx context.Context, event domain.RoomGiftEvent, periodStartMS int64, periodEndMS int64, nowMS int64) (domain.EventResult, error) { + if r == nil || r.db == nil { + return domain.EventResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.EventResult{}, err + } + defer func() { _ = tx.Rollback() }() + + result, err := tx.ExecContext(ctx, ` + INSERT IGNORE INTO room_turnover_reward_event_consumption ( + app_code, event_id, event_type, room_id, period_start_ms, coin_spent, + status, consumed_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, 'consumed', ?, ?, ?)`, + appcode.FromContext(ctx), event.EventID, event.EventType, event.RoomID, periodStartMS, event.CoinSpent, nowMS, nowMS, nowMS, + ) + if err != nil { + return domain.EventResult{}, err + } + affected, err := result.RowsAffected() + if err != nil { + return domain.EventResult{}, err + } + if affected == 0 { + // event_id 是 room outbox 事实幂等键;重复投递只提交幂等事务,不再累加 progress,保证贡献值不会翻倍。 + if err := tx.Commit(); err != nil { + return domain.EventResult{}, err + } + return domain.EventResult{EventID: event.EventID, Status: domain.EventStatusDuplicate}, nil + } + // progress 是 App H5 和结算任务共用的读模型;同一事务先落消费幂等,再按 UTC 周期原子累加房间流水。 + if _, err := tx.ExecContext(ctx, ` + INSERT INTO room_turnover_reward_progress ( + app_code, room_id, period_start_ms, period_end_ms, coin_spent, + last_event_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + coin_spent = coin_spent + VALUES(coin_spent), + period_end_ms = VALUES(period_end_ms), + last_event_at_ms = GREATEST(last_event_at_ms, VALUES(last_event_at_ms)), + updated_at_ms = VALUES(updated_at_ms)`, + appcode.FromContext(ctx), event.RoomID, periodStartMS, periodEndMS, event.CoinSpent, event.OccurredAtMS, nowMS, nowMS, + ); err != nil { + return domain.EventResult{}, err + } + if err := tx.Commit(); err != nil { + return domain.EventResult{}, err + } + return domain.EventResult{EventID: event.EventID, Status: domain.EventStatusConsumed}, nil +} + +// GetRoomTurnoverRewardProgress 返回指定房间和 UTC 周期的当前流水。 +func (r *Repository) GetRoomTurnoverRewardProgress(ctx context.Context, roomID string, periodStartMS int64) (domain.Progress, bool, error) { + if r == nil || r.db == nil { + return domain.Progress{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, roomTurnoverRewardProgressSelectSQL()+` + WHERE app_code = ? AND room_id = ? AND period_start_ms = ?`, + appcode.FromContext(ctx), strings.TrimSpace(roomID), periodStartMS, + ) + item, err := scanRoomTurnoverRewardProgress(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Progress{}, false, nil + } + return item, err == nil, err +} + +func (r *Repository) GetLatestRoomTurnoverRewardSettlement(ctx context.Context, roomID string) (domain.Settlement, bool, error) { + if r == nil || r.db == nil { + return domain.Settlement{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + // 最新结算给 H5 展示上一周期结果;按 period_start_ms 倒序而不是 status 排序,保证失败和成功都能被用户看到。 + row := r.db.QueryRowContext(ctx, roomTurnoverRewardSettlementSelectSQL()+` + WHERE app_code = ? AND room_id = ? + ORDER BY period_start_ms DESC, created_at_ms DESC + LIMIT 1`, + appcode.FromContext(ctx), strings.TrimSpace(roomID), + ) + item, err := scanRoomTurnoverRewardSettlement(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Settlement{}, false, nil + } + return item, err == nil, err +} + +// ListRoomTurnoverRewardSettlements 返回后台结算记录页;查询只命中 settlement 快照,不回扫事件或 progress。 +func (r *Repository) ListRoomTurnoverRewardSettlements(ctx context.Context, query domain.SettlementQuery) ([]domain.Settlement, int64, error) { + if r == nil || r.db == nil { + return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + // 后台列表只在 settlement 表上分页筛选;流水明细来自周期聚合快照,避免管理页回扫礼物事件。 + where := []string{"app_code = ?"} + args := []any{appcode.FromContext(ctx)} + if query.Status != "" { + where = append(where, "status = ?") + args = append(args, query.Status) + } + if strings.TrimSpace(query.RoomID) != "" { + where = append(where, "room_id = ?") + args = append(args, strings.TrimSpace(query.RoomID)) + } + if query.OwnerUserID > 0 { + where = append(where, "owner_user_id = ?") + args = append(args, query.OwnerUserID) + } + if query.PeriodStartMS > 0 { + where = append(where, "period_start_ms = ?") + args = append(args, query.PeriodStartMS) + } + clause := "WHERE " + strings.Join(where, " AND ") + var total int64 + if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM room_turnover_reward_settlements `+clause, args...).Scan(&total); err != nil { + return nil, 0, err + } + pageSize := int(query.PageSize) + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + page := int(query.Page) + if page <= 0 { + page = 1 + } + args = append(args, pageSize, (page-1)*pageSize) + rows, err := r.db.QueryContext(ctx, roomTurnoverRewardSettlementSelectSQL()+clause+` + ORDER BY period_start_ms DESC, created_at_ms DESC + LIMIT ? OFFSET ?`, args...) + if err != nil { + return nil, 0, err + } + defer rows.Close() + items, err := scanRoomTurnoverRewardSettlements(rows) + return items, total, err +} + +// ListUnsettledRoomTurnoverRewardProgress 找出上一周期有流水但还没有 settlement 的房间,用于 cron 补齐结算记录。 +func (r *Repository) ListUnsettledRoomTurnoverRewardProgress(ctx context.Context, periodStartMS int64, limit int) ([]domain.Progress, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if limit <= 0 { + limit = 100 + } + // LEFT JOIN settlement 只认领还没有结算快照的 progress;唯一键再兜底一次,防止并发 worker 同时扫描到同一房间。 + rows, err := r.db.QueryContext(ctx, roomTurnoverRewardProgressSelectSQL()+` + LEFT JOIN room_turnover_reward_settlements settlement + ON settlement.app_code = progress.app_code + AND settlement.room_id = progress.room_id + AND settlement.period_start_ms = progress.period_start_ms + WHERE progress.app_code = ? AND progress.period_start_ms = ? + AND progress.coin_spent > 0 AND settlement.settlement_id IS NULL + ORDER BY progress.coin_spent DESC, progress.room_id ASC + LIMIT ?`, + appcode.FromContext(ctx), periodStartMS, limit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanRoomTurnoverRewardProgressRows(rows) +} + +// InsertRoomTurnoverRewardSettlement 创建单房间单周期 settlement;已存在时读回原记录并返回 created=false。 +func (r *Repository) InsertRoomTurnoverRewardSettlement(ctx context.Context, settlement domain.Settlement, nowMS int64) (domain.Settlement, bool, error) { + if r == nil || r.db == nil { + return domain.Settlement{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if settlement.SettlementID == "" { + settlement.SettlementID = idgen.New("rtrsettle") + } + if settlement.WalletCommandID == "" { + settlement.WalletCommandID = walletRoomTurnoverRewardCommandID(settlement.AppCode, settlement.PeriodStartMS, settlement.RoomID) + } + settlement.CreatedAtMS = nowMS + settlement.UpdatedAtMS = nowMS + if settlement.Status == "" { + settlement.Status = domain.SettlementStatusPending + } + // room_id + period_start_ms 是业务唯一键;cron 重跑、并发 worker 或人工补偿都只能为同一房间周期保留一条 settlement。 + result, err := r.db.ExecContext(ctx, ` + INSERT IGNORE INTO room_turnover_reward_settlements ( + app_code, settlement_id, room_id, owner_user_id, period_start_ms, period_end_ms, + coin_spent, tier_id, tier_code, threshold_coin_spent, reward_coin_amount, + status, wallet_command_id, wallet_transaction_id, failure_reason, + settled_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', ?, 0, ?, ?)`, + appcode.FromContext(ctx), settlement.SettlementID, settlement.RoomID, settlement.OwnerUserID, + settlement.PeriodStartMS, settlement.PeriodEndMS, settlement.CoinSpent, settlement.TierID, + settlement.TierCode, settlement.ThresholdCoinSpent, settlement.RewardCoinAmount, + settlement.Status, settlement.WalletCommandID, settlement.FailureReason, nowMS, nowMS, + ) + if err != nil { + return domain.Settlement{}, false, err + } + affected, err := result.RowsAffected() + if err != nil { + return domain.Settlement{}, false, err + } + item, exists, err := r.getRoomTurnoverRewardSettlementByRoomPeriod(ctx, settlement.RoomID, settlement.PeriodStartMS) + return item, affected > 0 && exists, err +} + +// ListPendingRoomTurnoverRewardSettlements 返回等待发奖的 settlement;按老周期优先处理,避免历史失败恢复后长期排队。 +func (r *Repository) ListPendingRoomTurnoverRewardSettlements(ctx context.Context, limit int) ([]domain.Settlement, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if limit <= 0 { + limit = 100 + } + rows, err := r.db.QueryContext(ctx, roomTurnoverRewardSettlementSelectSQL()+` + WHERE app_code = ? AND status = ? + ORDER BY period_start_ms ASC, created_at_ms ASC + LIMIT ?`, + appcode.FromContext(ctx), domain.SettlementStatusPending, limit, + ) + if err != nil { + return nil, err + } + defer rows.Close() + return scanRoomTurnoverRewardSettlements(rows) +} + +// GetRoomTurnoverRewardSettlement 按后台传入的 settlement_id 读取单条结算记录。 +func (r *Repository) GetRoomTurnoverRewardSettlement(ctx context.Context, settlementID string) (domain.Settlement, bool, error) { + if r == nil || r.db == nil { + return domain.Settlement{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, roomTurnoverRewardSettlementSelectSQL()+` + WHERE app_code = ? AND settlement_id = ?`, + appcode.FromContext(ctx), strings.TrimSpace(settlementID), + ) + item, err := scanRoomTurnoverRewardSettlement(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Settlement{}, false, nil + } + return item, err == nil, err +} + +// ResetRoomTurnoverRewardSettlementForRetry 把失败记录重新放回 pending,并在 retry 时写入最新可用房主。 +func (r *Repository) ResetRoomTurnoverRewardSettlementForRetry(ctx context.Context, settlementID string, ownerUserID int64, nowMS int64) (domain.Settlement, error) { + if r == nil || r.db == nil { + return domain.Settlement{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if _, err := r.db.ExecContext(ctx, ` + UPDATE room_turnover_reward_settlements + SET status = ?, owner_user_id = ?, failure_reason = '', updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ? AND status <> ?`, + domain.SettlementStatusPending, ownerUserID, nowMS, appcode.FromContext(ctx), strings.TrimSpace(settlementID), domain.SettlementStatusGranted, + ); err != nil { + return domain.Settlement{}, err + } + // retry 只能把未发奖记录重新放回 pending;已经 granted 的记录不会被改回去,防止后台误点造成二次发奖。 + item, exists, err := r.GetRoomTurnoverRewardSettlement(ctx, settlementID) + if err != nil { + return domain.Settlement{}, err + } + if !exists { + return domain.Settlement{}, xerr.New(xerr.NotFound, "room turnover reward settlement not found") + } + return item, nil +} + +// MarkRoomTurnoverRewardSettlementGranted 记录钱包成功入账结果,是 activity 侧发奖状态的最终成功态。 +func (r *Repository) MarkRoomTurnoverRewardSettlementGranted(ctx context.Context, settlementID string, walletTransactionID string, grantedAtMS int64) (domain.Settlement, error) { + if r == nil || r.db == nil { + return domain.Settlement{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + // 只有钱包 RPC 成功后才写 granted,并保存 wallet_transaction_id,后台和对账都以这条链路追踪真实入账。 + if _, err := r.db.ExecContext(ctx, ` + UPDATE room_turnover_reward_settlements + SET status = ?, wallet_transaction_id = ?, failure_reason = '', settled_at_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ?`, + domain.SettlementStatusGranted, walletTransactionID, grantedAtMS, grantedAtMS, appcode.FromContext(ctx), strings.TrimSpace(settlementID), + ); err != nil { + return domain.Settlement{}, err + } + item, exists, err := r.GetRoomTurnoverRewardSettlement(ctx, settlementID) + if err != nil { + return domain.Settlement{}, err + } + if !exists { + return domain.Settlement{}, xerr.New(xerr.NotFound, "room turnover reward settlement not found") + } + return item, nil +} + +// MarkRoomTurnoverRewardSettlementFailed 写入可展示、可 retry 的失败原因。 +func (r *Repository) MarkRoomTurnoverRewardSettlementFailed(ctx context.Context, settlementID string, reason string, nowMS int64) error { + if r == nil || r.db == nil { + return xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + // 失败标记不会覆盖 granted,避免钱包已成功但 activity-service 更新重试时被后续错误回写成失败。 + _, err := r.db.ExecContext(ctx, ` + UPDATE room_turnover_reward_settlements + SET status = ?, failure_reason = ?, updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ? AND status <> ?`, + domain.SettlementStatusFailed, trimFailureReason(reason), nowMS, appcode.FromContext(ctx), strings.TrimSpace(settlementID), domain.SettlementStatusGranted, + ) + return err +} + +func (r *Repository) getRoomTurnoverRewardSettlementByRoomPeriod(ctx context.Context, roomID string, periodStartMS int64) (domain.Settlement, bool, error) { + row := r.db.QueryRowContext(ctx, roomTurnoverRewardSettlementSelectSQL()+` + WHERE app_code = ? AND room_id = ? AND period_start_ms = ?`, + appcode.FromContext(ctx), strings.TrimSpace(roomID), periodStartMS, + ) + item, err := scanRoomTurnoverRewardSettlement(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Settlement{}, false, nil + } + return item, err == nil, err +} + +func roomTurnoverRewardConfigSelectSQL() string { + return `SELECT app_code, enabled, updated_by_admin_id, created_at_ms, updated_at_ms + FROM room_turnover_reward_configs ` +} + +func roomTurnoverRewardTierSelectSQL() string { + return `SELECT tier_id, app_code, tier_code, tier_name, threshold_coin_spent, + reward_coin_amount, status, sort_order, created_at_ms, updated_at_ms + FROM room_turnover_reward_tiers ` +} + +func roomTurnoverRewardProgressSelectSQL() string { + return `SELECT progress.app_code, progress.room_id, progress.period_start_ms, progress.period_end_ms, + progress.coin_spent, progress.last_event_at_ms, progress.created_at_ms, progress.updated_at_ms + FROM room_turnover_reward_progress progress ` +} + +func roomTurnoverRewardSettlementSelectSQL() string { + return `SELECT app_code, settlement_id, room_id, owner_user_id, period_start_ms, period_end_ms, + coin_spent, tier_id, tier_code, threshold_coin_spent, reward_coin_amount, + status, wallet_command_id, wallet_transaction_id, failure_reason, + settled_at_ms, created_at_ms, updated_at_ms + FROM room_turnover_reward_settlements ` +} + +type roomTurnoverRewardConfigScanner interface { + Scan(dest ...any) error +} + +func scanRoomTurnoverRewardConfig(scanner roomTurnoverRewardConfigScanner) (domain.Config, error) { + var item domain.Config + err := scanner.Scan(&item.AppCode, &item.Enabled, &item.UpdatedByAdminID, &item.CreatedAtMS, &item.UpdatedAtMS) + return item, err +} + +func (r *Repository) listRoomTurnoverRewardTiers(ctx context.Context, tx *sql.Tx) ([]domain.Tier, error) { + query := roomTurnoverRewardTierSelectSQL() + ` + WHERE app_code = ? + ORDER BY sort_order ASC, threshold_coin_spent ASC, tier_id ASC` + var rows *sql.Rows + var err error + if tx != nil { + rows, err = tx.QueryContext(ctx, query, appcode.FromContext(ctx)) + } else { + rows, err = r.db.QueryContext(ctx, query, appcode.FromContext(ctx)) + } + if err != nil { + return nil, err + } + defer rows.Close() + items := make([]domain.Tier, 0) + for rows.Next() { + var item domain.Tier + var app string + if err := rows.Scan(&item.TierID, &app, &item.TierCode, &item.TierName, &item.ThresholdCoinSpent, &item.RewardCoinAmount, &item.Status, &item.SortOrder, &item.CreatedAtMS, &item.UpdatedAtMS); err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +type roomTurnoverRewardProgressScanner interface { + Scan(dest ...any) error +} + +func scanRoomTurnoverRewardProgress(scanner roomTurnoverRewardProgressScanner) (domain.Progress, error) { + var item domain.Progress + err := scanner.Scan(&item.AppCode, &item.RoomID, &item.PeriodStartMS, &item.PeriodEndMS, &item.CoinSpent, &item.LastEventAtMS, &item.CreatedAtMS, &item.UpdatedAtMS) + return item, err +} + +func scanRoomTurnoverRewardProgressRows(rows *sql.Rows) ([]domain.Progress, error) { + items := make([]domain.Progress, 0) + for rows.Next() { + item, err := scanRoomTurnoverRewardProgress(rows) + if err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +type roomTurnoverRewardSettlementScanner interface { + Scan(dest ...any) error +} + +func scanRoomTurnoverRewardSettlement(scanner roomTurnoverRewardSettlementScanner) (domain.Settlement, error) { + var item domain.Settlement + err := scanner.Scan( + &item.AppCode, &item.SettlementID, &item.RoomID, &item.OwnerUserID, + &item.PeriodStartMS, &item.PeriodEndMS, &item.CoinSpent, + &item.TierID, &item.TierCode, &item.ThresholdCoinSpent, &item.RewardCoinAmount, + &item.Status, &item.WalletCommandID, &item.WalletTransactionID, &item.FailureReason, + &item.SettledAtMS, &item.CreatedAtMS, &item.UpdatedAtMS, + ) + return item, err +} + +func scanRoomTurnoverRewardSettlements(rows *sql.Rows) ([]domain.Settlement, error) { + items := make([]domain.Settlement, 0) + for rows.Next() { + item, err := scanRoomTurnoverRewardSettlement(rows) + if err != nil { + return nil, err + } + items = append(items, item) + } + return items, rows.Err() +} + +func walletRoomTurnoverRewardCommandID(app string, periodStartMS int64, roomID string) string { + return "room_turnover_reward:" + appcode.Normalize(app) + ":" + int64String(periodStartMS) + ":" + strings.TrimSpace(roomID) +} + +func int64String(value int64) string { + return strconv.FormatInt(value, 10) +} + +func trimFailureReason(reason string) string { + reason = strings.TrimSpace(reason) + if len(reason) > 512 { + return reason[:512] + } + return reason +} diff --git a/services/activity-service/internal/storage/mysql/weekly_star_migration.go b/services/activity-service/internal/storage/mysql/weekly_star_migration.go new file mode 100644 index 00000000..74be0013 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/weekly_star_migration.go @@ -0,0 +1,96 @@ +package mysql + +import "context" + +func (r *Repository) ensureWeeklyStarTables(ctx context.Context) error { + statements := []string{ + `CREATE TABLE IF NOT EXISTS weekly_star_cycles ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + activity_code VARCHAR(64) NOT NULL DEFAULT 'weekly_star' COMMENT '活动编码', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域 ID,0 表示默认配置', + title VARCHAR(128) NOT NULL DEFAULT '' COMMENT '周期标题', + status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '状态', + start_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效开始,包含', + end_ms BIGINT NOT NULL COMMENT 'UTC epoch ms 生效结束,不包含', + created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建管理员', + updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新管理员', + settled_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '结算完成时间', + locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '结算 worker 锁', + lock_until_ms 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, cycle_id), + KEY idx_weekly_star_cycle_current (app_code, activity_code, status, region_id, start_ms, end_ms), + KEY idx_weekly_star_cycle_due (app_code, activity_code, status, end_ms, lock_until_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星指定礼物积分周期'`, + `CREATE TABLE IF NOT EXISTS weekly_star_cycle_gifts ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + gift_id VARCHAR(96) NOT NULL COMMENT '参与计分礼物 ID', + sort_order INT NOT NULL DEFAULT 0 COMMENT '展示顺序', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, cycle_id, gift_id), + KEY idx_weekly_star_gift_match (app_code, gift_id, cycle_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期指定礼物'`, + `CREATE TABLE IF NOT EXISTS weekly_star_cycle_rewards ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + rank_no INT NOT NULL COMMENT '排名,1/2/3', + resource_group_id BIGINT NOT NULL 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, cycle_id, rank_no) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星周期 Top 奖励'`, + `CREATE TABLE IF NOT EXISTS weekly_star_user_scores ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + user_id BIGINT NOT NULL COMMENT '用户 ID', + score BIGINT NOT NULL DEFAULT 0 COMMENT '累计积分,等于活动礼物消耗金币', + first_scored_at_ms BIGINT NOT NULL COMMENT '首次得分时间', + last_scored_at_ms BIGINT NOT NULL 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, cycle_id, user_id), + KEY idx_weekly_star_score_rank (app_code, cycle_id, score, first_scored_at_ms, user_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星用户积分榜'`, + `CREATE TABLE IF NOT EXISTS weekly_star_score_events ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + source_event_id VARCHAR(128) NOT NULL COMMENT 'room-service outbox event_id', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + user_id BIGINT NOT NULL COMMENT '送礼用户 ID', + gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID', + score_delta BIGINT NOT NULL COMMENT '本次增加积分', + occurred_at_ms BIGINT NOT NULL COMMENT '事件发生时间,UTC epoch ms', + created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms', + PRIMARY KEY (app_code, source_event_id), + KEY idx_weekly_star_score_event_cycle (app_code, cycle_id, user_id, occurred_at_ms) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星送礼积分事件幂等表'`, + `CREATE TABLE IF NOT EXISTS weekly_star_settlements ( + app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码', + settlement_id VARCHAR(96) NOT NULL COMMENT '周星结算 ID', + cycle_id VARCHAR(96) NOT NULL COMMENT '周星周期 ID', + rank_no INT NOT NULL COMMENT '排名,1/2/3', + user_id BIGINT NOT NULL COMMENT '获奖用户 ID', + score BIGINT NOT NULL DEFAULT 0 COMMENT '结算积分', + resource_group_id BIGINT NOT NULL COMMENT '奖励资源组 ID', + wallet_command_id VARCHAR(128) NOT NULL COMMENT 'wallet 幂等命令', + wallet_grant_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'wallet grant ID', + status VARCHAR(32) NOT NULL DEFAULT 'pending' COMMENT '发放状态', + failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因', + attempt_count 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', + PRIMARY KEY (app_code, settlement_id), + UNIQUE KEY uk_weekly_star_settlement_rank (app_code, cycle_id, rank_no), + UNIQUE KEY uk_weekly_star_wallet_command (app_code, wallet_command_id), + KEY idx_weekly_star_settlement_cycle (app_code, cycle_id, status) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='周星 Top 奖励结算'`, + } + for _, statement := range statements { + if _, err := r.db.ExecContext(ctx, statement); err != nil { + return err + } + } + return nil +} diff --git a/services/activity-service/internal/storage/mysql/weekly_star_repository.go b/services/activity-service/internal/storage/mysql/weekly_star_repository.go new file mode 100644 index 00000000..42f8a243 --- /dev/null +++ b/services/activity-service/internal/storage/mysql/weekly_star_repository.go @@ -0,0 +1,876 @@ +package mysql + +import ( + "context" + "database/sql" + "errors" + "fmt" + "strconv" + "strings" + "time" + + "hyapp/pkg/appcode" + "hyapp/pkg/idgen" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/weeklystar" +) + +// ListWeeklyStarCycles returns admin-configured cycles with gifts and rewards attached for editing. +func (r *Repository) ListWeeklyStarCycles(ctx context.Context, query domain.ListQuery) ([]domain.Cycle, int64, error) { + if r == nil || r.db == nil { + return nil, 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + where, args := weeklyStarCycleWhere(ctx, query) + var total int64 + if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM weekly_star_cycles `+where, args...).Scan(&total); err != nil { + return nil, 0, err + } + pageSize := normalizePageSize(query.PageSize) + page := query.Page + if page <= 0 { + page = 1 + } + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + FROM weekly_star_cycles `+where+` + ORDER BY start_ms DESC, region_id ASC, cycle_id DESC + LIMIT ? OFFSET ?`, append(args, int(pageSize), int((page-1)*pageSize))...) + if err != nil { + return nil, 0, err + } + defer rows.Close() + cycles := make([]domain.Cycle, 0) + for rows.Next() { + cycle, scanErr := scanWeeklyStarCycle(rows) + if scanErr != nil { + return nil, 0, scanErr + } + cycles = append(cycles, cycle) + } + if err := rows.Err(); err != nil { + return nil, 0, err + } + if err := r.attachWeeklyStarChildren(ctx, cycles); err != nil { + return nil, 0, err + } + return cycles, total, nil +} + +// GetWeeklyStarCycle returns the authoritative cycle row and its editable child rows. +func (r *Repository) GetWeeklyStarCycle(ctx context.Context, cycleID string) (domain.Cycle, error) { + if r == nil || r.db == nil { + return domain.Cycle{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + cycle, err := r.getWeeklyStarCycle(ctx, r.db, cycleID) + if err != nil { + return domain.Cycle{}, err + } + cycles := []domain.Cycle{cycle} + if err := r.attachWeeklyStarChildren(ctx, cycles); err != nil { + return domain.Cycle{}, err + } + return cycles[0], nil +} + +// UpsertWeeklyStarCycle replaces a full cycle configuration in one transaction so gifts and rewards stay consistent. +func (r *Repository) UpsertWeeklyStarCycle(ctx context.Context, command domain.CycleCommand, nowMS int64) (domain.Cycle, bool, error) { + if r == nil || r.db == nil { + return domain.Cycle{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.Cycle{}, false, err + } + defer tx.Rollback() + cycle := command.Cycle + cycle.AppCode = appcode.FromContext(ctx) + cycle.ActivityCode = domain.ActivityCode + if cycle.Status == "" { + cycle.Status = domain.StatusDraft + } + created := strings.TrimSpace(cycle.CycleID) == "" + if !created { + if _, err := r.getWeeklyStarCycle(ctx, tx, cycle.CycleID); err != nil { + return domain.Cycle{}, false, err + } + } else if !command.RequireNewRecord { + return domain.Cycle{}, false, xerr.New(xerr.InvalidArgument, "cycle_id is required") + } + if created { + cycle.CycleID = idgen.New("wstar") + cycle.CreatedAtMS = nowMS + cycle.CreatedByAdminID = command.OperatorAdminID + } + cycle.UpdatedAtMS = nowMS + cycle.UpdatedByAdminID = command.OperatorAdminID + if err := r.checkWeeklyStarCycleOverlap(ctx, tx, cycle); err != nil { + return domain.Cycle{}, false, err + } + if created { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_cycles ( + app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?, ?)`, + cycle.AppCode, cycle.CycleID, cycle.ActivityCode, cycle.RegionID, cycle.Title, cycle.Status, cycle.StartMS, cycle.EndMS, + cycle.CreatedByAdminID, cycle.UpdatedByAdminID, cycle.CreatedAtMS, cycle.UpdatedAtMS, + ); err != nil { + return domain.Cycle{}, false, err + } + } else { + if _, err := tx.ExecContext(ctx, ` + UPDATE weekly_star_cycles + SET region_id = ?, title = ?, status = ?, start_ms = ?, end_ms = ?, + updated_by_admin_id = ?, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + cycle.RegionID, cycle.Title, cycle.Status, cycle.StartMS, cycle.EndMS, + cycle.UpdatedByAdminID, cycle.UpdatedAtMS, cycle.AppCode, cycle.CycleID, + ); err != nil { + return domain.Cycle{}, false, err + } + } + if _, err := tx.ExecContext(ctx, `DELETE FROM weekly_star_cycle_gifts WHERE app_code = ? AND cycle_id = ?`, cycle.AppCode, cycle.CycleID); err != nil { + return domain.Cycle{}, false, err + } + for index, gift := range cycle.Gifts { + sortOrder := gift.SortOrder + if sortOrder <= 0 { + sortOrder = int32(index + 1) + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_cycle_gifts (app_code, cycle_id, gift_id, sort_order, created_at_ms) + VALUES (?, ?, ?, ?, ?)`, + cycle.AppCode, cycle.CycleID, gift.GiftID, sortOrder, nowMS, + ); err != nil { + return domain.Cycle{}, false, err + } + } + if _, err := tx.ExecContext(ctx, `DELETE FROM weekly_star_cycle_rewards WHERE app_code = ? AND cycle_id = ?`, cycle.AppCode, cycle.CycleID); err != nil { + return domain.Cycle{}, false, err + } + for _, reward := range cycle.Rewards { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_cycle_rewards (app_code, cycle_id, rank_no, resource_group_id, created_at_ms, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?)`, + cycle.AppCode, cycle.CycleID, reward.RankNo, reward.ResourceGroupID, nowMS, nowMS, + ); err != nil { + return domain.Cycle{}, false, err + } + } + if err := tx.Commit(); err != nil { + return domain.Cycle{}, false, err + } + stored, err := r.GetWeeklyStarCycle(ctx, cycle.CycleID) + return stored, created, err +} + +// SetWeeklyStarCycleStatus changes visibility without mutating gifts, rewards, or score facts. +func (r *Repository) SetWeeklyStarCycleStatus(ctx context.Context, cycleID string, status string, operatorAdminID int64, nowMS int64) (domain.Cycle, error) { + if r == nil || r.db == nil { + return domain.Cycle{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.Cycle{}, err + } + defer tx.Rollback() + cycle, err := r.getWeeklyStarCycle(ctx, tx, cycleID) + if err != nil { + return domain.Cycle{}, err + } + next := cycle + next.Status = status + if err := r.checkWeeklyStarCycleOverlap(ctx, tx, next); err != nil { + return domain.Cycle{}, err + } + if _, err := tx.ExecContext(ctx, ` + UPDATE weekly_star_cycles + SET status = ?, updated_by_admin_id = ?, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + status, operatorAdminID, nowMS, appcode.FromContext(ctx), cycleID, + ); err != nil { + return domain.Cycle{}, err + } + if err := tx.Commit(); err != nil { + return domain.Cycle{}, err + } + return r.GetWeeklyStarCycle(ctx, cycleID) +} + +// FindCurrentWeeklyStarCycle resolves the active concrete-region cycle first and falls back to region 0. +func (r *Repository) FindCurrentWeeklyStarCycle(ctx context.Context, regionID int64, nowMS int64) (domain.Cycle, bool, error) { + if r == nil || r.db == nil { + return domain.Cycle{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + row := r.db.QueryRowContext(ctx, ` + SELECT app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + FROM weekly_star_cycles + WHERE app_code = ? AND activity_code = ? AND status = ? AND start_ms <= ? AND end_ms > ? + AND region_id IN (?, 0) + ORDER BY CASE WHEN region_id = ? THEN 0 ELSE 1 END, start_ms DESC, updated_at_ms DESC + LIMIT 1`, + appcode.FromContext(ctx), domain.ActivityCode, domain.StatusActive, nowMS, nowMS, regionID, regionID, + ) + cycle, err := scanWeeklyStarCycle(row) + if err != nil { + if errors.Is(err, sql.ErrNoRows) { + return domain.Cycle{}, false, nil + } + return domain.Cycle{}, false, err + } + cycles := []domain.Cycle{cycle} + if err := r.attachWeeklyStarChildren(ctx, cycles); err != nil { + return domain.Cycle{}, false, err + } + return cycles[0], true, nil +} + +// ConsumeWeeklyStarGiftEvent stores source-event idempotency before adding the score delta. +func (r *Repository) ConsumeWeeklyStarGiftEvent(ctx context.Context, event domain.GiftEvent, nowMS int64) (domain.EventResult, error) { + if r == nil || r.db == nil { + return domain.EventResult{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return domain.EventResult{}, err + } + defer tx.Rollback() + cycle, ok, err := r.findCurrentWeeklyStarCycleForGift(ctx, tx, event.RegionID, event.GiftID, event.OccurredAtMS) + if err != nil { + return domain.EventResult{}, err + } + if !ok { + return domain.EventResult{EventID: event.EventID, Status: domain.EventStatusSkipped}, nil + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_score_events ( + app_code, source_event_id, cycle_id, user_id, gift_id, score_delta, occurred_at_ms, created_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + appcode.FromContext(ctx), event.EventID, cycle.CycleID, event.UserID, event.GiftID, event.ScoreDelta, event.OccurredAtMS, nowMS, + ); err != nil { + if isMySQLDuplicate(err) { + return domain.EventResult{EventID: event.EventID, Status: domain.EventStatusDuplicate, CycleID: cycle.CycleID}, nil + } + return domain.EventResult{}, err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_user_scores ( + app_code, cycle_id, user_id, score, first_scored_at_ms, last_scored_at_ms, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + score = score + VALUES(score), + first_scored_at_ms = LEAST(first_scored_at_ms, VALUES(first_scored_at_ms)), + last_scored_at_ms = GREATEST(last_scored_at_ms, VALUES(last_scored_at_ms)), + updated_at_ms = VALUES(updated_at_ms)`, + appcode.FromContext(ctx), cycle.CycleID, event.UserID, event.ScoreDelta, event.OccurredAtMS, event.OccurredAtMS, nowMS, nowMS, + ); err != nil { + return domain.EventResult{}, err + } + if err := tx.Commit(); err != nil { + return domain.EventResult{}, err + } + return domain.EventResult{EventID: event.EventID, Status: domain.EventStatusConsumed, CycleID: cycle.CycleID, ScoreDelta: event.ScoreDelta}, nil +} + +// ListWeeklyStarLeaderboard returns ranked score rows with stable pagination by offset token. +func (r *Repository) ListWeeklyStarLeaderboard(ctx context.Context, cycleID string, regionID int64, pageSize int32, pageToken string, nowMS int64) (domain.Cycle, []domain.LeaderboardEntry, string, int64, error) { + if r == nil || r.db == nil { + return domain.Cycle{}, nil, "", 0, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + var cycle domain.Cycle + var err error + if strings.TrimSpace(cycleID) == "" { + var ok bool + cycle, ok, err = r.FindCurrentWeeklyStarCycle(ctx, regionID, nowMS) + if err != nil || !ok { + return domain.Cycle{}, nil, "", 0, err + } + } else { + cycle, err = r.GetWeeklyStarCycle(ctx, cycleID) + if err != nil { + return domain.Cycle{}, nil, "", 0, err + } + } + size := int(normalizePageSize(pageSize)) + offset := parseWeeklyStarPageToken(pageToken) + var total int64 + if err := r.db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM weekly_star_user_scores WHERE app_code = ? AND cycle_id = ?`, + appcode.FromContext(ctx), cycle.CycleID, + ).Scan(&total); err != nil { + return domain.Cycle{}, nil, "", 0, err + } + rows, err := r.db.QueryContext(ctx, ` + SELECT user_id, score, first_scored_at_ms, last_scored_at_ms + FROM weekly_star_user_scores + WHERE app_code = ? AND cycle_id = ? + ORDER BY score DESC, first_scored_at_ms ASC, user_id ASC + LIMIT ? OFFSET ?`, + appcode.FromContext(ctx), cycle.CycleID, size, offset, + ) + if err != nil { + return domain.Cycle{}, nil, "", 0, err + } + defer rows.Close() + entries := make([]domain.LeaderboardEntry, 0, size) + for rows.Next() { + var entry domain.LeaderboardEntry + entry.RankNo = int32(offset + len(entries) + 1) + if err := rows.Scan(&entry.UserID, &entry.Score, &entry.FirstScoredAtMS, &entry.LastScoredAtMS); err != nil { + return domain.Cycle{}, nil, "", 0, err + } + entries = append(entries, entry) + } + if err := rows.Err(); err != nil { + return domain.Cycle{}, nil, "", 0, err + } + nextToken := "" + if int64(offset+len(entries)) < total { + nextToken = strconv.Itoa(offset + len(entries)) + } + return cycle, entries, nextToken, total, nil +} + +// GetWeeklyStarUserEntry computes the user's rank using the same score/first-time/user-id ordering as the leaderboard. +func (r *Repository) GetWeeklyStarUserEntry(ctx context.Context, cycleID string, userID int64) (domain.LeaderboardEntry, bool, error) { + if r == nil || r.db == nil { + return domain.LeaderboardEntry{}, false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + var entry domain.LeaderboardEntry + if err := r.db.QueryRowContext(ctx, ` + SELECT user_id, score, first_scored_at_ms, last_scored_at_ms + FROM weekly_star_user_scores + WHERE app_code = ? AND cycle_id = ? AND user_id = ?`, + appcode.FromContext(ctx), cycleID, userID, + ).Scan(&entry.UserID, &entry.Score, &entry.FirstScoredAtMS, &entry.LastScoredAtMS); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return domain.LeaderboardEntry{}, false, nil + } + return domain.LeaderboardEntry{}, false, err + } + if err := r.db.QueryRowContext(ctx, ` + SELECT COUNT(*) + 1 + FROM weekly_star_user_scores + WHERE app_code = ? AND cycle_id = ? + AND (score > ? OR (score = ? AND first_scored_at_ms < ?) OR (score = ? AND first_scored_at_ms = ? AND user_id < ?))`, + appcode.FromContext(ctx), cycleID, entry.Score, entry.Score, entry.FirstScoredAtMS, entry.Score, entry.FirstScoredAtMS, userID, + ).Scan(&entry.RankNo); err != nil { + return domain.LeaderboardEntry{}, false, err + } + return entry, true, nil +} + +// ListWeeklyStarHistory returns completed cycles, prioritizing a concrete region over default when both exist. +func (r *Repository) ListWeeklyStarHistory(ctx context.Context, regionID int64, limit int32, nowMS int64) ([]domain.HistoryCycle, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if limit <= 0 { + limit = 10 + } + if limit > 50 { + limit = 50 + } + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + FROM weekly_star_cycles + WHERE app_code = ? AND activity_code = ? AND status = ? AND region_id IN (?, 0) + ORDER BY end_ms DESC, CASE WHEN region_id = ? THEN 0 ELSE 1 END, cycle_id DESC + LIMIT ?`, + appcode.FromContext(ctx), domain.ActivityCode, domain.StatusSettled, regionID, regionID, int(limit), + ) + if err != nil { + return nil, err + } + defer rows.Close() + history := make([]domain.HistoryCycle, 0) + for rows.Next() { + cycle, scanErr := scanWeeklyStarCycle(rows) + if scanErr != nil { + return nil, scanErr + } + _, entries, _, _, listErr := r.ListWeeklyStarLeaderboard(ctx, cycle.CycleID, regionID, 3, "", nowMS) + if listErr != nil { + return nil, listErr + } + history = append(history, domain.HistoryCycle{Cycle: cycle, TopEntries: entries}) + } + return history, rows.Err() +} + +// ListWeeklyStarSettlements returns the wallet grant jobs created for a cycle settlement. +func (r *Repository) ListWeeklyStarSettlements(ctx context.Context, cycleID string) ([]domain.Settlement, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, settlement_id, cycle_id, rank_no, user_id, score, resource_group_id, + wallet_command_id, wallet_grant_id, status, failure_reason, attempt_count, created_at_ms, updated_at_ms + FROM weekly_star_settlements + WHERE app_code = ? AND cycle_id = ? + ORDER BY rank_no ASC`, + appcode.FromContext(ctx), cycleID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + settlements := make([]domain.Settlement, 0) + for rows.Next() { + settlement, scanErr := scanWeeklyStarSettlement(rows) + if scanErr != nil { + return nil, scanErr + } + settlements = append(settlements, settlement) + } + return settlements, rows.Err() +} + +// ClaimDueWeeklyStarCycles locks ended cycles so only one cron worker prepares their Top rewards. +// 这里允许认领 active 到期周期,也允许认领锁过期的 settling 周期;后者用于 worker 崩溃后的自动恢复。 +// FOR UPDATE SKIP LOCKED 保证多 cron worker 并发时互不等待,每个周期最多被一个事务改成 settling。 +func (r *Repository) ClaimDueWeeklyStarCycles(ctx context.Context, workerID string, nowMS int64, lockTTL time.Duration, batchSize int32) ([]domain.Cycle, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + if batchSize <= 0 { + batchSize = 50 + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer tx.Rollback() + rows, err := tx.QueryContext(ctx, ` + SELECT app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + FROM weekly_star_cycles + WHERE app_code = ? AND activity_code = ? AND end_ms <= ? + AND ((status = ?) OR (status = ? AND lock_until_ms <= ?)) + ORDER BY end_ms ASC, cycle_id ASC + LIMIT ? FOR UPDATE SKIP LOCKED`, + appcode.FromContext(ctx), domain.ActivityCode, nowMS, domain.StatusActive, domain.StatusSettling, nowMS, int(batchSize), + ) + if err != nil { + return nil, err + } + // go-sql-driver/mysql 不支持在同一个连接还持有未关闭 rows 时继续执行下一条语句。 + // 所以先把待认领周期完整读入内存并显式 Close,再执行后续 UPDATE,避免出现 driver: bad connection。 + cycles := make([]domain.Cycle, 0) + for rows.Next() { + cycle, scanErr := scanWeeklyStarCycle(rows) + if scanErr != nil { + return nil, scanErr + } + cycles = append(cycles, cycle) + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return nil, err + } + if err := rows.Close(); err != nil { + return nil, err + } + lockUntil := nowMS + lockTTL.Milliseconds() + for _, cycle := range cycles { + // 只更新本事务已经 FOR UPDATE 锁住的行;lock_until_ms 是恢复窗口,不是业务结束时间。 + if _, err := tx.ExecContext(ctx, ` + UPDATE weekly_star_cycles + SET status = ?, locked_by = ?, lock_until_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + domain.StatusSettling, workerID, lockUntil, nowMS, appcode.FromContext(ctx), cycle.CycleID, + ); err != nil { + return nil, err + } + } + if err := tx.Commit(); err != nil { + return nil, err + } + return cycles, nil +} + +// PrepareWeeklyStarSettlements materializes Top1/Top2/Top3 exactly once before wallet grants are attempted. +// 第一次进入时把当前榜单固化为 weekly_star_settlements,之后重试只读取 pending/failed 记录。 +// 这保证周期结束后的 Top3 快照不会因为迟到事件、重跑 cron 或后台刷新而变化。 +func (r *Repository) PrepareWeeklyStarSettlements(ctx context.Context, cycleID string, nowMS int64) ([]domain.Settlement, error) { + if r == nil || r.db == nil { + return nil, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return nil, err + } + defer tx.Rollback() + var existing int + if err := tx.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM weekly_star_settlements WHERE app_code = ? AND cycle_id = ?`, + appcode.FromContext(ctx), cycleID, + ).Scan(&existing); err != nil { + return nil, err + } + if existing == 0 { + // settlement 表以 cycle_id+rank_no 做唯一约束;即使 cron 重入,也只会固化一次 Top 排名。 + if err := r.insertWeeklyStarSettlements(ctx, tx, cycleID, nowMS); err != nil { + return nil, err + } + } + rows, err := tx.QueryContext(ctx, ` + SELECT app_code, settlement_id, cycle_id, rank_no, user_id, score, resource_group_id, + wallet_command_id, wallet_grant_id, status, failure_reason, attempt_count, created_at_ms, updated_at_ms + FROM weekly_star_settlements + WHERE app_code = ? AND cycle_id = ? AND status IN (?, ?) + ORDER BY rank_no ASC FOR UPDATE`, + appcode.FromContext(ctx), cycleID, domain.SettlementStatusPending, domain.SettlementStatusFailed, + ) + if err != nil { + return nil, err + } + // 这里同样必须先读完并关闭 rows,再把选中的 settlement 更新为 running。 + // 否则同一事务中的 UPDATE 会复用被 rows 占用的 MySQL 连接,导致 driver: bad connection。 + settlements := make([]domain.Settlement, 0) + for rows.Next() { + settlement, scanErr := scanWeeklyStarSettlement(rows) + if scanErr != nil { + return nil, scanErr + } + settlements = append(settlements, settlement) + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return nil, err + } + if err := rows.Close(); err != nil { + return nil, err + } + for _, settlement := range settlements { + // running 只表示本轮 cron 正在尝试发放;失败会回到 failed,成功会变成 granted。 + // attempt_count 在状态切换时递增,方便后台排查反复失败的奖励。 + if _, err := tx.ExecContext(ctx, ` + UPDATE weekly_star_settlements + SET status = ?, attempt_count = attempt_count + 1, updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ?`, + domain.SettlementStatusRunning, nowMS, appcode.FromContext(ctx), settlement.SettlementID, + ); err != nil { + return nil, err + } + } + if err := tx.Commit(); err != nil { + return nil, err + } + return settlements, nil +} + +// MarkWeeklyStarSettlementGranted records the wallet grant id after wallet-service idempotency succeeds. +// wallet_grant_id 是后续审计和客服排障的跨服务凭证,不能只依赖 activity 侧 settlement_id。 +func (r *Repository) MarkWeeklyStarSettlementGranted(ctx context.Context, settlementID string, walletGrantID 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 weekly_star_settlements + SET status = ?, wallet_grant_id = ?, failure_reason = '', updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ?`, + domain.SettlementStatusGranted, walletGrantID, nowMS, appcode.FromContext(ctx), settlementID, + ) + return err +} + +// MarkWeeklyStarSettlementFailed unlocks one grant job for a later cron retry. +// failed 不是终态;下一轮 PrepareWeeklyStarSettlements 会重新锁定它,并用同一 wallet_command_id 继续重试。 +func (r *Repository) MarkWeeklyStarSettlementFailed(ctx context.Context, settlementID string, reason 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 weekly_star_settlements + SET status = ?, failure_reason = ?, updated_at_ms = ? + WHERE app_code = ? AND settlement_id = ?`, + domain.SettlementStatusFailed, truncateWeeklyStarFailure(reason), nowMS, appcode.FromContext(ctx), settlementID, + ) + return err +} + +// FinishWeeklyStarCycleIfComplete marks a cycle settled only after every materialized grant succeeded. +// 只要存在非 granted 的 settlement,就释放 cycle 锁但保持 settling,等待下一轮 cron 补偿。 +// 全部发放成功后才写 settled_at_ms,H5 历史榜和后台结算记录才会把这个周期视为已完结。 +func (r *Repository) FinishWeeklyStarCycleIfComplete(ctx context.Context, cycleID string, nowMS int64) (bool, error) { + if r == nil || r.db == nil { + return false, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + var pending int + if err := r.db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM weekly_star_settlements + WHERE app_code = ? AND cycle_id = ? AND status <> ?`, + appcode.FromContext(ctx), cycleID, domain.SettlementStatusGranted, + ).Scan(&pending); err != nil { + return false, err + } + if pending > 0 { + _, err := r.db.ExecContext(ctx, ` + UPDATE weekly_star_cycles + SET locked_by = '', lock_until_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + nowMS, appcode.FromContext(ctx), cycleID, + ) + return false, err + } + _, err := r.db.ExecContext(ctx, ` + UPDATE weekly_star_cycles + SET status = ?, settled_at_ms = ?, locked_by = '', lock_until_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + domain.StatusSettled, nowMS, nowMS, appcode.FromContext(ctx), cycleID, + ) + return true, err +} + +func (r *Repository) checkWeeklyStarCycleOverlap(ctx context.Context, tx *sql.Tx, cycle domain.Cycle) error { + if cycle.Status != domain.StatusActive { + return nil + } + // 同一 app/activity/region 下 active 周期不能时间重叠;region_id=0 的默认周期可以和具体区域周期并存。 + // 具体区域优先级由读取 current 时的 ORDER BY 决定,这里只约束同一区域自身不重叠。 + var overlapID string + err := tx.QueryRowContext(ctx, ` + SELECT cycle_id + FROM weekly_star_cycles + WHERE app_code = ? AND activity_code = ? AND region_id = ? AND status = ? AND cycle_id <> ? + AND start_ms < ? AND end_ms > ? + LIMIT 1`, + cycle.AppCode, domain.ActivityCode, cycle.RegionID, domain.StatusActive, cycle.CycleID, cycle.EndMS, cycle.StartMS, + ).Scan(&overlapID) + if errors.Is(err, sql.ErrNoRows) { + return nil + } + if err != nil { + return err + } + return xerr.New(xerr.Conflict, "weekly star active cycle overlaps existing cycle") +} + +func (r *Repository) findCurrentWeeklyStarCycleForGift(ctx context.Context, tx *sql.Tx, regionID int64, giftID string, occurredAtMS int64) (domain.Cycle, bool, error) { + // 送礼事件按 occurred_at_ms 命中周期,而不是按消费时的系统时间命中。 + // 这样 MQ 延迟或手动补偿不会把旧周期的礼物误计到当前周期;具体区域优先于 region_id=0 默认配置。 + row := tx.QueryRowContext(ctx, ` + SELECT c.app_code, c.cycle_id, c.activity_code, c.region_id, c.title, c.status, c.start_ms, c.end_ms, + c.created_by_admin_id, c.updated_by_admin_id, c.settled_at_ms, c.created_at_ms, c.updated_at_ms + FROM weekly_star_cycles c + JOIN weekly_star_cycle_gifts g ON g.app_code = c.app_code AND g.cycle_id = c.cycle_id + WHERE c.app_code = ? AND c.activity_code = ? AND c.status = ? AND c.start_ms <= ? AND c.end_ms > ? + AND c.region_id IN (?, 0) AND g.gift_id = ? + ORDER BY CASE WHEN c.region_id = ? THEN 0 ELSE 1 END, c.start_ms DESC, c.updated_at_ms DESC + LIMIT 1`, + appcode.FromContext(ctx), domain.ActivityCode, domain.StatusActive, occurredAtMS, occurredAtMS, regionID, giftID, regionID, + ) + cycle, err := scanWeeklyStarCycle(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Cycle{}, false, nil + } + return cycle, err == nil, err +} + +func (r *Repository) insertWeeklyStarSettlements(ctx context.Context, tx *sql.Tx, cycleID string, nowMS int64) error { + // 排名规则必须和榜单查询一致:score 高优先,首次得分早优先,user_id 小优先。 + // 子查询先取 Top3,再用同一排序条件反算 rank_no,确保 Top1/2/3 对应正确资源组。 + rows, err := tx.QueryContext(ctx, ` + SELECT s.user_id, s.score, s.first_scored_at_ms, r.rank_no, r.resource_group_id + FROM ( + SELECT user_id, score, first_scored_at_ms + FROM weekly_star_user_scores + WHERE app_code = ? AND cycle_id = ? + ORDER BY score DESC, first_scored_at_ms ASC, user_id ASC + LIMIT 3 + ) s + JOIN weekly_star_cycle_rewards r ON r.app_code = ? AND r.cycle_id = ? AND r.rank_no = + (SELECT COUNT(*) + 1 FROM weekly_star_user_scores x + WHERE x.app_code = ? AND x.cycle_id = ? + AND (x.score > s.score OR (x.score = s.score AND x.first_scored_at_ms < s.first_scored_at_ms) OR (x.score = s.score AND x.first_scored_at_ms = s.first_scored_at_ms AND x.user_id < s.user_id))) + ORDER BY r.rank_no ASC`, + appcode.FromContext(ctx), cycleID, appcode.FromContext(ctx), cycleID, appcode.FromContext(ctx), cycleID, + ) + if err != nil { + return err + } + type topRow struct { + userID int64 + score int64 + rankNo int32 + resourceGroupID int64 + } + // 先缓存 Top3 再插入 settlement,原因同上:同一 MySQL 事务里不能边遍历 rows 边继续写表。 + topRows := make([]topRow, 0, 3) + for rows.Next() { + var firstScoredAtMS int64 + var item topRow + if err := rows.Scan(&item.userID, &item.score, &firstScoredAtMS, &item.rankNo, &item.resourceGroupID); err != nil { + _ = rows.Close() + return err + } + topRows = append(topRows, item) + _ = firstScoredAtMS + } + if err := rows.Err(); err != nil { + _ = rows.Close() + return err + } + if err := rows.Close(); err != nil { + return err + } + for _, item := range topRows { + settlementID := idgen.New("wstars") + // wallet_command_id 必须稳定包含 cycle/rank/user;结算重跑或 wallet 超时重试时依赖它防重发。 + commandID := fmt.Sprintf("weekly_star:%s:%d:%d", cycleID, item.rankNo, item.userID) + if _, err := tx.ExecContext(ctx, ` + INSERT INTO weekly_star_settlements ( + app_code, settlement_id, cycle_id, rank_no, user_id, score, resource_group_id, + wallet_command_id, wallet_grant_id, status, failure_reason, attempt_count, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, '', ?, '', 0, ?, ?)`, + appcode.FromContext(ctx), settlementID, cycleID, item.rankNo, item.userID, item.score, item.resourceGroupID, + commandID, domain.SettlementStatusPending, nowMS, nowMS, + ); err != nil { + return err + } + } + return nil +} + +func (r *Repository) getWeeklyStarCycle(ctx context.Context, q interface { + QueryRowContext(context.Context, string, ...any) *sql.Row +}, cycleID string) (domain.Cycle, error) { + row := q.QueryRowContext(ctx, ` + SELECT app_code, cycle_id, activity_code, region_id, title, status, start_ms, end_ms, + created_by_admin_id, updated_by_admin_id, settled_at_ms, created_at_ms, updated_at_ms + FROM weekly_star_cycles + WHERE app_code = ? AND cycle_id = ?`, + appcode.FromContext(ctx), strings.TrimSpace(cycleID), + ) + cycle, err := scanWeeklyStarCycle(row) + if errors.Is(err, sql.ErrNoRows) { + return domain.Cycle{}, xerr.New(xerr.NotFound, "weekly star cycle not found") + } + return cycle, err +} + +func (r *Repository) attachWeeklyStarChildren(ctx context.Context, cycles []domain.Cycle) error { + if len(cycles) == 0 { + return nil + } + for index := range cycles { + gifts, err := r.listWeeklyStarGifts(ctx, cycles[index].CycleID) + if err != nil { + return err + } + rewards, err := r.listWeeklyStarRewards(ctx, cycles[index].CycleID) + if err != nil { + return err + } + cycles[index].Gifts = gifts + cycles[index].Rewards = rewards + } + return nil +} + +func (r *Repository) listWeeklyStarGifts(ctx context.Context, cycleID string) ([]domain.Gift, error) { + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, cycle_id, gift_id, sort_order + FROM weekly_star_cycle_gifts + WHERE app_code = ? AND cycle_id = ? + ORDER BY sort_order ASC, gift_id ASC`, + appcode.FromContext(ctx), cycleID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + gifts := make([]domain.Gift, 0) + for rows.Next() { + var gift domain.Gift + if err := rows.Scan(&gift.AppCode, &gift.CycleID, &gift.GiftID, &gift.SortOrder); err != nil { + return nil, err + } + gifts = append(gifts, gift) + } + return gifts, rows.Err() +} + +func (r *Repository) listWeeklyStarRewards(ctx context.Context, cycleID string) ([]domain.Reward, error) { + rows, err := r.db.QueryContext(ctx, ` + SELECT app_code, cycle_id, rank_no, resource_group_id + FROM weekly_star_cycle_rewards + WHERE app_code = ? AND cycle_id = ? + ORDER BY rank_no ASC`, + appcode.FromContext(ctx), cycleID, + ) + if err != nil { + return nil, err + } + defer rows.Close() + rewards := make([]domain.Reward, 0) + for rows.Next() { + var reward domain.Reward + if err := rows.Scan(&reward.AppCode, &reward.CycleID, &reward.RankNo, &reward.ResourceGroupID); err != nil { + return nil, err + } + rewards = append(rewards, reward) + } + return rewards, rows.Err() +} + +type weeklyStarCycleScanner interface { + Scan(dest ...any) error +} + +func scanWeeklyStarCycle(row weeklyStarCycleScanner) (domain.Cycle, error) { + var cycle domain.Cycle + err := row.Scan(&cycle.AppCode, &cycle.CycleID, &cycle.ActivityCode, &cycle.RegionID, &cycle.Title, &cycle.Status, + &cycle.StartMS, &cycle.EndMS, &cycle.CreatedByAdminID, &cycle.UpdatedByAdminID, &cycle.SettledAtMS, &cycle.CreatedAtMS, &cycle.UpdatedAtMS) + return cycle, err +} + +func scanWeeklyStarSettlement(row weeklyStarCycleScanner) (domain.Settlement, error) { + var settlement domain.Settlement + err := row.Scan(&settlement.AppCode, &settlement.SettlementID, &settlement.CycleID, &settlement.RankNo, &settlement.UserID, + &settlement.Score, &settlement.ResourceGroupID, &settlement.WalletCommandID, &settlement.WalletGrantID, &settlement.Status, + &settlement.FailureReason, &settlement.AttemptCount, &settlement.CreatedAtMS, &settlement.UpdatedAtMS) + return settlement, err +} + +func weeklyStarCycleWhere(ctx context.Context, query domain.ListQuery) (string, []any) { + conditions := []string{"app_code = ?", "activity_code = ?"} + args := []any{appcode.FromContext(ctx), domain.ActivityCode} + if query.RegionID != nil { + conditions = append(conditions, "region_id = ?") + args = append(args, *query.RegionID) + } + if query.Status != "" { + conditions = append(conditions, "status = ?") + args = append(args, query.Status) + } + if query.StartMS > 0 { + conditions = append(conditions, "end_ms > ?") + args = append(args, query.StartMS) + } + if query.EndMS > 0 { + conditions = append(conditions, "start_ms < ?") + args = append(args, query.EndMS) + } + return "WHERE " + strings.Join(conditions, " AND "), args +} + +func parseWeeklyStarPageToken(value string) int { + offset, err := strconv.Atoi(strings.TrimSpace(value)) + if err != nil || offset < 0 { + return 0 + } + return offset +} + +func truncateWeeklyStarFailure(value string) string { + value = strings.TrimSpace(value) + if len(value) <= 512 { + return value + } + return value[:512] +} diff --git a/services/activity-service/internal/transport/grpc/broadcast_server.go b/services/activity-service/internal/transport/grpc/broadcast_server.go index 7a4cba1c..c6580c8b 100644 --- a/services/activity-service/internal/transport/grpc/broadcast_server.go +++ b/services/activity-service/internal/transport/grpc/broadcast_server.go @@ -9,6 +9,8 @@ import ( "hyapp/pkg/xerr" broadcastservice "hyapp/services/activity-service/internal/service/broadcast" growthservice "hyapp/services/activity-service/internal/service/growth" + roomturnoverrewardservice "hyapp/services/activity-service/internal/service/roomturnoverreward" + weeklystarservice "hyapp/services/activity-service/internal/service/weeklystar" ) // BroadcastServer 把 IM 播报能力暴露为内部 gRPC。 @@ -17,15 +19,22 @@ type BroadcastServer struct { activityv1.UnimplementedBroadcastServiceServer activityv1.UnimplementedRoomEventConsumerServiceServer - svc *broadcastservice.Service - growth *growthservice.Service + svc *broadcastservice.Service + growth *growthservice.Service + roomReward *roomturnoverrewardservice.Service + weeklyStar *weeklystarservice.Service } // NewBroadcastServer 创建播报和 room event 消费共用的 gRPC adapter。 -func NewBroadcastServer(svc *broadcastservice.Service, growthSvc ...*growthservice.Service) *BroadcastServer { +// room-service 的 outbox 事件只投递一次,但 activity-service 内部有多条独立投影: +// 播报负责 IM 展示,growth 负责等级进度,weekly-star 负责指定礼物榜单,roomReward 负责房间流水。 +// 这里把这些模块都挂到同一个 gRPC 入口,保证本地直连投递和 MQ 投递使用同一组业务副作用。 +func NewBroadcastServer(svc *broadcastservice.Service, growthSvc *growthservice.Service, weeklyStarSvc *weeklystarservice.Service, roomRewardSvc ...*roomturnoverrewardservice.Service) *BroadcastServer { server := &BroadcastServer{svc: svc} - if len(growthSvc) > 0 { - server.growth = growthSvc[0] + server.growth = growthSvc + server.weeklyStar = weeklyStarSvc + if len(roomRewardSvc) > 0 { + server.roomReward = roomRewardSvc[0] } return server } @@ -99,7 +108,9 @@ func (s *BroadcastServer) ProcessBroadcastOutboxBatch(ctx context.Context, req * } func (s *BroadcastServer) ConsumeRoomEvent(ctx context.Context, req *activityv1.ConsumeRoomEventRequest) (*activityv1.ConsumeRoomEventResponse, error) { - // room-service 只推送已提交的 outbox envelope;播报和等级都以同一个 event_id 幂等消费。 + // room-service 只推送已提交的 outbox envelope;每个下游模块都以同一个 event_id 做自己的幂等表。 + // 调用顺序保持和 MQ consumer 一致:先处理可见播报,再处理用户成长,再处理运营活动统计。 + // 任一模块返回错误时直接失败,让 room-service/MQ 重试同一个 envelope,而不是吞掉部分副作用。 ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) result, err := s.svc.HandleRoomEvent(ctx, req.GetEnvelope()) if err != nil { @@ -110,6 +121,16 @@ func (s *BroadcastServer) ConsumeRoomEvent(ctx context.Context, req *activityv1. return nil, xerr.ToGRPCError(err) } } + if s.weeklyStar != nil { + if _, err := s.weeklyStar.HandleRoomEvent(ctx, req.GetEnvelope()); err != nil { + return nil, xerr.ToGRPCError(err) + } + } + if s.roomReward != nil { + if _, err := s.roomReward.HandleRoomEvent(ctx, req.GetEnvelope()); err != nil { + return nil, xerr.ToGRPCError(err) + } + } return &activityv1.ConsumeRoomEventResponse{ EventId: result.EventID, Status: result.Status, diff --git a/services/activity-service/internal/transport/grpc/cron_server.go b/services/activity-service/internal/transport/grpc/cron_server.go index a5b8b254..aa768a7f 100644 --- a/services/activity-service/internal/transport/grpc/cron_server.go +++ b/services/activity-service/internal/transport/grpc/cron_server.go @@ -10,6 +10,8 @@ import ( achievementservice "hyapp/services/activity-service/internal/service/achievement" growthservice "hyapp/services/activity-service/internal/service/growth" messageservice "hyapp/services/activity-service/internal/service/message" + roomturnoverrewardservice "hyapp/services/activity-service/internal/service/roomturnoverreward" + weeklystarservice "hyapp/services/activity-service/internal/service/weeklystar" ) // CronServer exposes activity-service owned background batches to cron-service. @@ -19,14 +21,18 @@ type CronServer struct { message *messageservice.Service growth *growthservice.Service achievement *achievementservice.Service + weeklyStar *weeklystarservice.Service + roomReward *roomturnoverrewardservice.Service } // NewCronServer creates the internal cron adapter without exposing message storage. -func NewCronServer(messageSvc *messageservice.Service, growthSvc *growthservice.Service, achievementSvc ...*achievementservice.Service) *CronServer { +func NewCronServer(messageSvc *messageservice.Service, growthSvc *growthservice.Service, achievementSvc *achievementservice.Service, weeklyStarSvc *weeklystarservice.Service, roomRewardSvc ...*roomturnoverrewardservice.Service) *CronServer { server := &CronServer{message: messageSvc} server.growth = growthSvc - if len(achievementSvc) > 0 { - server.achievement = achievementSvc[0] + server.achievement = achievementSvc + server.weeklyStar = weeklyStarSvc + if len(roomRewardSvc) > 0 { + server.roomReward = roomRewardSvc[0] } return server } @@ -94,6 +100,45 @@ func (s *CronServer) ProcessAchievementRewardBatch(ctx context.Context, req *act }, nil } +// ProcessWeeklyStarSettlementBatch claims ended weekly-star cycles and grants Top rewards. +func (s *CronServer) ProcessWeeklyStarSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + if s.weeklyStar == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "weekly star service is not configured")) + } + claimed, processed, success, failure, hasMore, err := s.weeklyStar.ProcessSettlementBatch(ctx, req.GetRunId(), req.GetWorkerId(), req.GetBatchSize(), durationFromMillis(req.GetLockTtlMs())) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.CronBatchResponse{ + ClaimedCount: claimed, + ProcessedCount: processed, + SuccessCount: success, + FailureCount: failure, + HasMore: hasMore, + }, nil +} + +// ProcessRoomTurnoverRewardSettlementBatch closes the previous UTC week and grants pending room rewards. +func (s *CronServer) ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, req *activityv1.CronBatchRequest) (*activityv1.CronBatchResponse, error) { + // cron-service 只负责调度,activity-service 才拥有上一 UTC 周期认领 settlement 和发奖状态机。 + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + if s.roomReward == nil { + return nil, xerr.ToGRPCError(xerr.New(xerr.Unavailable, "room turnover reward service is not configured")) + } + result, err := s.roomReward.ProcessSettlementBatch(ctx, int(req.GetBatchSize())) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.CronBatchResponse{ + ClaimedCount: result.ClaimedCount, + ProcessedCount: result.ProcessedCount, + SuccessCount: result.SuccessCount, + FailureCount: result.FailureCount, + HasMore: result.HasMore, + }, nil +} + func durationFromMillis(value int64) time.Duration { if value <= 0 { return 0 diff --git a/services/activity-service/internal/transport/grpc/cumulative_recharge_reward_server.go b/services/activity-service/internal/transport/grpc/cumulative_recharge_reward_server.go new file mode 100644 index 00000000..fb0266d6 --- /dev/null +++ b/services/activity-service/internal/transport/grpc/cumulative_recharge_reward_server.go @@ -0,0 +1,212 @@ +package grpc + +import ( + "context" + + activityv1 "hyapp.local/api/proto/activity/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/cumulativerecharge" + service "hyapp/services/activity-service/internal/service/cumulativerecharge" +) + +// CumulativeRechargeRewardServer 暴露 App 累充奖励查询和内部充值事实消费入口。 +type CumulativeRechargeRewardServer struct { + activityv1.UnimplementedCumulativeRechargeRewardServiceServer + + svc *service.Service +} + +func NewCumulativeRechargeRewardServer(svc *service.Service) *CumulativeRechargeRewardServer { + return &CumulativeRechargeRewardServer{svc: svc} +} + +func (s *CumulativeRechargeRewardServer) GetCumulativeRechargeRewardStatus(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardStatusRequest) (*activityv1.GetCumulativeRechargeRewardStatusResponse, 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.GetCumulativeRechargeRewardStatusResponse{Status: cumulativeRechargeRewardStatusToProto(status)}, nil +} + +func (s *CumulativeRechargeRewardServer) ConsumeCumulativeRechargeReward(ctx context.Context, req *activityv1.ConsumeCumulativeRechargeRewardRequest) (*activityv1.ConsumeCumulativeRechargeRewardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + grants, 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(), + QualifyingUSDMinor: req.GetQualifyingUsdMinor(), + PayloadJSON: req.GetPayloadJson(), + OccurredAtMS: req.GetOccurredAtMs(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ConsumeCumulativeRechargeRewardResponse{ + Grants: make([]*activityv1.CumulativeRechargeRewardGrant, 0, len(grants)), + Consumed: consumed, + Reason: reason, + } + for _, grant := range grants { + resp.Grants = append(resp.Grants, cumulativeRechargeRewardGrantToProto(grant)) + } + return resp, nil +} + +// AdminCumulativeRechargeRewardServer 暴露后台配置和发放记录查询入口。 +type AdminCumulativeRechargeRewardServer struct { + activityv1.UnimplementedAdminCumulativeRechargeRewardServiceServer + + svc *service.Service +} + +func NewAdminCumulativeRechargeRewardServer(svc *service.Service) *AdminCumulativeRechargeRewardServer { + return &AdminCumulativeRechargeRewardServer{svc: svc} +} + +func (s *AdminCumulativeRechargeRewardServer) GetCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardConfigRequest) (*activityv1.GetCumulativeRechargeRewardConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + config, err := s.svc.GetConfig(ctx) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetCumulativeRechargeRewardConfigResponse{Config: cumulativeRechargeRewardConfigToProto(config)}, nil +} + +func (s *AdminCumulativeRechargeRewardServer) UpdateCumulativeRechargeRewardConfig(ctx context.Context, req *activityv1.UpdateCumulativeRechargeRewardConfigRequest) (*activityv1.UpdateCumulativeRechargeRewardConfigResponse, 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(), + ThresholdUSDMinor: tier.GetThresholdUsdMinor(), + 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.UpdateCumulativeRechargeRewardConfigResponse{Config: cumulativeRechargeRewardConfigToProto(config)}, nil +} + +func (s *AdminCumulativeRechargeRewardServer) ListCumulativeRechargeRewardGrants(ctx context.Context, req *activityv1.ListCumulativeRechargeRewardGrantsRequest) (*activityv1.ListCumulativeRechargeRewardGrantsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + grants, total, err := s.svc.ListGrants(ctx, domain.GrantQuery{ + Status: req.GetStatus(), + UserID: req.GetUserId(), + CycleKey: req.GetCycleKey(), + Page: req.GetPage(), + PageSize: req.GetPageSize(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListCumulativeRechargeRewardGrantsResponse{Grants: make([]*activityv1.CumulativeRechargeRewardGrant, 0, len(grants)), Total: total} + for _, grant := range grants { + resp.Grants = append(resp.Grants, cumulativeRechargeRewardGrantToProto(grant)) + } + return resp, nil +} + +func cumulativeRechargeRewardStatusToProto(status domain.StatusResult) *activityv1.CumulativeRechargeRewardStatus { + resp := &activityv1.CumulativeRechargeRewardStatus{ + Config: cumulativeRechargeRewardConfigToProto(status.Config), + Progress: cumulativeRechargeRewardProgressToProto(status.Progress), + Grants: make([]*activityv1.CumulativeRechargeRewardGrant, 0, len(status.Grants)), + CycleKey: status.Cycle.Key, + PeriodStartMs: status.Cycle.StartMS, + PeriodEndMs: status.Cycle.EndMS, + ServerTimeMs: status.ServerTimeMS, + } + for _, grant := range status.Grants { + resp.Grants = append(resp.Grants, cumulativeRechargeRewardGrantToProto(grant)) + } + return resp +} + +func cumulativeRechargeRewardConfigToProto(config domain.Config) *activityv1.CumulativeRechargeRewardConfig { + resp := &activityv1.CumulativeRechargeRewardConfig{ + AppCode: config.AppCode, + Enabled: config.Enabled, + Tiers: make([]*activityv1.CumulativeRechargeRewardTier, 0, len(config.Tiers)), + UpdatedByAdminId: config.UpdatedByAdminID, + CreatedAtMs: config.CreatedAtMS, + UpdatedAtMs: config.UpdatedAtMS, + } + for _, tier := range config.Tiers { + resp.Tiers = append(resp.Tiers, cumulativeRechargeRewardTierToProto(tier)) + } + return resp +} + +func cumulativeRechargeRewardTierToProto(tier domain.Tier) *activityv1.CumulativeRechargeRewardTier { + return &activityv1.CumulativeRechargeRewardTier{ + TierId: tier.TierID, + TierCode: tier.TierCode, + TierName: tier.TierName, + ThresholdUsdMinor: tier.ThresholdUSDMinor, + ResourceGroupId: tier.ResourceGroupID, + Status: tier.Status, + SortOrder: tier.SortOrder, + CreatedAtMs: tier.CreatedAtMS, + UpdatedAtMs: tier.UpdatedAtMS, + } +} + +func cumulativeRechargeRewardProgressToProto(progress domain.Progress) *activityv1.CumulativeRechargeRewardProgress { + return &activityv1.CumulativeRechargeRewardProgress{ + AppCode: progress.AppCode, + CycleKey: progress.CycleKey, + UserId: progress.UserID, + TotalUsdMinor: progress.TotalUSDMinor, + TotalCoinAmount: progress.TotalCoinAmount, + FirstRechargedAtMs: progress.FirstRechargedAtMS, + LastRechargedAtMs: progress.LastRechargedAtMS, + UpdatedAtMs: progress.UpdatedAtMS, + } +} + +func cumulativeRechargeRewardGrantToProto(grant domain.Grant) *activityv1.CumulativeRechargeRewardGrant { + if grant.GrantID == "" { + return nil + } + return &activityv1.CumulativeRechargeRewardGrant{ + GrantId: grant.GrantID, + AppCode: grant.AppCode, + CycleKey: grant.CycleKey, + UserId: grant.UserID, + EventId: grant.EventID, + TransactionId: grant.TransactionID, + CommandId: grant.CommandID, + TierId: grant.TierID, + TierCode: grant.TierCode, + ThresholdUsdMinor: grant.ThresholdUSDMinor, + ResourceGroupId: grant.ResourceGroupID, + ReachedUsdMinor: grant.ReachedUSDMinor, + QualifyingUsdMinor: grant.QualifyingUSDMinor, + RechargeCoinAmount: grant.RechargeCoinAmount, + RechargeType: grant.RechargeType, + Status: grant.Status, + WalletCommandId: grant.WalletCommandID, + WalletGrantId: grant.WalletGrantID, + FailureReason: grant.FailureReason, + GrantedAtMs: grant.GrantedAtMS, + CreatedAtMs: grant.CreatedAtMS, + UpdatedAtMs: grant.UpdatedAtMS, + } +} diff --git a/services/activity-service/internal/transport/grpc/registration_reward_server.go b/services/activity-service/internal/transport/grpc/registration_reward_server.go index 88268790..39f07f93 100644 --- a/services/activity-service/internal/transport/grpc/registration_reward_server.go +++ b/services/activity-service/internal/transport/grpc/registration_reward_server.go @@ -84,16 +84,22 @@ func (s *AdminRegistrationRewardServer) UpdateRegistrationRewardConfig(ctx conte func (s *AdminRegistrationRewardServer) ListRegistrationRewardClaims(ctx context.Context, req *activityv1.ListRegistrationRewardClaimsRequest) (*activityv1.ListRegistrationRewardClaimsResponse, 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(), + claims, total, todayClaimedCount, err := s.svc.ListClaims(ctx, domain.ClaimQuery{ + Status: req.GetStatus(), + UserID: req.GetUserId(), + ClaimedStartMS: req.GetClaimedStartMs(), + ClaimedEndMS: req.GetClaimedEndMs(), + Page: req.GetPage(), + PageSize: req.GetPageSize(), }) if err != nil { return nil, xerr.ToGRPCError(err) } - resp := &activityv1.ListRegistrationRewardClaimsResponse{Claims: make([]*activityv1.RegistrationRewardClaim, 0, len(claims)), Total: total} + resp := &activityv1.ListRegistrationRewardClaimsResponse{ + Claims: make([]*activityv1.RegistrationRewardClaim, 0, len(claims)), + Total: total, + TodayClaimedCount: todayClaimedCount, + } for _, claim := range claims { resp.Claims = append(resp.Claims, registrationRewardClaimToProto(claim)) } diff --git a/services/activity-service/internal/transport/grpc/room_turnover_reward_server.go b/services/activity-service/internal/transport/grpc/room_turnover_reward_server.go new file mode 100644 index 00000000..663b0b16 --- /dev/null +++ b/services/activity-service/internal/transport/grpc/room_turnover_reward_server.go @@ -0,0 +1,185 @@ +package grpc + +import ( + "context" + + activityv1 "hyapp.local/api/proto/activity/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/roomturnoverreward" + service "hyapp/services/activity-service/internal/service/roomturnoverreward" +) + +// RoomTurnoverRewardServer 暴露 App 房间流水奖励查询入口。 +type RoomTurnoverRewardServer struct { + activityv1.UnimplementedRoomTurnoverRewardServiceServer + + svc *service.Service +} + +func NewRoomTurnoverRewardServer(svc *service.Service) *RoomTurnoverRewardServer { + return &RoomTurnoverRewardServer{svc: svc} +} + +func (s *RoomTurnoverRewardServer) GetRoomTurnoverRewardStatus(ctx context.Context, req *activityv1.GetRoomTurnoverRewardStatusRequest) (*activityv1.GetRoomTurnoverRewardStatusResponse, error) { + // AppCode 从 protobuf meta 写入 context,下面 service 和 repository 都按这个上下文隔离配置、流水和结算记录。 + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + status, err := s.svc.GetStatus(ctx, req.GetUserId(), req.GetRoomId(), req.GetOwnerUserId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetRoomTurnoverRewardStatusResponse{Status: roomTurnoverRewardStatusToProto(status)}, nil +} + +// AdminRoomTurnoverRewardServer 暴露后台配置、结算记录和 retry 入口。 +type AdminRoomTurnoverRewardServer struct { + activityv1.UnimplementedAdminRoomTurnoverRewardServiceServer + + svc *service.Service +} + +func NewAdminRoomTurnoverRewardServer(svc *service.Service) *AdminRoomTurnoverRewardServer { + return &AdminRoomTurnoverRewardServer{svc: svc} +} + +func (s *AdminRoomTurnoverRewardServer) GetRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.GetRoomTurnoverRewardConfigRequest) (*activityv1.GetRoomTurnoverRewardConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + config, err := s.svc.GetConfig(ctx) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetRoomTurnoverRewardConfigResponse{Config: roomTurnoverRewardConfigToProto(config)}, nil +} + +func (s *AdminRoomTurnoverRewardServer) UpdateRoomTurnoverRewardConfig(ctx context.Context, req *activityv1.UpdateRoomTurnoverRewardConfigRequest) (*activityv1.UpdateRoomTurnoverRewardConfigResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + tiers := make([]domain.Tier, 0, len(req.GetTiers())) + for _, tier := range req.GetTiers() { + // protobuf 层只做字段转换,具体默认值、排序和合法性都留给 service,避免入口之间校验规则分叉。 + tiers = append(tiers, domain.Tier{ + TierID: tier.GetTierId(), + TierCode: tier.GetTierCode(), + TierName: tier.GetTierName(), + ThresholdCoinSpent: tier.GetThresholdCoinSpent(), + RewardCoinAmount: tier.GetRewardCoinAmount(), + 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.UpdateRoomTurnoverRewardConfigResponse{Config: roomTurnoverRewardConfigToProto(config)}, nil +} + +func (s *AdminRoomTurnoverRewardServer) ListRoomTurnoverRewardSettlements(ctx context.Context, req *activityv1.ListRoomTurnoverRewardSettlementsRequest) (*activityv1.ListRoomTurnoverRewardSettlementsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + // 查询条件完整透传到 domain query,分页上限由 service 统一收敛,后台和潜在内部工具不会各自实现分页规则。 + items, total, err := s.svc.ListSettlements(ctx, domain.SettlementQuery{ + Status: req.GetStatus(), + RoomID: req.GetRoomId(), + OwnerUserID: req.GetOwnerUserId(), + PeriodStartMS: req.GetPeriodStartMs(), + Page: req.GetPage(), + PageSize: req.GetPageSize(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListRoomTurnoverRewardSettlementsResponse{ + Settlements: make([]*activityv1.RoomTurnoverRewardSettlement, 0, len(items)), + Total: total, + } + for _, item := range items { + resp.Settlements = append(resp.Settlements, roomTurnoverRewardSettlementToProto(item)) + } + return resp, nil +} + +func (s *AdminRoomTurnoverRewardServer) RetryRoomTurnoverRewardSettlement(ctx context.Context, req *activityv1.RetryRoomTurnoverRewardSettlementRequest) (*activityv1.RetryRoomTurnoverRewardSettlementResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + // operator_admin_id 当前只由 admin-server 审计使用;retry 的业务幂等仍由 settlement 和 wallet command_id 保证。 + settlement, err := s.svc.RetrySettlement(ctx, req.GetSettlementId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.RetryRoomTurnoverRewardSettlementResponse{Settlement: roomTurnoverRewardSettlementToProto(settlement)}, nil +} + +func roomTurnoverRewardStatusToProto(status domain.StatusResult) *activityv1.RoomTurnoverRewardStatus { + return &activityv1.RoomTurnoverRewardStatus{ + Config: roomTurnoverRewardConfigToProto(status.Config), + RoomId: status.RoomID, + OwnerUserId: status.OwnerUserID, + PeriodStartMs: status.PeriodStartMS, + PeriodEndMs: status.PeriodEndMS, + CurrentCoinSpent: status.CurrentCoinSpent, + ExpectedRewardCoinAmount: status.ExpectedRewardCoinAmount, + MatchedTier: roomTurnoverRewardTierToProto(status.MatchedTier), + LatestSettlement: roomTurnoverRewardSettlementToProto(status.LatestSettlement), + ServerTimeMs: status.ServerTimeMS, + } +} + +func roomTurnoverRewardConfigToProto(config domain.Config) *activityv1.RoomTurnoverRewardConfig { + resp := &activityv1.RoomTurnoverRewardConfig{ + AppCode: config.AppCode, + Enabled: config.Enabled, + Tiers: make([]*activityv1.RoomTurnoverRewardTier, 0, len(config.Tiers)), + UpdatedByAdminId: config.UpdatedByAdminID, + CreatedAtMs: config.CreatedAtMS, + UpdatedAtMs: config.UpdatedAtMS, + } + for _, tier := range config.Tiers { + resp.Tiers = append(resp.Tiers, roomTurnoverRewardTierToProto(tier)) + } + return resp +} + +func roomTurnoverRewardTierToProto(tier domain.Tier) *activityv1.RoomTurnoverRewardTier { + if tier.TierID == 0 && tier.TierCode == "" { + return nil + } + return &activityv1.RoomTurnoverRewardTier{ + TierId: tier.TierID, + TierCode: tier.TierCode, + TierName: tier.TierName, + ThresholdCoinSpent: tier.ThresholdCoinSpent, + RewardCoinAmount: tier.RewardCoinAmount, + Status: tier.Status, + SortOrder: tier.SortOrder, + CreatedAtMs: tier.CreatedAtMS, + UpdatedAtMs: tier.UpdatedAtMS, + } +} + +func roomTurnoverRewardSettlementToProto(item domain.Settlement) *activityv1.RoomTurnoverRewardSettlement { + if item.SettlementID == "" { + return nil + } + return &activityv1.RoomTurnoverRewardSettlement{ + SettlementId: item.SettlementID, + AppCode: item.AppCode, + RoomId: item.RoomID, + OwnerUserId: item.OwnerUserID, + PeriodStartMs: item.PeriodStartMS, + PeriodEndMs: item.PeriodEndMS, + CoinSpent: item.CoinSpent, + TierId: item.TierID, + TierCode: item.TierCode, + ThresholdCoinSpent: item.ThresholdCoinSpent, + RewardCoinAmount: item.RewardCoinAmount, + Status: item.Status, + WalletCommandId: item.WalletCommandID, + WalletTransactionId: item.WalletTransactionID, + FailureReason: item.FailureReason, + SettledAtMs: item.SettledAtMS, + CreatedAtMs: item.CreatedAtMS, + UpdatedAtMs: item.UpdatedAtMS, + } +} diff --git a/services/activity-service/internal/transport/grpc/weekly_star_server.go b/services/activity-service/internal/transport/grpc/weekly_star_server.go new file mode 100644 index 00000000..b424689d --- /dev/null +++ b/services/activity-service/internal/transport/grpc/weekly_star_server.go @@ -0,0 +1,250 @@ +package grpc + +import ( + "context" + "time" + + activityv1 "hyapp.local/api/proto/activity/v1" + "hyapp/pkg/appcode" + "hyapp/pkg/xerr" + domain "hyapp/services/activity-service/internal/domain/weeklystar" + service "hyapp/services/activity-service/internal/service/weeklystar" +) + +// WeeklyStarServer exposes App/H5 weekly-star reads. +type WeeklyStarServer struct { + activityv1.UnimplementedWeeklyStarServiceServer + svc *service.Service +} + +func NewWeeklyStarServer(svc *service.Service) *WeeklyStarServer { + return &WeeklyStarServer{svc: svc} +} + +func (s *WeeklyStarServer) GetWeeklyStarCurrent(ctx context.Context, req *activityv1.GetWeeklyStarCurrentRequest) (*activityv1.GetWeeklyStarCurrentResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, topEntries, myEntry, found, err := s.svc.GetCurrent(ctx, req.GetUserId(), req.GetRegionId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.GetWeeklyStarCurrentResponse{ + Cycle: weeklyStarCycleToProto(cycle), + TopEntries: weeklyStarEntriesToProto(topEntries), + ServerTimeMs: time.Now().UnixMilli(), + } + if found { + resp.MyEntry = weeklyStarEntryToProto(myEntry) + } + return resp, nil +} + +func (s *WeeklyStarServer) ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, entries, nextToken, total, err := s.svc.ListLeaderboard(ctx, req.GetCycleId(), req.GetRegionId(), req.GetPageSize(), req.GetPageToken()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.ListWeeklyStarLeaderboardResponse{ + Cycle: weeklyStarCycleToProto(cycle), + Entries: weeklyStarEntriesToProto(entries), + NextPageToken: nextToken, + Total: total, + }, nil +} + +func (s *WeeklyStarServer) ListWeeklyStarHistory(ctx context.Context, req *activityv1.ListWeeklyStarHistoryRequest) (*activityv1.ListWeeklyStarHistoryResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycles, err := s.svc.ListHistory(ctx, req.GetRegionId(), req.GetLimit()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListWeeklyStarHistoryResponse{Cycles: make([]*activityv1.WeeklyStarHistoryCycle, 0, len(cycles)), ServerTimeMs: time.Now().UnixMilli()} + for _, cycle := range cycles { + resp.Cycles = append(resp.Cycles, &activityv1.WeeklyStarHistoryCycle{ + Cycle: weeklyStarCycleToProto(cycle.Cycle), + TopEntries: weeklyStarEntriesToProto(cycle.TopEntries), + }) + } + return resp, nil +} + +// AdminWeeklyStarServer exposes admin weekly-star configuration and audit reads. +type AdminWeeklyStarServer struct { + activityv1.UnimplementedAdminWeeklyStarServiceServer + svc *service.Service +} + +func NewAdminWeeklyStarServer(svc *service.Service) *AdminWeeklyStarServer { + return &AdminWeeklyStarServer{svc: svc} +} + +func (s *AdminWeeklyStarServer) ListWeeklyStarCycles(ctx context.Context, req *activityv1.ListWeeklyStarCyclesRequest) (*activityv1.ListWeeklyStarCyclesResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + var regionID *int64 + if req.GetRegionId() >= 0 && req.RegionId != 0 { + value := req.GetRegionId() + regionID = &value + } + cycles, total, err := s.svc.ListCycles(ctx, domain.ListQuery{ + RegionID: regionID, + Status: req.GetStatus(), + StartMS: req.GetStartMs(), + EndMS: req.GetEndMs(), + Page: req.GetPage(), + PageSize: req.GetPageSize(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListWeeklyStarCyclesResponse{Cycles: make([]*activityv1.WeeklyStarCycle, 0, len(cycles)), Total: total} + for _, cycle := range cycles { + resp.Cycles = append(resp.Cycles, weeklyStarCycleToProto(cycle)) + } + return resp, nil +} + +func (s *AdminWeeklyStarServer) CreateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, created, err := s.svc.CreateCycle(ctx, domain.CycleCommand{Cycle: weeklyStarCycleFromProto(req.GetCycle()), OperatorAdminID: req.GetOperatorAdminId()}) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.UpsertWeeklyStarCycleResponse{Cycle: weeklyStarCycleToProto(cycle), Created: created}, nil +} + +func (s *AdminWeeklyStarServer) GetWeeklyStarCycle(ctx context.Context, req *activityv1.GetWeeklyStarCycleRequest) (*activityv1.GetWeeklyStarCycleResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, err := s.svc.GetCycle(ctx, req.GetCycleId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.GetWeeklyStarCycleResponse{Cycle: weeklyStarCycleToProto(cycle)}, nil +} + +func (s *AdminWeeklyStarServer) UpdateWeeklyStarCycle(ctx context.Context, req *activityv1.UpsertWeeklyStarCycleRequest) (*activityv1.UpsertWeeklyStarCycleResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, created, err := s.svc.UpdateCycle(ctx, domain.CycleCommand{Cycle: weeklyStarCycleFromProto(req.GetCycle()), OperatorAdminID: req.GetOperatorAdminId()}) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.UpsertWeeklyStarCycleResponse{Cycle: weeklyStarCycleToProto(cycle), Created: created}, nil +} + +func (s *AdminWeeklyStarServer) SetWeeklyStarCycleStatus(ctx context.Context, req *activityv1.SetWeeklyStarCycleStatusRequest) (*activityv1.SetWeeklyStarCycleStatusResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + cycle, err := s.svc.SetCycleStatus(ctx, req.GetCycleId(), req.GetStatus(), req.GetOperatorAdminId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + return &activityv1.SetWeeklyStarCycleStatusResponse{Cycle: weeklyStarCycleToProto(cycle)}, nil +} + +func (s *AdminWeeklyStarServer) ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) { + return NewWeeklyStarServer(s.svc).ListWeeklyStarLeaderboard(ctx, req) +} + +func (s *AdminWeeklyStarServer) ListWeeklyStarSettlements(ctx context.Context, req *activityv1.ListWeeklyStarSettlementsRequest) (*activityv1.ListWeeklyStarSettlementsResponse, error) { + ctx = appcode.WithContext(ctx, req.GetMeta().GetAppCode()) + settlements, err := s.svc.ListSettlements(ctx, req.GetCycleId()) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + resp := &activityv1.ListWeeklyStarSettlementsResponse{Settlements: make([]*activityv1.WeeklyStarSettlement, 0, len(settlements))} + for _, settlement := range settlements { + resp.Settlements = append(resp.Settlements, weeklyStarSettlementToProto(settlement)) + } + return resp, nil +} + +func weeklyStarCycleFromProto(item *activityv1.WeeklyStarCycle) domain.Cycle { + if item == nil { + return domain.Cycle{} + } + cycle := domain.Cycle{ + CycleID: item.GetCycleId(), + ActivityCode: item.GetActivityCode(), + RegionID: item.GetRegionId(), + Title: item.GetTitle(), + Status: item.GetStatus(), + StartMS: item.GetStartMs(), + EndMS: item.GetEndMs(), + CreatedByAdminID: item.GetCreatedByAdminId(), + UpdatedByAdminID: item.GetUpdatedByAdminId(), + } + for _, gift := range item.GetGifts() { + cycle.Gifts = append(cycle.Gifts, domain.Gift{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder()}) + } + for _, reward := range item.GetRewards() { + cycle.Rewards = append(cycle.Rewards, domain.Reward{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()}) + } + return cycle +} + +func weeklyStarCycleToProto(item domain.Cycle) *activityv1.WeeklyStarCycle { + if item.CycleID == "" { + return nil + } + resp := &activityv1.WeeklyStarCycle{ + AppCode: item.AppCode, + CycleId: item.CycleID, + ActivityCode: item.ActivityCode, + RegionId: item.RegionID, + Title: item.Title, + Status: item.Status, + StartMs: item.StartMS, + EndMs: item.EndMS, + Gifts: make([]*activityv1.WeeklyStarGift, 0, len(item.Gifts)), + Rewards: make([]*activityv1.WeeklyStarReward, 0, len(item.Rewards)), + CreatedByAdminId: item.CreatedByAdminID, + UpdatedByAdminId: item.UpdatedByAdminID, + SettledAtMs: item.SettledAtMS, + CreatedAtMs: item.CreatedAtMS, + UpdatedAtMs: item.UpdatedAtMS, + } + for _, gift := range item.Gifts { + resp.Gifts = append(resp.Gifts, &activityv1.WeeklyStarGift{GiftId: gift.GiftID, SortOrder: gift.SortOrder}) + } + for _, reward := range item.Rewards { + resp.Rewards = append(resp.Rewards, &activityv1.WeeklyStarReward{RankNo: reward.RankNo, ResourceGroupId: reward.ResourceGroupID}) + } + return resp +} + +func weeklyStarEntryToProto(item domain.LeaderboardEntry) *activityv1.WeeklyStarLeaderboardEntry { + if item.UserID <= 0 { + return nil + } + return &activityv1.WeeklyStarLeaderboardEntry{ + RankNo: item.RankNo, + UserId: item.UserID, + Score: item.Score, + FirstScoredAtMs: item.FirstScoredAtMS, + LastScoredAtMs: item.LastScoredAtMS, + } +} + +func weeklyStarEntriesToProto(items []domain.LeaderboardEntry) []*activityv1.WeeklyStarLeaderboardEntry { + resp := make([]*activityv1.WeeklyStarLeaderboardEntry, 0, len(items)) + for _, item := range items { + resp = append(resp, weeklyStarEntryToProto(item)) + } + return resp +} + +func weeklyStarSettlementToProto(item domain.Settlement) *activityv1.WeeklyStarSettlement { + return &activityv1.WeeklyStarSettlement{ + SettlementId: item.SettlementID, + CycleId: item.CycleID, + RankNo: item.RankNo, + UserId: item.UserID, + Score: item.Score, + ResourceGroupId: item.ResourceGroupID, + WalletCommandId: item.WalletCommandID, + WalletGrantId: item.WalletGrantID, + Status: item.Status, + FailureReason: item.FailureReason, + AttemptCount: item.AttemptCount, + CreatedAtMs: item.CreatedAtMS, + UpdatedAtMs: item.UpdatedAtMS, + } +} diff --git a/services/cron-service/configs/config.docker.yaml b/services/cron-service/configs/config.docker.yaml index 197b706e..f9f70c6b 100644 --- a/services/cron-service/configs/config.docker.yaml +++ b/services/cron-service/configs/config.docker.yaml @@ -43,6 +43,20 @@ tasks: lock_ttl: "30s" batch_size: 100 app_codes: ["lalu"] + weekly_star_settlement: + enabled: true + interval: "5s" + timeout: "20s" + lock_ttl: "1m" + batch_size: 50 + app_codes: ["lalu"] + room_turnover_reward_settlement: + enabled: true + interval: "5m" + timeout: "30s" + lock_ttl: "5m" + batch_size: 100 + app_codes: ["lalu"] game_level_event_relay: enabled: true interval: "5s" diff --git a/services/cron-service/configs/config.tencent.example.yaml b/services/cron-service/configs/config.tencent.example.yaml index ea41edf8..ec05f4da 100644 --- a/services/cron-service/configs/config.tencent.example.yaml +++ b/services/cron-service/configs/config.tencent.example.yaml @@ -43,6 +43,20 @@ tasks: lock_ttl: "30s" batch_size: 100 app_codes: ["lalu"] + weekly_star_settlement: + enabled: true + interval: "5s" + timeout: "20s" + lock_ttl: "1m" + batch_size: 50 + app_codes: ["lalu"] + room_turnover_reward_settlement: + enabled: true + interval: "5m" + timeout: "30s" + lock_ttl: "5m" + batch_size: 100 + app_codes: ["lalu"] game_level_event_relay: enabled: true interval: "5s" diff --git a/services/cron-service/configs/config.yaml b/services/cron-service/configs/config.yaml index e240b07e..fbadb058 100644 --- a/services/cron-service/configs/config.yaml +++ b/services/cron-service/configs/config.yaml @@ -43,6 +43,20 @@ tasks: lock_ttl: "30s" batch_size: 100 app_codes: ["lalu"] + weekly_star_settlement: + enabled: true + interval: "5s" + timeout: "20s" + lock_ttl: "1m" + batch_size: 50 + app_codes: ["lalu"] + room_turnover_reward_settlement: + enabled: true + interval: "5m" + timeout: "30s" + lock_ttl: "5m" + batch_size: 100 + app_codes: ["lalu"] game_level_event_relay: enabled: true interval: "5s" diff --git a/services/cron-service/internal/app/app.go b/services/cron-service/internal/app/app.go index 1ffc9789..7c220bf9 100644 --- a/services/cron-service/internal/app/app.go +++ b/services/cron-service/internal/app/app.go @@ -119,6 +119,8 @@ func New(cfg config.Config) (*App, error) { "message_fanout": activityCron.ProcessMessageFanoutBatch, "growth_level_reward": activityCron.ProcessLevelRewardBatch, "achievement_reward": activityCron.ProcessAchievementRewardBatch, + "weekly_star_settlement": activityCron.ProcessWeeklyStarSettlementBatch, + "room_turnover_reward_settlement": activityCron.ProcessRoomTurnoverRewardSettlementBatch, "game_level_event_relay": gameCron.ProcessLevelEventOutboxBatch, "host_salary_daily_settlement": walletCron.ProcessHostSalaryDailySettlementBatch, "host_salary_half_month_settlement": walletCron.ProcessHostSalaryHalfMonthSettlementBatch, diff --git a/services/cron-service/internal/config/config.go b/services/cron-service/internal/config/config.go index edf5e743..aa155232 100644 --- a/services/cron-service/internal/config/config.go +++ b/services/cron-service/internal/config/config.go @@ -164,6 +164,22 @@ func defaultTasks() map[string]TaskConfig { BatchSize: 100, AppCodes: []string{defaultAppCode}, }, + "weekly_star_settlement": { + Enabled: true, + Interval: "5s", + Timeout: "20s", + LockTTL: "1m", + BatchSize: 50, + AppCodes: []string{defaultAppCode}, + }, + "room_turnover_reward_settlement": { + Enabled: true, + Interval: "5m", + Timeout: "30s", + LockTTL: "5m", + BatchSize: 100, + AppCodes: []string{defaultAppCode}, + }, "game_level_event_relay": { Enabled: true, Interval: "5s", diff --git a/services/cron-service/internal/integration/activity.go b/services/cron-service/internal/integration/activity.go index b15b9b9c..dbf8dc56 100644 --- a/services/cron-service/internal/integration/activity.go +++ b/services/cron-service/internal/integration/activity.go @@ -45,6 +45,25 @@ func (c *ActivityCronClient) ProcessAchievementRewardBatch(ctx context.Context, return activityCronBatchResult(resp), nil } +// ProcessWeeklyStarSettlementBatch handles ended weekly-star cycle settlements. +func (c *ActivityCronClient) ProcessWeeklyStarSettlementBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + resp, err := c.client.ProcessWeeklyStarSettlementBatch(ctx, activityCronBatchRequest(req)) + if err != nil { + return scheduler.BatchResult{}, err + } + return activityCronBatchResult(resp), nil +} + +// ProcessRoomTurnoverRewardSettlementBatch handles ended room-turnover-reward cycle settlements. +func (c *ActivityCronClient) ProcessRoomTurnoverRewardSettlementBatch(ctx context.Context, req scheduler.BatchRequest) (scheduler.BatchResult, error) { + // cron-service 不直连 activity MySQL;它只把 run_id、worker_id 和 batch_size 传给活动服务,让 owner service 自己处理幂等和状态推进。 + resp, err := c.client.ProcessRoomTurnoverRewardSettlementBatch(ctx, activityCronBatchRequest(req)) + if err != nil { + return scheduler.BatchResult{}, err + } + return activityCronBatchResult(resp), nil +} + func activityCronBatchRequest(req scheduler.BatchRequest) *activityv1.CronBatchRequest { return &activityv1.CronBatchRequest{ Meta: &activityv1.RequestMeta{ diff --git a/services/game-service/internal/domain/game/game.go b/services/game-service/internal/domain/game/game.go index fb67d132..6b6319de 100644 --- a/services/game-service/internal/domain/game/game.go +++ b/services/game-service/internal/domain/game/game.go @@ -13,11 +13,12 @@ const ( LaunchModeH5Popup = "h5_popup" SessionActive = "active" - AdapterDemo = "demo" - AdapterYomiV4 = "yomi_v4" - AdapterLeaderCCV1 = "leadercc_v1" - AdapterZeeOneV1 = "zeeone_v1" - AdapterBaishunV1 = "baishun_v1" + AdapterDemo = "demo" + AdapterYomiV4 = "yomi_v4" + AdapterLeaderCCV1 = "leadercc_v1" + AdapterZeeOneV1 = "zeeone_v1" + AdapterBaishunV1 = "baishun_v1" + AdapterVivaGamesV1 = "vivagames_v1" OrderStatusWalletApplying = "wallet_applying" OrderStatusSucceeded = "succeeded" diff --git a/services/game-service/internal/service/game/service.go b/services/game-service/internal/service/game/service.go index e7bd221d..8484c192 100644 --- a/services/game-service/internal/service/game/service.go +++ b/services/game-service/internal/service/game/service.go @@ -203,7 +203,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) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) { + if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) || strings.EqualFold(game.AdapterType, gamedomain.AdapterLeaderCCV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterZeeOneV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) || strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) { return LaunchResult{}, xerr.New(xerr.InvalidArgument, "access token is required for provider game launch") } token = "gt_" + randomHex(24) @@ -218,6 +218,8 @@ func (s *Service) LaunchGame(ctx context.Context, command LaunchCommand) (Launch sessionTTL = maxDuration(sessionTTL, zeeoneConfigFromPlatform(game).TokenTTL()) } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) { sessionTTL = maxDuration(sessionTTL, baishunConfigFromPlatform(game).TokenTTL()) + } else if strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) { + sessionTTL = maxDuration(sessionTTL, vivaGamesConfigFromPlatform(game).TokenTTL()) } expiresAt := now.Add(sessionTTL).UnixMilli() session := gamedomain.LaunchSession{ @@ -288,6 +290,8 @@ func (s *Service) HandleCallback(ctx context.Context, req *gamev1.CallbackReques responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleZeeOneOperation(ctx, app, platform, req, operation, requestHash) case strings.EqualFold(platform.AdapterType, gamedomain.AdapterBaishunV1): responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleBaishunOperation(ctx, app, platform, req, operation, requestHash) + case strings.EqualFold(platform.AdapterType, gamedomain.AdapterVivaGamesV1): + responseBody, contentType, statusCode, signatureValid, providerRequestID, err = s.handleVivaGamesOperation(ctx, app, platform, req, operation, requestHash) default: responseBody, contentType, statusCode, err = s.handleDemoOperation(ctx, app, req, operation, requestHash) } @@ -616,6 +620,12 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes base = configuredBase } } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) { + // VIVAGAMES 文档说明游戏 URL 由厂商提供;后台按 game_id 保存 URL,启动时只拼客户端 getConfig 需要的热配置。 + if configuredBase := vivaGamesLaunchBaseURL(game, vivaGamesConfigFromPlatform(game)); configuredBase != "" { + base = configuredBase + } + } if base == "" { if strings.EqualFold(game.AdapterType, gamedomain.AdapterYomiV4) { return "", xerr.New(xerr.InvalidArgument, "yomi auth url is required") @@ -626,6 +636,9 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes if strings.EqualFold(game.AdapterType, gamedomain.AdapterBaishunV1) { return "", xerr.New(xerr.InvalidArgument, "baishun launch url is required") } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) { + return "", xerr.New(xerr.InvalidArgument, "vivagames launch url is required") + } // demo 平台可以没有真实厂商域名,保留本地默认地址用于开发自测。 base = "https://game.example.local/h5" } @@ -727,6 +740,29 @@ func buildLaunchURL(game gamedomain.LaunchableGame, session gamedomain.LaunchSes parsed.RawQuery = query.Encode() return parsed.String(), nil } + if strings.EqualFold(game.AdapterType, gamedomain.AdapterVivaGamesV1) { + // VIVAGAMES H5 通过 NativeBridge.getConfig 取 appId/userId/code;这里把同一份配置拼到 URL,供 App 壳层回写给 H5。 + config := vivaGamesConfigFromPlatform(game) + query.Set("bridge_keys", "appId,userId,code,metadata,language,coinType,amountRate,bgmSwitch,gsp,currencyIcon,gameConfig,gameId") + if config.AppID > 0 { + query.Set("appId", strconv.FormatInt(config.AppID, 10)) + } + query.Set("userId", externalUserID(session, config.UIDMode)) + query.Set("code", token) + query.Set("gameId", strings.TrimSpace(session.ProviderGameID)) + query.Set("metadata", config.MetadataValue(session)) + query.Set("language", config.LanguageValue()) + query.Set("coinType", strconv.FormatInt(config.CoinType, 10)) + query.Set("amountRate", strconv.FormatInt(config.AmountRateValue(), 10)) + query.Set("bgmSwitch", strconv.FormatInt(config.BGMSwitchValue(), 10)) + query.Set("gsp", strconv.FormatInt(config.GSPValue(), 10)) + if config.CurrencyIcon != "" { + query.Set("currencyIcon", config.CurrencyIcon) + query.Set("gameConfig", vivaGamesGameConfigQuery(config.CurrencyIcon)) + } + 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 43e92722..fa932c96 100644 --- a/services/game-service/internal/service/game/service_test.go +++ b/services/game-service/internal/service/game/service_test.go @@ -335,6 +335,81 @@ func TestLaunchGameBuildsBaishunURL(t *testing.T) { } } +func TestLaunchGameBuildsVivaGamesURL(t *testing.T) { + repo := &fakeRepository{ + launchable: gamedomain.LaunchableGame{ + CatalogItem: gamedomain.CatalogItem{ + AppCode: "lalu", + GameID: "vivagames_2", + PlatformCode: "vivagames", + ProviderGameID: "2", + GameName: "Viva Demo", + Status: gamedomain.StatusActive, + Orientation: "portrait", + }, + PlatformStatus: gamedomain.StatusActive, + APIBaseURL: "https://fallback.example.invalid/game.html", + AdapterType: gamedomain.AdapterVivaGamesV1, + AdapterConfigJSON: `{ + "app_id":1012127974, + "default_lang":"en-US", + "token_ttl_seconds":86400, + "uid_mode":"display_user_id", + "amount_rate":1, + "bgm_switch":0, + "gsp":101, + "currency_icon":"https://cdn.example/coin.png", + "game_urls":{"2":"https://dev-rich2.s3.ap-southeast-1.amazonaws.com/richForever.html?game_id=2&isShow=1"} + }`, + }, + } + 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: "vivagames_2", + RoomID: "room_1", + AccessToken: "app_access_token_viva", + }) + if err != nil { + t.Fatalf("LaunchGame failed: %v", err) + } + if result.ExpiresAtMS != 1700086400000 { + t.Fatalf("vivagames launch must use adapter token ttl, got %+v", result) + } + parsed, err := url.Parse(result.LaunchURL) + if err != nil { + t.Fatalf("parse vivagames launch url failed: %v", err) + } + if parsed.Scheme+"://"+parsed.Host+parsed.Path != "https://dev-rich2.s3.ap-southeast-1.amazonaws.com/richForever.html" { + t.Fatalf("vivagames launch url must use per-game configured url: %s", result.LaunchURL) + } + query := parsed.Query() + expected := map[string]string{ + "appId": "1012127974", + "userId": "420001", + "code": "app_access_token_viva", + "gameId": "2", + "metadata": `{"room_id":"room_1"}`, + "language": "en-US", + "coinType": "0", + "amountRate": "1", + "bgmSwitch": "0", + "gsp": "101", + "currencyIcon": "https://cdn.example/coin.png", + "gameConfig": `{"currencyIcon":"https://cdn.example/coin.png"}`, + "bridge_keys": "appId,userId,code,metadata,language,coinType,amountRate,bgmSwitch,gsp,currencyIcon,gameConfig,gameId", + } + for key, want := range expected { + if got := query.Get(key); got != want { + t.Fatalf("vivagames launch query %s mismatch: got %q want %q url=%s", key, got, want, result.LaunchURL) + } + } +} + func TestLaunchGameRequiresBaishunLaunchURL(t *testing.T) { repo := &fakeRepository{ launchable: gamedomain.LaunchableGame{ @@ -1002,6 +1077,95 @@ func TestHandleBaishunSSTokenUserInfoUpdateAndChangeBalance(t *testing.T) { } } +func TestHandleVivaGamesTokenUserInfoUpdateAndChangeBalance(t *testing.T) { + secret := "vivagames-test-app-key" + token := "app_access_token_viva" + repo := &fakeRepository{ + platform: gamedomain.Platform{ + PlatformCode: "vivagames", + AdapterType: gamedomain.AdapterVivaGamesV1, + CallbackSecretCiphertext: secret, + AdapterConfigJSON: `{"app_id":1012127974,"uid_mode":"display_user_id"}`, + }, + session: gamedomain.LaunchSession{ + AppCode: "lalu", + SessionID: "game_sess_viva", + UserID: 42, + DisplayUserID: "420001", + RoomID: "room_1", + PlatformCode: "vivagames", + GameID: "vivagames_2", + ProviderGameID: "2", + LaunchTokenHash: stableHash(token), + Status: gamedomain.SessionActive, + ExpiresAtMS: 1700086400000, + }, + } + wallet := &fakeWallet{balanceAfter: 1880} + user := &fakeUser{} + svc := New(Config{}, repo, wallet, user) + svc.now = func() time.Time { return time.UnixMilli(1700000000000) } + + raw, contentType, err := svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-viva-token", AppCode: "lalu"}, + PlatformCode: "vivagames", + Operation: "get-token", + RawBody: vivaGamesTestBody(t, secret, `{"app_id":1012127974,"user_id":"420001","code":"app_access_token_viva"}`, 1700000000), + RemoteAddr: "3.1.174.194:443", + }) + if err != nil { + t.Fatalf("HandleCallback get-token failed: %v", err) + } + if contentType != "application/json" || !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"token":"app_access_token_viva"`) || !strings.Contains(string(raw), `"expire_at":1700086400000`) { + t.Fatalf("vivagames get-token response mismatch: %s", raw) + } + + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-viva-userinfo", AppCode: "lalu"}, + PlatformCode: "vivagames", + Operation: "get-user-info", + RawBody: vivaGamesTestBody(t, secret, `{"app_id":1012127974,"user_id":"420001","token":"app_access_token_viva","client_ip":"110.86.1.130","game_id":2}`, 1700000000), + RemoteAddr: "3.1.174.194:443", + }) + if err != nil { + t.Fatalf("HandleCallback get-user-info failed: %v", err) + } + if !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"user_id":"420001"`) || !strings.Contains(string(raw), `"avatar_url":"https://cdn.example/avatar.png"`) || !strings.Contains(string(raw), `"balance":1880`) { + t.Fatalf("vivagames userinfo response mismatch: %s", raw) + } + + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-viva-update", AppCode: "lalu"}, + PlatformCode: "vivagames", + Operation: "update-token", + RawBody: vivaGamesTestBody(t, secret, `{"app_id":1012127974,"user_id":"420001","token":"app_access_token_viva"}`, 1700000000), + RemoteAddr: "3.1.174.194:443", + }) + if err != nil { + t.Fatalf("HandleCallback update-token failed: %v", err) + } + if !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"expire_at":1700086400000`) { + t.Fatalf("vivagames update-token response mismatch: %s", raw) + } + + raw, _, err = svc.HandleCallback(context.Background(), &gamev1.CallbackRequest{ + Meta: &gamev1.RequestMeta{RequestId: "req-viva-change", AppCode: "lalu"}, + PlatformCode: "vivagames", + Operation: "change-balance", + RawBody: vivaGamesTestBody(t, secret, `{"app_id":1012127974,"user_id":"420001","token":"app_access_token_viva","order_id":"viva_order_1","game_round_id":"round_1","game_id":2,"total_bet":120,"change_amount":-120,"change_reason":"bet","change_time_at":1700000000,"metadata":"{\"room_id\":\"room_1\"}"}`, 1700000000), + RemoteAddr: "3.1.174.194:443", + }) + if err != nil { + t.Fatalf("HandleCallback change-balance failed: %v", err) + } + if !strings.Contains(string(raw), `"code":0`) || !strings.Contains(string(raw), `"balance":1880`) { + t.Fatalf("vivagames change response mismatch: %s", raw) + } + if wallet.lastApply.GetCommandId() != "game:vivagames:viva_order_1" || wallet.lastApply.GetOpType() != "debit" || wallet.lastApply.GetCoinAmount() != 120 || wallet.lastApply.GetGameId() != "vivagames_2" { + t.Fatalf("vivagames wallet command mismatch: %+v", wallet.lastApply) + } +} + func TestHandleBaishunAccessTokenIgnoresStaleLaunchSessionGameID(t *testing.T) { secret := "baishun-test-app-key" userID := int64(312900923573673984) @@ -1458,3 +1622,20 @@ func baishunTestBody(t *testing.T, secret string, body string, timestamp int64) } return encoded } + +func vivaGamesTestBody(t *testing.T, secret string, body string, timestamp int64) []byte { + t.Helper() + var payload map[string]any + decoder := json.NewDecoder(strings.NewReader(body)) + decoder.UseNumber() + if err := decoder.Decode(&payload); err != nil { + t.Fatalf("decode vivagames test body: %v", err) + } + payload["timestamp"] = json.Number(strconv.FormatInt(timestamp, 10)) + payload["sign"] = vivaGamesSign(payload, secret) + encoded, err := json.Marshal(payload) + if err != nil { + t.Fatalf("marshal vivagames test body: %v", err) + } + return encoded +} diff --git a/services/game-service/internal/service/game/vivagames_adapter.go b/services/game-service/internal/service/game/vivagames_adapter.go new file mode 100644 index 00000000..2dd97fbe --- /dev/null +++ b/services/game-service/internal/service/game/vivagames_adapter.go @@ -0,0 +1,494 @@ +package game + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "sort" + "strconv" + "strings" + "time" + + gamev1 "hyapp.local/api/proto/game/v1" + "hyapp/pkg/xerr" + gamedomain "hyapp/services/game-service/internal/domain/game" +) + +const ( + // VIVAGAMES 文档定义 code=0 成功;游戏侧按 JSON code 判断业务结果,HTTP 200 只表示回调已被接收。 + vivaGamesCodeOK = 0 + vivaGamesCodeAppNotFound = 1001 + vivaGamesCodeInvalidArgument = 1002 + vivaGamesCodeSignatureInvalid = 1003 + vivaGamesCodeCodeInvalid = 1004 + vivaGamesCodeTokenInvalid = 1005 + vivaGamesCodeInternalError = 1006 + vivaGamesCodeGameMaintenance = 1007 + vivaGamesCodeInsufficientBalance = 1008 + vivaGamesCodeUserDisabled = 1009 + vivaGamesCodeRequestExpired = 1010 + + vivaGamesDefaultTokenTTL = 24 * time.Hour + vivaGamesSignatureValidWindow = 5 * time.Minute +) + +type vivaGamesAdapterConfig struct { + // app_id 来自 VIVAGAMES 后台;callbackSecret 存放 PDF 签名算法使用的 AppKey。 + AppID int64 `json:"app_id"` + AppIDAlias int64 `json:"appId"` + AppSecret string `json:"app_secret"` + UIDMode string `json:"uid_mode"` + DefaultLang string `json:"default_lang"` + // token_ttl_seconds 控制启动 session 至少保留多久,避免 H5 游戏中途回调时 token 已过期。 + TokenTTLSeconds int64 `json:"token_ttl_seconds"` + + // 以下字段直接对应 NativeBridge.getConfig,后台热改后下一次启动生效。 + Metadata string `json:"metadata"` + CoinType int64 `json:"coin_type"` + AmountRate int64 `json:"amount_rate"` + BGMSwitch *int64 `json:"bgm_switch"` + GSP int64 `json:"gsp"` + CurrencyIcon string `json:"currency_icon"` + + // VIVAGAMES 文档没有游戏列表 API,game_urls 用后台配置保存厂商提供的逐游戏 H5 URL。 + GameURLs map[string]string `json:"game_urls"` + LaunchURLTemplate string `json:"launch_url_template"` +} + +func vivaGamesConfigFromPlatform(value any) vivaGamesAdapterConfig { + var raw string + switch typed := value.(type) { + case gamedomain.Platform: + raw = typed.AdapterConfigJSON + case gamedomain.LaunchableGame: + raw = typed.AdapterConfigJSON + } + var config vivaGamesAdapterConfig + _ = json.Unmarshal([]byte(strings.TrimSpace(raw)), &config) + if config.AppID == 0 { + config.AppID = config.AppIDAlias + } + config.AppSecret = strings.TrimSpace(config.AppSecret) + config.UIDMode = strings.ToLower(strings.TrimSpace(config.UIDMode)) + config.DefaultLang = strings.TrimSpace(config.DefaultLang) + config.Metadata = strings.TrimSpace(config.Metadata) + config.CurrencyIcon = strings.TrimSpace(config.CurrencyIcon) + config.LaunchURLTemplate = strings.TrimSpace(config.LaunchURLTemplate) + config.GameURLs = normalizeStringMap(config.GameURLs) + return config +} + +func (c vivaGamesAdapterConfig) TokenTTL() time.Duration { + if c.TokenTTLSeconds > 0 { + return time.Duration(c.TokenTTLSeconds) * time.Second + } + return vivaGamesDefaultTokenTTL +} + +func (c vivaGamesAdapterConfig) LanguageValue() string { + if c.DefaultLang != "" { + return c.DefaultLang + } + return "en-US" +} + +func (c vivaGamesAdapterConfig) AmountRateValue() int64 { + if c.AmountRate > 0 { + return c.AmountRate + } + return 1 +} + +func (c vivaGamesAdapterConfig) BGMSwitchValue() int64 { + if c.BGMSwitch != nil { + return *c.BGMSwitch + } + return 1 +} + +func (c vivaGamesAdapterConfig) GSPValue() int64 { + if c.GSP > 0 { + return c.GSP + } + return 101 +} + +func (c vivaGamesAdapterConfig) MetadataValue(session gamedomain.LaunchSession) string { + if c.Metadata != "" { + return c.Metadata + } + if strings.TrimSpace(session.RoomID) == "" { + return "" + } + raw, err := json.Marshal(map[string]string{"room_id": strings.TrimSpace(session.RoomID)}) + if err != nil { + return "" + } + return string(raw) +} + +func vivaGamesLaunchBaseURL(game gamedomain.LaunchableGame, config vivaGamesAdapterConfig) 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 vivaGamesGameConfigQuery(currencyIcon string) string { + raw, err := json.Marshal(map[string]string{"currencyIcon": strings.TrimSpace(currencyIcon)}) + if err != nil { + return "" + } + return string(raw) +} + +func (s *Service) handleVivaGamesOperation(ctx context.Context, app string, platform gamedomain.Platform, req *gamev1.CallbackRequest, operation string, requestHash string) ([]byte, string, string, bool, string, error) { + if !callbackIPAllowed(req, platform.CallbackIPWhitelist) { + raw, contentType := vivaGamesJSON(vivaGamesCodeSignatureInvalid, "ip restricted", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeSignatureInvalid), false, "", nil + } + config := vivaGamesConfigFromPlatform(platform) + body, signed, decoded, expired, providerRequestID := s.decodeVivaGamesBody(req, platform.CallbackSecretCiphertext) + if !decoded { + raw, contentType := vivaGamesJSON(vivaGamesCodeInvalidArgument, "invalid argument", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeInvalidArgument), false, providerRequestID, nil + } + if expired { + raw, contentType := vivaGamesJSON(vivaGamesCodeRequestExpired, "request expired", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeRequestExpired), false, providerRequestID, nil + } + if !signed { + raw, contentType := vivaGamesJSON(vivaGamesCodeSignatureInvalid, "sign error", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeSignatureInvalid), false, providerRequestID, nil + } + appID := body.AppIDInt64() + if appID <= 0 { + raw, contentType := vivaGamesJSON(vivaGamesCodeInvalidArgument, "invalid app_id", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeInvalidArgument), signed, providerRequestID, nil + } + if config.AppID > 0 && appID != config.AppID { + raw, contentType := vivaGamesJSON(vivaGamesCodeAppNotFound, "appId not found", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeAppNotFound), signed, providerRequestID, nil + } + switch operation { + case "get-token", "get_token", "gettoken", "api/get-token", "api/get_token", "v1/api/get-token": + return s.handleVivaGamesGetToken(ctx, app, config, req, body) + case "get-user-info", "get_user_info", "userinfo", "user_info", "api/get-user-info", "api/get_user_info", "v1/api/get-user-info": + return s.handleVivaGamesUserInfo(ctx, app, config, req, body) + case "update-token", "update_token", "updatetoken", "api/update-token", "api/update_token", "v1/api/update-token": + return s.handleVivaGamesUpdateToken(ctx, app, config, body) + case "change-balance", "change_balance", "changebalance", "api/change-balance", "api/change_balance", "v1/api/change-balance": + return s.handleVivaGamesChangeBalance(ctx, app, config, req, body, requestHash) + default: + raw, contentType := vivaGamesJSON(vivaGamesCodeOK, "", map[string]any{}) + return raw, contentType, strconv.Itoa(vivaGamesCodeOK), signed, providerRequestID, nil + } +} + +type vivaGamesBody struct { + AppID json.Number `json:"app_id"` + UserID string `json:"user_id"` + Code string `json:"code"` + Token string `json:"token"` + ClientIP string `json:"client_ip"` + GameID json.Number `json:"game_id"` + OrderID string `json:"order_id"` + GameRoundID string `json:"game_round_id"` + TotalBet int64 `json:"total_bet"` + ChangeAmount int64 `json:"change_amount"` + ChangeReason string `json:"change_reason"` + ChangeTimeAt int64 `json:"change_time_at"` + Metadata string `json:"metadata"` + ExtendType string `json:"extend_type"` + Extend string `json:"extend"` + IgnoreExpire bool `json:"ignore_expire"` + Timestamp int64 `json:"timestamp"` + Signature string `json:"sign"` +} + +func (s *Service) decodeVivaGamesBody(req *gamev1.CallbackRequest, secret string) (vivaGamesBody, bool, bool, bool, string) { + var body vivaGamesBody + decoder := json.NewDecoder(strings.NewReader(string(req.GetRawBody()))) + decoder.UseNumber() + if err := decoder.Decode(&body); err != nil { + return vivaGamesBody{}, false, false, false, "" + } + body.normalize() + providerRequestID := strings.TrimSpace(body.OrderID) + params, err := vivaGamesParamsForSign(req.GetRawBody()) + if err != nil { + return vivaGamesBody{}, false, false, false, providerRequestID + } + signed, expired := s.vivaGamesSignatureValid(params, body.Signature, body.Timestamp, secret) + return body, signed, true, expired, providerRequestID +} + +func vivaGamesParamsForSign(raw []byte) (map[string]any, error) { + var params map[string]any + decoder := json.NewDecoder(strings.NewReader(string(raw))) + decoder.UseNumber() + if err := decoder.Decode(¶ms); err != nil { + return nil, err + } + delete(params, "sign") + return params, nil +} + +func (s *Service) vivaGamesSignatureValid(params map[string]any, signature string, timestamp int64, secret string) (bool, bool) { + secret = strings.TrimSpace(secret) + if secret == "" || strings.TrimSpace(signature) == "" || timestamp <= 0 { + return false, false + } + requestAt := time.Unix(timestamp, 0) + now := s.now() + if requestAt.After(now.Add(vivaGamesSignatureValidWindow)) || now.Sub(requestAt) > vivaGamesSignatureValidWindow { + return false, true + } + expected := vivaGamesSign(params, secret) + return strings.EqualFold(strings.TrimSpace(signature), expected), false +} + +func vivaGamesSign(params map[string]any, secret string) string { + keys := make([]string, 0, len(params)) + for key, value := range params { + if value == nil || strings.TrimSpace(key) == "" || strings.EqualFold(key, "sign") { + continue + } + keys = append(keys, key) + } + sort.Strings(keys) + parts := make([]string, 0, len(keys)+1) + for _, key := range keys { + parts = append(parts, fmt.Sprintf("%s=%s", key, vivaGamesSignValue(params[key]))) + } + parts = append(parts, "key="+strings.TrimSpace(secret)) + sum := sha256.Sum256([]byte(strings.Join(parts, "&"))) + return hex.EncodeToString(sum[:]) +} + +func vivaGamesSignValue(value any) string { + switch typed := value.(type) { + case json.Number: + return typed.String() + case string: + return typed + case bool: + if typed { + return "true" + } + return "false" + default: + return strings.TrimSpace(fmt.Sprint(typed)) + } +} + +func (body *vivaGamesBody) normalize() { + body.UserID = strings.TrimSpace(body.UserID) + body.Code = strings.TrimSpace(body.Code) + body.Token = strings.TrimSpace(body.Token) + body.ClientIP = strings.TrimSpace(body.ClientIP) + body.OrderID = strings.TrimSpace(body.OrderID) + body.GameRoundID = strings.TrimSpace(body.GameRoundID) + body.ChangeReason = strings.ToLower(strings.TrimSpace(body.ChangeReason)) + body.Metadata = strings.TrimSpace(body.Metadata) + body.ExtendType = strings.TrimSpace(body.ExtendType) + body.Extend = strings.TrimSpace(body.Extend) + body.Signature = strings.TrimSpace(body.Signature) +} + +func (body vivaGamesBody) AppIDInt64() int64 { + value, _ := strconv.ParseInt(strings.TrimSpace(body.AppID.String()), 10, 64) + return value +} + +func (body vivaGamesBody) GameIDInt64() int64 { + value, _ := strconv.ParseInt(strings.TrimSpace(body.GameID.String()), 10, 64) + return value +} + +func (s *Service) handleVivaGamesGetToken(ctx context.Context, app string, config vivaGamesAdapterConfig, req *gamev1.CallbackRequest, body vivaGamesBody) ([]byte, string, string, bool, string, error) { + if body.UserID == "" || body.Code == "" { + return vivaGamesAdapterError(vivaGamesCodeInvalidArgument, "invalid argument", true, "") + } + session, err := s.validVivaGamesSession(ctx, app, body.Code, false) + if err != nil || !vivaGamesSessionMatches(session, config, body.UserID, 0) { + return vivaGamesAdapterError(vivaGamesCodeCodeInvalid, "code error", true, "") + } + raw, contentType := vivaGamesJSON(vivaGamesCodeOK, "", map[string]any{ + "token": body.Code, + "expire_at": session.ExpiresAtMS, + }) + return raw, contentType, strconv.Itoa(vivaGamesCodeOK), true, "", nil +} + +func (s *Service) handleVivaGamesUserInfo(ctx context.Context, app string, config vivaGamesAdapterConfig, req *gamev1.CallbackRequest, body vivaGamesBody) ([]byte, string, string, bool, string, error) { + if body.UserID == "" || body.Token == "" { + return vivaGamesAdapterError(vivaGamesCodeInvalidArgument, "invalid argument", true, "") + } + session, err := s.validVivaGamesSession(ctx, app, body.Token, false) + if err != nil || !vivaGamesSessionMatches(session, config, body.UserID, body.GameIDInt64()) { + return vivaGamesAdapterError(vivaGamesCodeTokenInvalid, "token error", true, "") + } + snapshot, err := s.yomiUserSnapshot(ctx, app, req, session.UserID) + if err != nil { + return vivaGamesAdapterError(vivaGamesCodeFromError(err), vivaGamesMessageFromError(err), true, "") + } + raw, contentType := vivaGamesJSON(vivaGamesCodeOK, "", map[string]any{ + "user_id": externalUserID(session, config.UIDMode), + "nickname": snapshot.Nickname, + "avatar_url": snapshot.Avatar, + "balance": snapshot.Balance, + "status": 0, + }) + return raw, contentType, strconv.Itoa(vivaGamesCodeOK), true, "", nil +} + +func (s *Service) handleVivaGamesUpdateToken(ctx context.Context, app string, config vivaGamesAdapterConfig, body vivaGamesBody) ([]byte, string, string, bool, string, error) { + if body.UserID == "" || body.Token == "" { + return vivaGamesAdapterError(vivaGamesCodeInvalidArgument, "invalid argument", true, "") + } + session, err := s.validVivaGamesSession(ctx, app, body.Token, false) + if err != nil || !vivaGamesSessionMatches(session, config, body.UserID, 0) { + return vivaGamesAdapterError(vivaGamesCodeTokenInvalid, "token error", true, "") + } + raw, contentType := vivaGamesJSON(vivaGamesCodeOK, "", map[string]any{ + "token": body.Token, + "expire_at": session.ExpiresAtMS, + }) + return raw, contentType, strconv.Itoa(vivaGamesCodeOK), true, "", nil +} + +func (s *Service) handleVivaGamesChangeBalance(ctx context.Context, app string, config vivaGamesAdapterConfig, req *gamev1.CallbackRequest, body vivaGamesBody, requestHash string) ([]byte, string, string, bool, string, error) { + if body.UserID == "" || body.Token == "" || body.OrderID == "" || body.GameIDInt64() <= 0 || body.ChangeReason == "" { + return vivaGamesAdapterError(vivaGamesCodeInvalidArgument, "invalid argument", true, body.OrderID) + } + session, err := s.validVivaGamesSession(ctx, app, body.Token, body.IgnoreExpire) + if err != nil || !vivaGamesSessionMatches(session, config, body.UserID, body.GameIDInt64()) { + return vivaGamesAdapterError(vivaGamesCodeTokenInvalid, "token error", true, body.OrderID) + } + if session.ProviderGameID == "" { + session.ProviderGameID = strconv.FormatInt(body.GameIDInt64(), 10) + } + if session.GameID == "" { + session.GameID = session.ProviderGameID + } + opType, amount := vivaGamesOpType(body.ChangeAmount) + result, err := s.applyYomiCoinChange(ctx, app, req, session, body.OrderID, body.GameRoundID, opType, amount, "", requestHash) + if err != nil { + code := vivaGamesCodeFromError(err) + balance := s.bestEffortCoinBalance(ctx, app, req.GetMeta().GetRequestId(), session.UserID) + raw, contentType := vivaGamesJSON(code, vivaGamesMessageFromError(err), map[string]any{"balance": balance}) + return raw, contentType, strconv.Itoa(code), true, body.OrderID, nil + } + raw, contentType := vivaGamesJSON(vivaGamesCodeOK, "", map[string]any{"balance": result.BalanceAfter}) + return raw, contentType, strconv.Itoa(vivaGamesCodeOK), true, body.OrderID, nil +} + +func (s *Service) validVivaGamesSession(ctx context.Context, app string, token string, ignoreExpire bool) (gamedomain.LaunchSession, error) { + token = strings.TrimSpace(token) + if token == "" { + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") + } + // VIVAGAMES token 直接复用 App access token;先解析 JWT 可以避免同一登录 token 多游戏启动时命中过期旧 session。 + if strings.Count(token, ".") == 2 && !ignoreExpire { + if session, err := s.appSessionFromAccessToken(app, token); err == nil { + return session, nil + } + } + if session, err := s.repository.GetLaunchSessionByToken(ctx, app, token); err == nil { + if session.Status != gamedomain.SessionActive { + return gamedomain.LaunchSession{}, xerr.New(xerr.SessionExpired, "token expired") + } + if !ignoreExpire && session.ExpiresAtMS <= s.now().UnixMilli() { + return gamedomain.LaunchSession{}, xerr.New(xerr.SessionExpired, "token expired") + } + return session, nil + } + if strings.Count(token, ".") == 2 { + return s.appSessionFromAccessToken(app, token) + } + return gamedomain.LaunchSession{}, xerr.New(xerr.Unauthorized, "token invalid") +} + +func vivaGamesSessionMatches(session gamedomain.LaunchSession, config vivaGamesAdapterConfig, 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 == externalUserID(session, config.UIDMode) || + userID == strings.TrimSpace(session.DisplayUserID) || + userID == strconv.FormatInt(session.UserID, 10) +} + +func vivaGamesOpType(changeAmount int64) (string, int64) { + if changeAmount < 0 { + return "debit", -changeAmount + } + return "credit", changeAmount +} + +func vivaGamesAdapterError(code int, message string, signatureValid bool, providerRequestID string) ([]byte, string, string, bool, string, error) { + raw, contentType := vivaGamesJSON(code, message, map[string]any{}) + return raw, contentType, strconv.Itoa(code), signatureValid, providerRequestID, nil +} + +func vivaGamesJSON(code int, message string, data any) ([]byte, string) { + if data == nil { + data = map[string]any{} + } + return jsonResponse(map[string]any{ + "code": code, + "msg": strings.TrimSpace(message), + "data": data, + }) +} + +func vivaGamesCodeFromError(err error) int { + switch { + case err == nil: + return vivaGamesCodeOK + case xerr.IsCode(err, xerr.InsufficientBalance): + return vivaGamesCodeInsufficientBalance + case xerr.IsCode(err, xerr.SessionExpired), xerr.IsCode(err, xerr.Unauthorized): + return vivaGamesCodeTokenInvalid + case xerr.IsCode(err, xerr.InvalidArgument): + return vivaGamesCodeInvalidArgument + case xerr.IsCode(err, xerr.Conflict): + return vivaGamesCodeGameMaintenance + case xerr.IsCode(err, xerr.NotFound): + return vivaGamesCodeTokenInvalid + default: + return vivaGamesCodeInternalError + } +} + +func vivaGamesMessageFromError(err error) string { + switch vivaGamesCodeFromError(err) { + case vivaGamesCodeInsufficientBalance: + return "balance not enough" + case vivaGamesCodeTokenInvalid: + return "token error" + case vivaGamesCodeInvalidArgument: + return "invalid argument" + case vivaGamesCodeGameMaintenance: + return "game maintenance" + default: + if err != nil && strings.TrimSpace(xerr.MessageOf(err)) != "" { + return xerr.MessageOf(err) + } + return "internal error" + } +} diff --git a/services/gateway-service/internal/app/app.go b/services/gateway-service/internal/app/app.go index a7731e1f..23abc979 100644 --- a/services/gateway-service/internal/app/app.go +++ b/services/gateway-service/internal/app/app.go @@ -99,8 +99,11 @@ func New(cfg config.Config) (*App, error) { var achievementClient client.AchievementClient = client.NewGRPCAchievementClient(activityConn) var registrationRewardClient client.RegistrationRewardClient = client.NewGRPCRegistrationRewardClient(activityConn) var firstRechargeRewardClient client.FirstRechargeRewardClient = client.NewGRPCFirstRechargeRewardClient(activityConn) + var cumulativeRechargeRewardClient client.CumulativeRechargeRewardClient = client.NewGRPCCumulativeRechargeRewardClient(activityConn) var sevenDayCheckInClient client.SevenDayCheckInClient = client.NewGRPCSevenDayCheckInClient(activityConn) var luckyGiftClient client.LuckyGiftClient = client.NewGRPCLuckyGiftClient(activityConn) + var roomTurnoverRewardClient client.RoomTurnoverRewardClient = client.NewGRPCRoomTurnoverRewardClient(activityConn) + var weeklyStarClient client.WeeklyStarClient = client.NewGRPCWeeklyStarClient(activityConn) var broadcastClient client.BroadcastClient = client.NewGRPCBroadcastClient(activityConn) var gameClient client.GameClient = client.NewGRPCGameClient(gameConn) appConfigReader, err := openAppConfigReader(cfg.AppConfig) @@ -163,8 +166,11 @@ func New(cfg config.Config) (*App, error) { handler.SetAchievementClient(achievementClient) handler.SetRegistrationRewardClient(registrationRewardClient) handler.SetFirstRechargeRewardClient(firstRechargeRewardClient) + handler.SetCumulativeRechargeRewardClient(cumulativeRechargeRewardClient) handler.SetSevenDayCheckInClient(sevenDayCheckInClient) handler.SetLuckyGiftClient(luckyGiftClient) + handler.SetRoomTurnoverRewardClient(roomTurnoverRewardClient) + handler.SetWeeklyStarClient(weeklyStarClient) handler.SetBroadcastClient(broadcastClient) handler.SetGameClient(gameClient) handler.SetLeaderboardWalletDB(leaderboardWalletDB) diff --git a/services/gateway-service/internal/client/cumulative_recharge_reward_client.go b/services/gateway-service/internal/client/cumulative_recharge_reward_client.go new file mode 100644 index 00000000..731c8fcb --- /dev/null +++ b/services/gateway-service/internal/client/cumulative_recharge_reward_client.go @@ -0,0 +1,25 @@ +package client + +import ( + "context" + + "google.golang.org/grpc" + activityv1 "hyapp.local/api/proto/activity/v1" +) + +// CumulativeRechargeRewardClient abstracts gateway reads from activity-service cumulative recharge reward APIs. +type CumulativeRechargeRewardClient interface { + GetCumulativeRechargeRewardStatus(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardStatusRequest) (*activityv1.GetCumulativeRechargeRewardStatusResponse, error) +} + +type grpcCumulativeRechargeRewardClient struct { + client activityv1.CumulativeRechargeRewardServiceClient +} + +func NewGRPCCumulativeRechargeRewardClient(conn *grpc.ClientConn) CumulativeRechargeRewardClient { + return &grpcCumulativeRechargeRewardClient{client: activityv1.NewCumulativeRechargeRewardServiceClient(conn)} +} + +func (c *grpcCumulativeRechargeRewardClient) GetCumulativeRechargeRewardStatus(ctx context.Context, req *activityv1.GetCumulativeRechargeRewardStatusRequest) (*activityv1.GetCumulativeRechargeRewardStatusResponse, error) { + return c.client.GetCumulativeRechargeRewardStatus(ctx, req) +} diff --git a/services/gateway-service/internal/client/room_turnover_reward_client.go b/services/gateway-service/internal/client/room_turnover_reward_client.go new file mode 100644 index 00000000..c9a7af6f --- /dev/null +++ b/services/gateway-service/internal/client/room_turnover_reward_client.go @@ -0,0 +1,25 @@ +package client + +import ( + "context" + + "google.golang.org/grpc" + activityv1 "hyapp.local/api/proto/activity/v1" +) + +// RoomTurnoverRewardClient abstracts gateway reads from activity-service room turnover reward APIs. +type RoomTurnoverRewardClient interface { + GetRoomTurnoverRewardStatus(ctx context.Context, req *activityv1.GetRoomTurnoverRewardStatusRequest) (*activityv1.GetRoomTurnoverRewardStatusResponse, error) +} + +type grpcRoomTurnoverRewardClient struct { + client activityv1.RoomTurnoverRewardServiceClient +} + +func NewGRPCRoomTurnoverRewardClient(conn *grpc.ClientConn) RoomTurnoverRewardClient { + return &grpcRoomTurnoverRewardClient{client: activityv1.NewRoomTurnoverRewardServiceClient(conn)} +} + +func (c *grpcRoomTurnoverRewardClient) GetRoomTurnoverRewardStatus(ctx context.Context, req *activityv1.GetRoomTurnoverRewardStatusRequest) (*activityv1.GetRoomTurnoverRewardStatusResponse, error) { + return c.client.GetRoomTurnoverRewardStatus(ctx, req) +} diff --git a/services/gateway-service/internal/client/weekly_star_client.go b/services/gateway-service/internal/client/weekly_star_client.go new file mode 100644 index 00000000..a7d1d246 --- /dev/null +++ b/services/gateway-service/internal/client/weekly_star_client.go @@ -0,0 +1,35 @@ +package client + +import ( + "context" + + "google.golang.org/grpc" + activityv1 "hyapp.local/api/proto/activity/v1" +) + +// WeeklyStarClient abstracts gateway access to activity-service weekly-star APIs. +type WeeklyStarClient interface { + GetWeeklyStarCurrent(ctx context.Context, req *activityv1.GetWeeklyStarCurrentRequest) (*activityv1.GetWeeklyStarCurrentResponse, error) + ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) + ListWeeklyStarHistory(ctx context.Context, req *activityv1.ListWeeklyStarHistoryRequest) (*activityv1.ListWeeklyStarHistoryResponse, error) +} + +type grpcWeeklyStarClient struct { + client activityv1.WeeklyStarServiceClient +} + +func NewGRPCWeeklyStarClient(conn *grpc.ClientConn) WeeklyStarClient { + return &grpcWeeklyStarClient{client: activityv1.NewWeeklyStarServiceClient(conn)} +} + +func (c *grpcWeeklyStarClient) GetWeeklyStarCurrent(ctx context.Context, req *activityv1.GetWeeklyStarCurrentRequest) (*activityv1.GetWeeklyStarCurrentResponse, error) { + return c.client.GetWeeklyStarCurrent(ctx, req) +} + +func (c *grpcWeeklyStarClient) ListWeeklyStarLeaderboard(ctx context.Context, req *activityv1.ListWeeklyStarLeaderboardRequest) (*activityv1.ListWeeklyStarLeaderboardResponse, error) { + return c.client.ListWeeklyStarLeaderboard(ctx, req) +} + +func (c *grpcWeeklyStarClient) ListWeeklyStarHistory(ctx context.Context, req *activityv1.ListWeeklyStarHistoryRequest) (*activityv1.ListWeeklyStarHistoryResponse, error) { + return c.client.ListWeeklyStarHistory(ctx, req) +} diff --git a/services/gateway-service/internal/transport/http/activityapi/cumulative_recharge_reward_handler.go b/services/gateway-service/internal/transport/http/activityapi/cumulative_recharge_reward_handler.go new file mode 100644 index 00000000..8379a6bc --- /dev/null +++ b/services/gateway-service/internal/transport/http/activityapi/cumulative_recharge_reward_handler.go @@ -0,0 +1,225 @@ +package activityapi + +import ( + "net/http" + + activityv1 "hyapp.local/api/proto/activity/v1" + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type cumulativeRechargeRewardUserData struct { + UserID int64 `json:"user_id"` + DisplayUserID string `json:"display_user_id"` + Username string `json:"username"` + Avatar string `json:"avatar"` +} + +type cumulativeRechargeRewardPeriodData struct { + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` +} + +type cumulativeRechargeRewardTierData struct { + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + TierName string `json:"tier_name"` + ThresholdUSDMinor int64 `json:"threshold_usd_minor"` + ResourceGroupID int64 `json:"resource_group_id"` + ResourceGroup *checkinResourceGroupData `json:"resource_group,omitempty"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` + Reached bool `json:"reached"` + Grant *cumulativeRechargeRewardGrantData `json:"grant,omitempty"` +} + +type cumulativeRechargeRewardProgressData struct { + TotalUSDMinor int64 `json:"total_usd_minor"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type cumulativeRechargeRewardGrantData struct { + GrantID string `json:"grant_id"` + EventID string `json:"event_id"` + TransactionID string `json:"transaction_id"` + CommandID string `json:"command_id"` + UserID int64 `json:"user_id"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ThresholdUSDMinor int64 `json:"threshold_usd_minor"` + ResourceGroupID int64 `json:"resource_group_id"` + ReachedUSDMinor int64 `json:"reached_usd_minor"` + QualifyingUSDMinor int64 `json:"qualifying_usd_minor"` + RechargeCoinAmount int64 `json:"recharge_coin_amount"` + 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"` + GrantedAtMS int64 `json:"granted_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type cumulativeRechargeRewardStatusData struct { + Enabled bool `json:"enabled"` + User cumulativeRechargeRewardUserData `json:"user"` + CycleKey string `json:"cycle_key"` + Period cumulativeRechargeRewardPeriodData `json:"period"` + Tiers []cumulativeRechargeRewardTierData `json:"tiers"` + Progress cumulativeRechargeRewardProgressData `json:"progress"` + Grants []cumulativeRechargeRewardGrantData `json:"grants"` + ServerTimeMS int64 `json:"server_time_ms"` +} + +// getCumulativeRechargeRewardStatus 返回当前用户本 UTC 周期累充面板;累计与发放事实只读 activity-service,gateway 只补展示依赖。 +func (h *Handler) getCumulativeRechargeRewardStatus(writer http.ResponseWriter, request *http.Request) { + if h.cumulativeRecharge == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + userID := auth.UserIDFromContext(request.Context()) + resp, err := h.cumulativeRecharge.GetCumulativeRechargeRewardStatus(request.Context(), &activityv1.GetCumulativeRechargeRewardStatusRequest{ + Meta: httpkit.ActivityMeta(request), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + status := resp.GetStatus() + // activity-service 只保存 resource_group_id;gateway 负责补资源组展示素材,避免活动服务依赖 H5 展示结构。 + groups, ok := h.resolveCheckinResourceGroups(writer, request, cumulativeRechargeRewardGroupIDs(status)) + if !ok { + return + } + userData := cumulativeRechargeRewardUserData{UserID: userID} + if h.userProfileClient != nil { + // 用户资料是 H5 展示信息,读取失败时不影响活动金额和发放状态返回。 + if userResp, userErr := h.userProfileClient.BatchGetUsers(request.Context(), &userv1.BatchGetUsersRequest{ + Meta: httpkit.UserMeta(request, ""), + UserIds: []int64{userID}, + }); userErr == nil { + userData = cumulativeRechargeRewardUserFromProto(userResp.GetUsers()[userID], userID) + } + } + + httpkit.WriteOK(writer, request, cumulativeRechargeRewardStatusFromProto(status, userData, groups)) +} + +func cumulativeRechargeRewardStatusFromProto(item *activityv1.CumulativeRechargeRewardStatus, user cumulativeRechargeRewardUserData, groups map[int64]checkinResourceGroupData) cumulativeRechargeRewardStatusData { + if item == nil { + return cumulativeRechargeRewardStatusData{ + User: user, + Tiers: []cumulativeRechargeRewardTierData{}, + Grants: []cumulativeRechargeRewardGrantData{}, + } + } + grants := make([]cumulativeRechargeRewardGrantData, 0, len(item.GetGrants())) + grantsByTierID := make(map[int64]cumulativeRechargeRewardGrantData, len(item.GetGrants())) + for _, grant := range item.GetGrants() { + // grant 按 tier_id 回填到档位,H5 可以直接渲染每个档位的 reached/granted/failed 状态。 + converted := cumulativeRechargeRewardGrantFromProto(grant) + grants = append(grants, converted) + grantsByTierID[converted.TierID] = converted + } + tiers := make([]cumulativeRechargeRewardTierData, 0, len(item.GetConfig().GetTiers())) + for _, tier := range item.GetConfig().GetTiers() { + converted := cumulativeRechargeRewardTierFromProto(tier, item.GetProgress().GetTotalUsdMinor(), groups) + if grant, ok := grantsByTierID[converted.TierID]; ok { + converted.Grant = &grant + } + tiers = append(tiers, converted) + } + return cumulativeRechargeRewardStatusData{ + Enabled: item.GetConfig().GetEnabled(), + User: user, + CycleKey: item.GetCycleKey(), + Period: cumulativeRechargeRewardPeriodData{ + StartMS: item.GetPeriodStartMs(), + EndMS: item.GetPeriodEndMs(), + }, + Tiers: tiers, + Progress: cumulativeRechargeRewardProgressData{ + TotalUSDMinor: item.GetProgress().GetTotalUsdMinor(), + UpdatedAtMS: item.GetProgress().GetUpdatedAtMs(), + }, + Grants: grants, + ServerTimeMS: item.GetServerTimeMs(), + } +} + +func cumulativeRechargeRewardTierFromProto(item *activityv1.CumulativeRechargeRewardTier, totalUSDMinor int64, groups map[int64]checkinResourceGroupData) cumulativeRechargeRewardTierData { + if item == nil { + return cumulativeRechargeRewardTierData{} + } + data := cumulativeRechargeRewardTierData{ + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + TierName: item.GetTierName(), + ThresholdUSDMinor: item.GetThresholdUsdMinor(), + ResourceGroupID: item.GetResourceGroupId(), + Status: item.GetStatus(), + SortOrder: item.GetSortOrder(), + Reached: totalUSDMinor >= item.GetThresholdUsdMinor(), + } + if group, ok := groups[item.GetResourceGroupId()]; ok { + data.ResourceGroup = &group + } + return data +} + +func cumulativeRechargeRewardGrantFromProto(item *activityv1.CumulativeRechargeRewardGrant) cumulativeRechargeRewardGrantData { + if item == nil { + return cumulativeRechargeRewardGrantData{} + } + return cumulativeRechargeRewardGrantData{ + GrantID: item.GetGrantId(), + EventID: item.GetEventId(), + TransactionID: item.GetTransactionId(), + CommandID: item.GetCommandId(), + UserID: item.GetUserId(), + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + ThresholdUSDMinor: item.GetThresholdUsdMinor(), + ResourceGroupID: item.GetResourceGroupId(), + ReachedUSDMinor: item.GetReachedUsdMinor(), + QualifyingUSDMinor: item.GetQualifyingUsdMinor(), + RechargeCoinAmount: item.GetRechargeCoinAmount(), + RechargeType: item.GetRechargeType(), + Status: item.GetStatus(), + WalletCommandID: item.GetWalletCommandId(), + WalletGrantID: item.GetWalletGrantId(), + FailureReason: item.GetFailureReason(), + GrantedAtMS: item.GetGrantedAtMs(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } +} + +func cumulativeRechargeRewardGroupIDs(item *activityv1.CumulativeRechargeRewardStatus) []int64 { + if item == nil || item.GetConfig() == nil { + return nil + } + ids := make([]int64, 0, len(item.GetConfig().GetTiers())) + for _, tier := range item.GetConfig().GetTiers() { + if tier.GetResourceGroupId() > 0 { + ids = append(ids, tier.GetResourceGroupId()) + } + } + return ids +} + +func cumulativeRechargeRewardUserFromProto(item *userv1.User, fallbackUserID int64) cumulativeRechargeRewardUserData { + if item == nil { + return cumulativeRechargeRewardUserData{UserID: fallbackUserID} + } + return cumulativeRechargeRewardUserData{ + UserID: item.GetUserId(), + DisplayUserID: item.GetDisplayUserId(), + Username: item.GetUsername(), + Avatar: item.GetAvatar(), + } +} diff --git a/services/gateway-service/internal/transport/http/activityapi/handler.go b/services/gateway-service/internal/transport/http/activityapi/handler.go index 144ab475..20444f76 100644 --- a/services/gateway-service/internal/transport/http/activityapi/handler.go +++ b/services/gateway-service/internal/transport/http/activityapi/handler.go @@ -19,8 +19,11 @@ type Handler struct { walletDB *sql.DB registrationReward client.RegistrationRewardClient firstRechargeReward client.FirstRechargeRewardClient + cumulativeRecharge client.CumulativeRechargeRewardClient sevenDayCheckIn client.SevenDayCheckInClient luckyGift client.LuckyGiftClient + roomTurnoverReward client.RoomTurnoverRewardClient + weeklyStar client.WeeklyStarClient } type Config struct { @@ -33,8 +36,11 @@ type Config struct { WalletDB *sql.DB RegistrationReward client.RegistrationRewardClient FirstRechargeReward client.FirstRechargeRewardClient + CumulativeRecharge client.CumulativeRechargeRewardClient SevenDayCheckIn client.SevenDayCheckInClient LuckyGift client.LuckyGiftClient + RoomTurnoverReward client.RoomTurnoverRewardClient + WeeklyStar client.WeeklyStarClient } func New(config Config) *Handler { @@ -48,21 +54,29 @@ func New(config Config) *Handler { walletDB: config.WalletDB, registrationReward: config.RegistrationReward, firstRechargeReward: config.FirstRechargeReward, + cumulativeRecharge: config.CumulativeRecharge, sevenDayCheckIn: config.SevenDayCheckIn, luckyGift: config.LuckyGift, + roomTurnoverReward: config.RoomTurnoverReward, + weeklyStar: config.WeeklyStar, } } func (h *Handler) TaskHandlers() httproutes.TaskHandlers { return httproutes.TaskHandlers{ - ListTaskTabs: h.listTaskTabs, - ClaimTaskReward: h.claimTaskReward, - GetRegistrationRewardEligibility: h.getRegistrationRewardEligibility, - GetFirstRechargeRewardStatus: h.getFirstRechargeRewardStatus, - GetSevenDayCheckInStatus: h.getSevenDayCheckInStatus, - SignSevenDayCheckIn: h.signSevenDayCheckIn, - ListUserLeaderboards: h.listUserLeaderboards, - CheckLuckyGift: h.checkLuckyGift, + ListTaskTabs: h.listTaskTabs, + ClaimTaskReward: h.claimTaskReward, + GetRegistrationRewardEligibility: h.getRegistrationRewardEligibility, + GetFirstRechargeRewardStatus: h.getFirstRechargeRewardStatus, + GetCumulativeRechargeRewardStatus: h.getCumulativeRechargeRewardStatus, + GetSevenDayCheckInStatus: h.getSevenDayCheckInStatus, + SignSevenDayCheckIn: h.signSevenDayCheckIn, + ListUserLeaderboards: h.listUserLeaderboards, + CheckLuckyGift: h.checkLuckyGift, + GetRoomTurnoverRewardStatus: h.getRoomTurnoverRewardStatus, + GetWeeklyStarCurrent: h.getWeeklyStarCurrent, + ListWeeklyStarLeaderboard: h.listWeeklyStarLeaderboard, + ListWeeklyStarHistory: h.listWeeklyStarHistory, } } diff --git a/services/gateway-service/internal/transport/http/activityapi/room_turnover_reward_handler.go b/services/gateway-service/internal/transport/http/activityapi/room_turnover_reward_handler.go new file mode 100644 index 00000000..dca15893 --- /dev/null +++ b/services/gateway-service/internal/transport/http/activityapi/room_turnover_reward_handler.go @@ -0,0 +1,237 @@ +package activityapi + +import ( + "net/http" + + activityv1 "hyapp.local/api/proto/activity/v1" + roomv1 "hyapp.local/api/proto/room/v1" + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type roomTurnoverRewardTierData struct { + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + TierName string `json:"tier_name"` + ThresholdCoinSpent int64 `json:"threshold_coin_spent"` + RewardCoinAmount int64 `json:"reward_coin_amount"` + Status string `json:"status"` + SortOrder int32 `json:"sort_order"` +} + +type roomTurnoverRewardUserData struct { + UserID int64 `json:"user_id"` + DisplayUserID string `json:"display_user_id"` + Username string `json:"username"` + Avatar string `json:"avatar"` +} + +type roomTurnoverRewardRoomData struct { + HasRoom bool `json:"has_room"` + RoomID string `json:"room_id"` + OwnerUserID int64 `json:"owner_user_id"` + Title string `json:"title"` + CoverURL string `json:"cover_url"` +} + +type roomTurnoverRewardPeriodData struct { + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` +} + +type roomTurnoverRewardSettlementData struct { + SettlementID string `json:"settlement_id"` + RoomID string `json:"room_id"` + OwnerUserID int64 `json:"owner_user_id"` + PeriodStartMS int64 `json:"period_start_ms"` + PeriodEndMS int64 `json:"period_end_ms"` + CoinSpent int64 `json:"coin_spent"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + ThresholdCoinSpent int64 `json:"threshold_coin_spent"` + RewardCoinAmount int64 `json:"reward_coin_amount"` + Status string `json:"status"` + WalletCommandID string `json:"wallet_command_id"` + WalletTransactionID string `json:"wallet_transaction_id"` + FailureReason string `json:"failure_reason"` + SettledAtMS int64 `json:"settled_at_ms"` + CreatedAtMS int64 `json:"created_at_ms"` + UpdatedAtMS int64 `json:"updated_at_ms"` +} + +type roomTurnoverRewardStatusData struct { + Enabled bool `json:"enabled"` + User roomTurnoverRewardUserData `json:"user"` + Room roomTurnoverRewardRoomData `json:"room"` + Period roomTurnoverRewardPeriodData `json:"period"` + Tiers []roomTurnoverRewardTierData `json:"tiers"` + CurrentCoinSpent int64 `json:"current_coin_spent"` + ExpectedRewardCoinAmount int64 `json:"expected_reward_coin_amount"` + MatchedTier *roomTurnoverRewardTierData `json:"matched_tier,omitempty"` + LatestSettlement *roomTurnoverRewardSettlementData `json:"latest_settlement,omitempty"` + ServerTimeMS int64 `json:"server_time_ms"` +} + +func (h *Handler) getRoomTurnoverRewardStatus(writer http.ResponseWriter, request *http.Request) { + if h.roomTurnoverReward == nil || h.roomQueryClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + + userID := auth.UserIDFromContext(request.Context()) + roomData := roomTurnoverRewardRoomData{OwnerUserID: userID} + // App 接口按“当前登录用户自己的房间”展示活动进度;gateway 只编排 room-service 查询,不在本服务缓存房间归属。 + roomResp, err := h.roomQueryClient.GetMyRoom(request.Context(), &roomv1.GetMyRoomRequest{ + Meta: httpkit.RoomMeta(request, "", ""), + OwnerUserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + if roomResp.GetHasRoom() { + roomData = roomTurnoverRewardRoomFromProto(roomResp.GetRoom(), userID) + } + + // activity-service 只需要房间 ID 和 owner_user_id 计算当前周期流水与预计奖励;用户头像、昵称等展示字段由 gateway 统一补齐。 + resp, err := h.roomTurnoverReward.GetRoomTurnoverRewardStatus(request.Context(), &activityv1.GetRoomTurnoverRewardStatusRequest{ + Meta: httpkit.ActivityMeta(request), + UserId: userID, + RoomId: roomData.RoomID, + OwnerUserId: roomData.OwnerUserID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + + userData := roomTurnoverRewardUserData{UserID: userID} + if h.userProfileClient != nil { + // 用户资料只服务 H5 展示;读取失败时奖励状态仍应可用,避免头像依赖放大活动接口故障面。 + if userResp, userErr := h.userProfileClient.BatchGetUsers(request.Context(), &userv1.BatchGetUsersRequest{ + Meta: httpkit.UserMeta(request, ""), + UserIds: []int64{userID}, + }); userErr == nil { + userData = roomTurnoverRewardUserFromProto(userResp.GetUsers()[userID], userID) + } + } + + httpkit.WriteOK(writer, request, roomTurnoverRewardStatusFromProto(resp.GetStatus(), roomData, userData)) +} + +func roomTurnoverRewardStatusFromProto(item *activityv1.RoomTurnoverRewardStatus, room roomTurnoverRewardRoomData, user roomTurnoverRewardUserData) roomTurnoverRewardStatusData { + if item == nil { + return roomTurnoverRewardStatusData{ + User: user, + Room: room, + Tiers: []roomTurnoverRewardTierData{}, + } + } + tiers := make([]roomTurnoverRewardTierData, 0, len(item.GetConfig().GetTiers())) + for _, tier := range item.GetConfig().GetTiers() { + tiers = append(tiers, roomTurnoverRewardTierFromProto(tier)) + } + var matched *roomTurnoverRewardTierData + if item.GetMatchedTier() != nil { + // matched_tier 使用指针是为了区分“未达档位”和“达到了 ID 为 0 的空值”,前端可直接按 null 判断未命中。 + converted := roomTurnoverRewardTierFromProto(item.GetMatchedTier()) + matched = &converted + } + var latest *roomTurnoverRewardSettlementData + if item.GetLatestSettlement() != nil { + // latest_settlement 允许跨周期展示上一周发奖状态;当前周期流水清零后,H5 仍能提示最近一次结算结果。 + converted := roomTurnoverRewardSettlementFromProto(item.GetLatestSettlement()) + latest = &converted + } + room.RoomID = item.GetRoomId() + room.OwnerUserID = item.GetOwnerUserId() + if room.OwnerUserID == 0 { + // 没有房间或 activity-service 未返回 owner 时,保留当前登录用户作为展示兜底,避免 H5 出现空 owner。 + room.OwnerUserID = user.UserID + } + return roomTurnoverRewardStatusData{ + Enabled: item.GetConfig().GetEnabled(), + User: user, + Room: room, + Period: roomTurnoverRewardPeriodData{ + StartMS: item.GetPeriodStartMs(), + EndMS: item.GetPeriodEndMs(), + }, + Tiers: tiers, + CurrentCoinSpent: item.GetCurrentCoinSpent(), + ExpectedRewardCoinAmount: item.GetExpectedRewardCoinAmount(), + MatchedTier: matched, + LatestSettlement: latest, + ServerTimeMS: item.GetServerTimeMs(), + } +} + +func roomTurnoverRewardRoomFromProto(item *roomv1.RoomListItem, fallbackOwnerUserID int64) roomTurnoverRewardRoomData { + if item == nil { + return roomTurnoverRewardRoomData{OwnerUserID: fallbackOwnerUserID} + } + ownerID := item.GetOwnerUserId() + if ownerID == 0 { + ownerID = fallbackOwnerUserID + } + return roomTurnoverRewardRoomData{ + HasRoom: true, + RoomID: item.GetRoomId(), + OwnerUserID: ownerID, + Title: item.GetTitle(), + CoverURL: item.GetCoverUrl(), + } +} + +func roomTurnoverRewardUserFromProto(item *userv1.User, fallbackUserID int64) roomTurnoverRewardUserData { + if item == nil { + return roomTurnoverRewardUserData{UserID: fallbackUserID} + } + return roomTurnoverRewardUserData{ + UserID: item.GetUserId(), + DisplayUserID: item.GetDisplayUserId(), + Username: item.GetUsername(), + Avatar: item.GetAvatar(), + } +} + +func roomTurnoverRewardTierFromProto(item *activityv1.RoomTurnoverRewardTier) roomTurnoverRewardTierData { + if item == nil { + return roomTurnoverRewardTierData{} + } + return roomTurnoverRewardTierData{ + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + TierName: item.GetTierName(), + ThresholdCoinSpent: item.GetThresholdCoinSpent(), + RewardCoinAmount: item.GetRewardCoinAmount(), + Status: item.GetStatus(), + SortOrder: item.GetSortOrder(), + } +} + +func roomTurnoverRewardSettlementFromProto(item *activityv1.RoomTurnoverRewardSettlement) roomTurnoverRewardSettlementData { + if item == nil { + return roomTurnoverRewardSettlementData{} + } + return roomTurnoverRewardSettlementData{ + SettlementID: item.GetSettlementId(), + RoomID: item.GetRoomId(), + OwnerUserID: item.GetOwnerUserId(), + PeriodStartMS: item.GetPeriodStartMs(), + PeriodEndMS: item.GetPeriodEndMs(), + CoinSpent: item.GetCoinSpent(), + TierID: item.GetTierId(), + TierCode: item.GetTierCode(), + ThresholdCoinSpent: item.GetThresholdCoinSpent(), + RewardCoinAmount: item.GetRewardCoinAmount(), + Status: item.GetStatus(), + WalletCommandID: item.GetWalletCommandId(), + WalletTransactionID: item.GetWalletTransactionId(), + FailureReason: item.GetFailureReason(), + SettledAtMS: item.GetSettledAtMs(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } +} diff --git a/services/gateway-service/internal/transport/http/activityapi/weekly_star_handler.go b/services/gateway-service/internal/transport/http/activityapi/weekly_star_handler.go new file mode 100644 index 00000000..febb39a2 --- /dev/null +++ b/services/gateway-service/internal/transport/http/activityapi/weekly_star_handler.go @@ -0,0 +1,282 @@ +package activityapi + +import ( + "net/http" + "strconv" + "strings" + + activityv1 "hyapp.local/api/proto/activity/v1" + userv1 "hyapp.local/api/proto/user/v1" + "hyapp/services/gateway-service/internal/auth" + "hyapp/services/gateway-service/internal/transport/http/httpkit" +) + +type weeklyStarCycleData struct { + CycleID string `json:"cycle_id"` + ActivityCode string `json:"activity_code"` + RegionID int64 `json:"region_id"` + Title string `json:"title"` + Status string `json:"status"` + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` + Gifts []weeklyStarGiftData `json:"gifts"` + Rewards []weeklyStarRewardData `json:"rewards"` + SettledAtMS int64 `json:"settled_at_ms,omitempty"` + CreatedAtMS int64 `json:"created_at_ms,omitempty"` + UpdatedAtMS int64 `json:"updated_at_ms,omitempty"` +} + +type weeklyStarGiftData struct { + GiftID string `json:"gift_id"` + SortOrder int32 `json:"sort_order"` +} + +type weeklyStarRewardData struct { + RankNo int32 `json:"rank_no"` + ResourceGroupID int64 `json:"resource_group_id"` +} + +type weeklyStarEntryData struct { + RankNo int32 `json:"rank_no"` + UserID string `json:"user_id"` + Score int64 `json:"score"` + FirstScoredAtMS int64 `json:"first_scored_at_ms"` + LastScoredAtMS int64 `json:"last_scored_at_ms"` + User *weeklyStarUserData `json:"user,omitempty"` +} + +type weeklyStarUserData struct { + UserID string `json:"user_id"` + DisplayUserID string `json:"display_user_id"` + Username string `json:"username"` + Avatar string `json:"avatar"` + RegionID int64 `json:"region_id,omitempty"` +} + +type weeklyStarCurrentData struct { + Cycle *weeklyStarCycleData `json:"cycle,omitempty"` + TopEntries []weeklyStarEntryData `json:"top_entries"` + MyEntry *weeklyStarEntryData `json:"my_entry,omitempty"` + ServerTimeMS int64 `json:"server_time_ms"` +} + +type weeklyStarLeaderboardData struct { + Cycle *weeklyStarCycleData `json:"cycle,omitempty"` + Entries []weeklyStarEntryData `json:"entries"` + NextPageToken string `json:"next_page_token,omitempty"` + Total int64 `json:"total"` +} + +type weeklyStarHistoryData struct { + Cycles []weeklyStarHistoryCycleData `json:"cycles"` + ServerTimeMS int64 `json:"server_time_ms"` +} + +type weeklyStarHistoryCycleData struct { + Cycle *weeklyStarCycleData `json:"cycle,omitempty"` + TopEntries []weeklyStarEntryData `json:"top_entries"` +} + +// getWeeklyStarCurrent returns the current region/default weekly-star cycle for the logged-in user. +func (h *Handler) getWeeklyStarCurrent(writer http.ResponseWriter, request *http.Request) { + if h.weeklyStar == nil || h.userProfileClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + userID := auth.UserIDFromContext(request.Context()) + regionID, ok := h.resolveWeeklyStarRegionID(writer, request, userID) + if !ok { + return + } + resp, err := h.weeklyStar.GetWeeklyStarCurrent(request.Context(), &activityv1.GetWeeklyStarCurrentRequest{ + Meta: httpkit.ActivityMeta(request), + UserId: userID, + RegionId: regionID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + users := h.resolveWeeklyStarUsers(request, weeklyStarUserIDs(resp.GetTopEntries(), resp.GetMyEntry())) + data := weeklyStarCurrentData{ + Cycle: weeklyStarCycleFromProto(resp.GetCycle()), + TopEntries: weeklyStarEntriesFromProto(resp.GetTopEntries(), users), + ServerTimeMS: resp.GetServerTimeMs(), + } + if resp.GetMyEntry() != nil { + entry := weeklyStarEntryFromProto(resp.GetMyEntry(), users) + data.MyEntry = &entry + } + httpkit.WriteOK(writer, request, data) +} + +// listWeeklyStarLeaderboard pages through the selected cycle or current region cycle. +func (h *Handler) listWeeklyStarLeaderboard(writer http.ResponseWriter, request *http.Request) { + if h.weeklyStar == nil || h.userProfileClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + userID := auth.UserIDFromContext(request.Context()) + regionID, ok := h.resolveWeeklyStarRegionID(writer, request, userID) + if !ok { + return + } + resp, err := h.weeklyStar.ListWeeklyStarLeaderboard(request.Context(), &activityv1.ListWeeklyStarLeaderboardRequest{ + Meta: httpkit.ActivityMeta(request), + CycleId: strings.TrimSpace(request.URL.Query().Get("cycle_id")), + RegionId: regionID, + PageSize: int32(queryInt(request, "page_size", 50)), + PageToken: strings.TrimSpace(request.URL.Query().Get("page_token")), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + users := h.resolveWeeklyStarUsers(request, weeklyStarUserIDs(resp.GetEntries(), nil)) + httpkit.WriteOK(writer, request, weeklyStarLeaderboardData{ + Cycle: weeklyStarCycleFromProto(resp.GetCycle()), + Entries: weeklyStarEntriesFromProto(resp.GetEntries(), users), + NextPageToken: resp.GetNextPageToken(), + Total: resp.GetTotal(), + }) +} + +// listWeeklyStarHistory returns recent settled cycles for the current user's region with default fallback. +func (h *Handler) listWeeklyStarHistory(writer http.ResponseWriter, request *http.Request) { + if h.weeklyStar == nil || h.userProfileClient == nil { + httpkit.WriteError(writer, request, http.StatusBadGateway, httpkit.CodeUpstreamError, "upstream service error") + return + } + userID := auth.UserIDFromContext(request.Context()) + regionID, ok := h.resolveWeeklyStarRegionID(writer, request, userID) + if !ok { + return + } + resp, err := h.weeklyStar.ListWeeklyStarHistory(request.Context(), &activityv1.ListWeeklyStarHistoryRequest{ + Meta: httpkit.ActivityMeta(request), + RegionId: regionID, + Limit: int32(queryInt(request, "limit", 10)), + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } + ids := make([]int64, 0) + for _, cycle := range resp.GetCycles() { + ids = append(ids, weeklyStarUserIDs(cycle.GetTopEntries(), nil)...) + } + users := h.resolveWeeklyStarUsers(request, ids) + cycles := make([]weeklyStarHistoryCycleData, 0, len(resp.GetCycles())) + for _, item := range resp.GetCycles() { + cycles = append(cycles, weeklyStarHistoryCycleData{ + Cycle: weeklyStarCycleFromProto(item.GetCycle()), + TopEntries: weeklyStarEntriesFromProto(item.GetTopEntries(), users), + }) + } + httpkit.WriteOK(writer, request, weeklyStarHistoryData{Cycles: cycles, ServerTimeMS: resp.GetServerTimeMs()}) +} + +func (h *Handler) resolveWeeklyStarRegionID(writer http.ResponseWriter, request *http.Request, userID int64) (int64, bool) { + resp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ + Meta: httpkit.UserMeta(request, ""), + UserId: userID, + }) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return 0, false + } + return resp.GetUser().GetRegionId(), true +} + +func (h *Handler) resolveWeeklyStarUsers(request *http.Request, ids []int64) map[int64]weeklyStarUserData { + users := make(map[int64]weeklyStarUserData) + ids = uniquePositiveIDs(ids) + if len(ids) == 0 || h.userProfileClient == nil { + return users + } + resp, err := h.userProfileClient.BatchGetUsers(request.Context(), &userv1.BatchGetUsersRequest{ + Meta: httpkit.UserMeta(request, ""), + UserIds: ids, + }) + if err != nil { + return users + } + for _, item := range resp.GetUsers() { + users[item.GetUserId()] = weeklyStarUserData{ + UserID: strconv.FormatInt(item.GetUserId(), 10), + DisplayUserID: item.GetDisplayUserId(), + Username: item.GetUsername(), + Avatar: item.GetAvatar(), + RegionID: item.GetRegionId(), + } + } + return users +} + +func weeklyStarCycleFromProto(item *activityv1.WeeklyStarCycle) *weeklyStarCycleData { + if item == nil { + return nil + } + cycle := &weeklyStarCycleData{ + CycleID: item.GetCycleId(), + ActivityCode: item.GetActivityCode(), + RegionID: item.GetRegionId(), + Title: item.GetTitle(), + Status: item.GetStatus(), + StartMS: item.GetStartMs(), + EndMS: item.GetEndMs(), + Gifts: make([]weeklyStarGiftData, 0, len(item.GetGifts())), + Rewards: make([]weeklyStarRewardData, 0, len(item.GetRewards())), + SettledAtMS: item.GetSettledAtMs(), + CreatedAtMS: item.GetCreatedAtMs(), + UpdatedAtMS: item.GetUpdatedAtMs(), + } + for _, gift := range item.GetGifts() { + cycle.Gifts = append(cycle.Gifts, weeklyStarGiftData{GiftID: gift.GetGiftId(), SortOrder: gift.GetSortOrder()}) + } + for _, reward := range item.GetRewards() { + cycle.Rewards = append(cycle.Rewards, weeklyStarRewardData{RankNo: reward.GetRankNo(), ResourceGroupID: reward.GetResourceGroupId()}) + } + return cycle +} + +func weeklyStarEntriesFromProto(items []*activityv1.WeeklyStarLeaderboardEntry, users map[int64]weeklyStarUserData) []weeklyStarEntryData { + entries := make([]weeklyStarEntryData, 0, len(items)) + for _, item := range items { + entries = append(entries, weeklyStarEntryFromProto(item, users)) + } + return entries +} + +func weeklyStarEntryFromProto(item *activityv1.WeeklyStarLeaderboardEntry, users map[int64]weeklyStarUserData) weeklyStarEntryData { + entry := weeklyStarEntryData{ + RankNo: item.GetRankNo(), + UserID: strconv.FormatInt(item.GetUserId(), 10), + Score: item.GetScore(), + FirstScoredAtMS: item.GetFirstScoredAtMs(), + LastScoredAtMS: item.GetLastScoredAtMs(), + } + if user, ok := users[item.GetUserId()]; ok { + entry.User = &user + } + return entry +} + +func weeklyStarUserIDs(items []*activityv1.WeeklyStarLeaderboardEntry, extra *activityv1.WeeklyStarLeaderboardEntry) []int64 { + ids := make([]int64, 0, len(items)+1) + for _, item := range items { + ids = append(ids, item.GetUserId()) + } + if extra != nil { + ids = append(ids, extra.GetUserId()) + } + return ids +} + +func queryInt(request *http.Request, key string, fallback int) int { + value, err := strconv.Atoi(strings.TrimSpace(request.URL.Query().Get(key))) + if err != nil || value <= 0 { + return fallback + } + return value +} diff --git a/services/gateway-service/internal/transport/http/handler.go b/services/gateway-service/internal/transport/http/handler.go index b3dea9a3..91d55542 100644 --- a/services/gateway-service/internal/transport/http/handler.go +++ b/services/gateway-service/internal/transport/http/handler.go @@ -40,8 +40,11 @@ type Handler struct { achievementClient client.AchievementClient registrationReward client.RegistrationRewardClient firstRechargeReward client.FirstRechargeRewardClient + cumulativeRecharge client.CumulativeRechargeRewardClient sevenDayCheckIn client.SevenDayCheckInClient luckyGift client.LuckyGiftClient + roomTurnoverReward client.RoomTurnoverRewardClient + weeklyStar client.WeeklyStarClient broadcastClient client.BroadcastClient gameClient client.GameClient appConfigReader appapi.ConfigReader @@ -212,6 +215,11 @@ func (h *Handler) SetFirstRechargeRewardClient(firstRechargeReward client.FirstR h.firstRechargeReward = firstRechargeReward } +// SetCumulativeRechargeRewardClient 注入 activity-service 累充奖励查询 client。 +func (h *Handler) SetCumulativeRechargeRewardClient(cumulativeRecharge client.CumulativeRechargeRewardClient) { + h.cumulativeRecharge = cumulativeRecharge +} + // SetSevenDayCheckInClient 注入 activity-service 七日签到 client。 func (h *Handler) SetSevenDayCheckInClient(sevenDayCheckIn client.SevenDayCheckInClient) { h.sevenDayCheckIn = sevenDayCheckIn @@ -222,6 +230,16 @@ func (h *Handler) SetLuckyGiftClient(luckyGift client.LuckyGiftClient) { h.luckyGift = luckyGift } +// SetRoomTurnoverRewardClient 注入 activity-service 房间流水奖励查询 client。 +func (h *Handler) SetRoomTurnoverRewardClient(roomTurnoverReward client.RoomTurnoverRewardClient) { + h.roomTurnoverReward = roomTurnoverReward +} + +// SetWeeklyStarClient 注入 activity-service 周星活动 client。 +func (h *Handler) SetWeeklyStarClient(weeklyStar client.WeeklyStarClient) { + h.weeklyStar = weeklyStar +} + // SetBroadcastClient 注入 activity-service 播报群成员关系 client。 func (h *Handler) SetBroadcastClient(broadcastClient client.BroadcastClient) { h.broadcastClient = broadcastClient diff --git a/services/gateway-service/internal/transport/http/httproutes/router.go b/services/gateway-service/internal/transport/http/httproutes/router.go index 445fa9bb..c781eab7 100644 --- a/services/gateway-service/internal/transport/http/httproutes/router.go +++ b/services/gateway-service/internal/transport/http/httproutes/router.go @@ -159,14 +159,19 @@ type MessageHandlers struct { } type TaskHandlers struct { - ListTaskTabs http.HandlerFunc - ClaimTaskReward http.HandlerFunc - GetRegistrationRewardEligibility http.HandlerFunc - GetFirstRechargeRewardStatus http.HandlerFunc - GetSevenDayCheckInStatus http.HandlerFunc - SignSevenDayCheckIn http.HandlerFunc - ListUserLeaderboards http.HandlerFunc - CheckLuckyGift http.HandlerFunc + ListTaskTabs http.HandlerFunc + ClaimTaskReward http.HandlerFunc + GetRegistrationRewardEligibility http.HandlerFunc + GetFirstRechargeRewardStatus http.HandlerFunc + GetCumulativeRechargeRewardStatus http.HandlerFunc + GetSevenDayCheckInStatus http.HandlerFunc + SignSevenDayCheckIn http.HandlerFunc + ListUserLeaderboards http.HandlerFunc + CheckLuckyGift http.HandlerFunc + GetRoomTurnoverRewardStatus http.HandlerFunc + GetWeeklyStarCurrent http.HandlerFunc + ListWeeklyStarLeaderboard http.HandlerFunc + ListWeeklyStarHistory http.HandlerFunc } type LevelHandlers struct { @@ -409,9 +414,14 @@ 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/cumulative-recharge-reward", http.MethodGet, h.GetCumulativeRechargeRewardStatus) 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) + r.profile("/activities/room-turnover-reward", http.MethodGet, h.GetRoomTurnoverRewardStatus) + r.profile("/activities/weekly-star/current", http.MethodGet, h.GetWeeklyStarCurrent) + r.profile("/activities/weekly-star/leaderboard", http.MethodGet, h.ListWeeklyStarLeaderboard) + r.profile("/activities/weekly-star/history", http.MethodGet, h.ListWeeklyStarHistory) // App 侧接口保持稳定;内部仍按 pool_id 走当前 v2 规则、抽奖和返奖实现。 r.profile("/activities/lucky-gifts/check", http.MethodPost, h.CheckLuckyGift) r.profile("/tasks/tabs", http.MethodGet, h.ListTaskTabs) diff --git a/services/gateway-service/internal/transport/http/router.go b/services/gateway-service/internal/transport/http/router.go index bc0a7ad7..83cbfe8b 100644 --- a/services/gateway-service/internal/transport/http/router.go +++ b/services/gateway-service/internal/transport/http/router.go @@ -74,8 +74,11 @@ func (h *Handler) Routes(jwtVerifier *auth.Verifier) http.Handler { WalletDB: h.leaderboardWalletDB, RegistrationReward: h.registrationReward, FirstRechargeReward: h.firstRechargeReward, + CumulativeRecharge: h.cumulativeRecharge, SevenDayCheckIn: h.sevenDayCheckIn, LuckyGift: h.luckyGift, + RoomTurnoverReward: h.roomTurnoverReward, + WeeklyStar: h.weeklyStar, }) gameAPI := gameapi.New(gameapi.Config{ GameClient: h.gameClient, diff --git a/services/statistics-service/configs/config.docker.yaml b/services/statistics-service/configs/config.docker.yaml index b46a2e93..11e5b9e2 100644 --- a/services/statistics-service/configs/config.docker.yaml +++ b/services/statistics-service/configs/config.docker.yaml @@ -4,6 +4,7 @@ environment: local health_http_addr: ":13110" query_http_addr: ":13010" mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_statistics?parseTime=true&charset=utf8mb4&loc=UTC&multiStatements=true" +activity_mysql_dsn: "hyapp:hyapp@tcp(mysql:3306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC" rocketmq: enabled: true name_servers: ["rocketmq-namesrv:9876"] diff --git a/services/statistics-service/configs/config.tencent.example.yaml b/services/statistics-service/configs/config.tencent.example.yaml index d8529993..679262f7 100644 --- a/services/statistics-service/configs/config.tencent.example.yaml +++ b/services/statistics-service/configs/config.tencent.example.yaml @@ -4,6 +4,7 @@ environment: prod health_http_addr: ":13110" query_http_addr: ":13010" mysql_dsn: "${STATISTICS_MYSQL_DSN}" +activity_mysql_dsn: "${ACTIVITY_MYSQL_DSN}" rocketmq: enabled: true name_servers: [] diff --git a/services/statistics-service/configs/config.yaml b/services/statistics-service/configs/config.yaml index 4c47bf6b..c313274f 100644 --- a/services/statistics-service/configs/config.yaml +++ b/services/statistics-service/configs/config.yaml @@ -4,6 +4,7 @@ environment: local health_http_addr: ":13110" query_http_addr: ":13010" mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_statistics?parseTime=true&charset=utf8mb4&loc=UTC&multiStatements=true" +activity_mysql_dsn: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC" rocketmq: enabled: false name_servers: [] diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index d828b5ee..646c4706 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -36,7 +36,7 @@ type App struct { func New(cfg config.Config) (*App, error) { startupCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - repo, err := mysqlstorage.Open(startupCtx, cfg.MySQLDSN) + repo, err := mysqlstorage.Open(startupCtx, cfg.MySQLDSN, cfg.ActivityMySQLDSN) if err != nil { return nil, err } diff --git a/services/statistics-service/internal/config/config.go b/services/statistics-service/internal/config/config.go index 414b5d87..929d11f4 100644 --- a/services/statistics-service/internal/config/config.go +++ b/services/statistics-service/internal/config/config.go @@ -10,14 +10,15 @@ import ( // Config describes statistics-service dependencies and MQ subscriptions. type Config struct { - ServiceName string `yaml:"service_name"` - NodeID string `yaml:"node_id"` - Environment string `yaml:"environment"` - HealthHTTPAddr string `yaml:"health_http_addr"` - QueryHTTPAddr string `yaml:"query_http_addr"` - MySQLDSN string `yaml:"mysql_dsn"` - RocketMQ RocketMQConfig `yaml:"rocketmq"` - Log logx.Config `yaml:"log"` + ServiceName string `yaml:"service_name"` + NodeID string `yaml:"node_id"` + Environment string `yaml:"environment"` + HealthHTTPAddr string `yaml:"health_http_addr"` + QueryHTTPAddr string `yaml:"query_http_addr"` + MySQLDSN string `yaml:"mysql_dsn"` + ActivityMySQLDSN string `yaml:"activity_mysql_dsn"` + RocketMQ RocketMQConfig `yaml:"rocketmq"` + Log logx.Config `yaml:"log"` } type RocketMQConfig struct { @@ -44,13 +45,14 @@ type ConsumerMQConfig struct { func Default() Config { return Config{ - ServiceName: "statistics-service", - NodeID: "statistics-local", - Environment: "local", - HealthHTTPAddr: ":13110", - QueryHTTPAddr: ":13010", - MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_statistics?parseTime=true&charset=utf8mb4&loc=UTC&multiStatements=true", - RocketMQ: defaultRocketMQConfig(), + ServiceName: "statistics-service", + NodeID: "statistics-local", + Environment: "local", + HealthHTTPAddr: ":13110", + QueryHTTPAddr: ":13010", + MySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_statistics?parseTime=true&charset=utf8mb4&loc=UTC&multiStatements=true", + ActivityMySQLDSN: "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC", + RocketMQ: defaultRocketMQConfig(), Log: logx.Config{ Level: "info", Format: "json", @@ -86,6 +88,8 @@ func Load(path string) (Config, error) { if cfg.QueryHTTPAddr == "" { cfg.QueryHTTPAddr = ":13010" } + cfg.MySQLDSN = strings.TrimSpace(cfg.MySQLDSN) + cfg.ActivityMySQLDSN = strings.TrimSpace(cfg.ActivityMySQLDSN) cfg.RocketMQ = normalizeRocketMQConfig(cfg.RocketMQ) if cfg.RocketMQ.Enabled { if len(cfg.RocketMQ.NameServers) == 0 && cfg.RocketMQ.NameServerDomain == "" { diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index eda6d6f2..999e080d 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -114,9 +114,6 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov if channelRechargeUSDMinor > overview.RechargeUSDMinor { overview.RechargeUSDMinor = channelRechargeUSDMinor } - overview.LuckyGiftProfit = overview.LuckyGiftTurnover - overview.LuckyGiftPayout - overview.LuckyGiftPayoutRate = ratio(overview.LuckyGiftPayout, overview.LuckyGiftTurnover) - overview.LuckyGiftProfitRate = ratio(overview.LuckyGiftProfit, overview.LuckyGiftTurnover) overview.GameProfit = overview.GameTurnover - overview.GamePayout - overview.GameRefund overview.GameProfitRate = ratio(overview.GameProfit, overview.GameTurnover) overview.ARPUUSDMinor = div(overview.RechargeUSDMinor, overview.ActiveUsers) @@ -138,6 +135,16 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov return Overview{}, err } overview.LuckyGiftPools = pools + // 幸运礼物流水和返奖以 activity-service 的抽奖事实增量日汇总为准;这里仅读小表,避免 Databi 页面扫描 lucky_draw_records。 + if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, startDay, endDay, query.CountryID); err != nil { + return Overview{}, err + } else if ok { + overview.LuckyGiftPools = activityPools + overview.LuckyGiftTurnover, overview.LuckyGiftPayout = sumLuckyGiftPools(activityPools) + } + overview.LuckyGiftProfit = overview.LuckyGiftTurnover - overview.LuckyGiftPayout + overview.LuckyGiftPayoutRate = ratio(overview.LuckyGiftPayout, overview.LuckyGiftTurnover) + overview.LuckyGiftProfitRate = ratio(overview.LuckyGiftProfit, overview.LuckyGiftTurnover) return overview, nil } @@ -228,6 +235,55 @@ func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, end return out, rows.Err() } +func (r *Repository) queryLuckyGiftPoolsFromActivityStats(ctx context.Context, app, startDay, endDay string, countryID int64) ([]LuckyGiftPoolStat, bool, error) { + if r == nil || r.activityDB == nil { + return nil, false, nil + } + args := []any{app, startDay, endDay} + filter := "" + if countryID > 0 { + filter = " AND visible_region_id = ?" + args = append(args, countryID) + } + rows, err := r.activityDB.QueryContext(ctx, ` + SELECT pool_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0) + FROM lucky_draw_pool_day_stats + WHERE app_code = ? AND stat_day BETWEEN ? AND ? AND gift_id = ''`+filter+` + GROUP BY pool_id + ORDER BY COALESCE(SUM(turnover_coin),0) DESC, pool_id ASC`, args...) + if err != nil { + if isMissingTableError(err) { + return nil, false, nil + } + return nil, false, err + } + defer rows.Close() + out := []LuckyGiftPoolStat{} + for rows.Next() { + var item LuckyGiftPoolStat + if err := rows.Scan(&item.PoolID, &item.TurnoverCoin, &item.PayoutCoin); err != nil { + return nil, false, err + } + item.ProfitCoin = item.TurnoverCoin - item.PayoutCoin + item.PayoutRate = ratio(item.PayoutCoin, item.TurnoverCoin) + item.ProfitRate = ratio(item.ProfitCoin, item.TurnoverCoin) + out = append(out, item) + } + if err := rows.Err(); err != nil { + return nil, false, err + } + return out, len(out) > 0, nil +} + +func sumLuckyGiftPools(pools []LuckyGiftPoolStat) (int64, int64) { + var turnover, payout int64 + for _, pool := range pools { + turnover += pool.TurnoverCoin + payout += pool.PayoutCoin + } + return turnover, payout +} + func normalizeRange(startMS, endMS int64) (int64, int64) { if startMS <= 0 { now := time.Now().UTC() diff --git a/services/statistics-service/internal/storage/mysql/query_test.go b/services/statistics-service/internal/storage/mysql/query_test.go new file mode 100644 index 00000000..b0dab2a9 --- /dev/null +++ b/services/statistics-service/internal/storage/mysql/query_test.go @@ -0,0 +1,66 @@ +package mysql + +import ( + "context" + "runtime" + "testing" + "time" + + "hyapp/internal/testutil/mysqlschema" +) + +func TestQueryOverviewUsesActivityLuckyGiftDayStats(t *testing.T) { + ctx := context.Background() + _, file, _, _ := runtime.Caller(0) + statsSchema := mysqlschema.New(t, mysqlschema.Config{ + InitDBPath: mysqlschema.InitDBPath(t, file, "..", "..", "..", "deploy", "mysql", "initdb", "001_statistics_service.sql"), + DatabasePrefix: "hy_stats_query_test", + }) + activitySchema := mysqlschema.New(t, mysqlschema.Config{ + EnvVar: "ACTIVITY_SERVICE_MYSQL_TEST_DSN", + InitDBPath: mysqlschema.InitDBPath(t, file, "..", "..", "..", "..", "activity-service", "deploy", "mysql", "initdb", "001_activity_service.sql"), + DatabasePrefix: "hy_activity_query_test", + }) + repository, err := Open(ctx, statsSchema.DSN, activitySchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO stat_app_day_country ( + app_code, stat_day, country_id, lucky_gift_turnover, lucky_gift_payout, updated_at_ms + ) VALUES ('lalu', '2026-06-06', 210, 100, 900, 1)`); err != nil { + t.Fatalf("seed stale statistics overview: %v", err) + } + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO stat_lucky_gift_pool_day_country ( + app_code, stat_day, country_id, pool_id, turnover_coin, payout_coin, updated_at_ms + ) VALUES ('lalu', '2026-06-06', 210, 'lucky', 100, 900, 1)`); err != nil { + t.Fatalf("seed stale statistics pool: %v", err) + } + if _, err := repository.activityDB.ExecContext(ctx, ` + INSERT INTO lucky_draw_pool_day_stats ( + app_code, stat_day, visible_region_id, pool_id, gift_id, draw_count, turnover_coin, payout_coin, + base_reward_coin, room_atmosphere_reward_coin, activity_subsidy_coin, created_at_ms, updated_at_ms + ) VALUES + ('lalu', '2026-06-06', 210, 'super_lucky', '', 10, 2744832, 2401885, 2401885, 0, 0, 1, 1), + ('lalu', '2026-06-06', 210, 'lucky', '', 5, 148322, 126415, 126415, 0, 0, 1, 1)`); err != nil { + t.Fatalf("seed activity databi stats: %v", err) + } + + start := time.Date(2026, 6, 6, 0, 0, 0, 0, time.UTC).UnixMilli() + overview, err := repository.QueryOverview(ctx, OverviewQuery{AppCode: "lalu", StartMS: start, EndMS: start + int64(24*time.Hour/time.Millisecond), CountryID: 210}) + if err != nil { + t.Fatalf("query overview: %v", err) + } + if overview.LuckyGiftTurnover != 2_893_154 || overview.LuckyGiftPayout != 2_528_300 || overview.LuckyGiftProfit != 364_854 { + t.Fatalf("activity lucky gift overview not applied: %+v", overview) + } + if len(overview.LuckyGiftPools) != 2 { + t.Fatalf("activity lucky gift pools not applied: %+v", overview.LuckyGiftPools) + } + if overview.LuckyGiftPools[0].PoolID != "super_lucky" || overview.LuckyGiftPools[0].TurnoverCoin != 2_744_832 || overview.LuckyGiftPools[0].PayoutCoin != 2_401_885 { + t.Fatalf("super_lucky pool mismatch: %+v", overview.LuckyGiftPools[0]) + } +} diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index 205c9a44..e34f76d5 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -20,13 +20,15 @@ const ( SourceGame = "game" ) -// Repository owns the statistics read model. Online queries must use these -// aggregate tables, never owner-service fact tables. +// Repository owns the statistics read model. Online queries must use aggregate +// tables; the optional activity connection only reads lucky-gift day snapshots, +// never the high-cardinality draw fact table. type Repository struct { - db *sql.DB + db *sql.DB + activityDB *sql.DB } -func Open(ctx context.Context, dsn string) (*Repository, error) { +func Open(ctx context.Context, dsn string, activityDSNs ...string) (*Repository, error) { if strings.TrimSpace(dsn) == "" { return nil, xerr.New(xerr.InvalidArgument, "mysql_dsn is required") } @@ -38,8 +40,24 @@ func Open(ctx context.Context, dsn string) (*Repository, error) { _ = db.Close() return nil, err } - repo := &Repository{db: db} + var activityDB *sql.DB + if len(activityDSNs) > 0 && strings.TrimSpace(activityDSNs[0]) != "" { + activityDB, err = sql.Open("mysql", strings.TrimSpace(activityDSNs[0])) + if err != nil { + _ = db.Close() + return nil, err + } + if err := activityDB.PingContext(ctx); err != nil { + _ = activityDB.Close() + _ = db.Close() + return nil, err + } + } + repo := &Repository{db: db, activityDB: activityDB} if err := repo.Migrate(ctx); err != nil { + if activityDB != nil { + _ = activityDB.Close() + } _ = db.Close() return nil, err } @@ -47,17 +65,32 @@ func Open(ctx context.Context, dsn string) (*Repository, error) { } func (r *Repository) Close() error { - if r == nil || r.db == nil { + if r == nil { return nil } - return r.db.Close() + var err error + if r.activityDB != nil { + err = r.activityDB.Close() + } + if r.db != nil { + if dbErr := r.db.Close(); err == nil { + err = dbErr + } + } + return err } func (r *Repository) Ping(ctx context.Context) error { if r == nil || r.db == nil { return xerr.New(xerr.Unavailable, "mysql repository is not configured") } - return r.db.PingContext(ctx) + if err := r.db.PingContext(ctx); err != nil { + return err + } + if r.activityDB != nil { + return r.activityDB.PingContext(ctx) + } + return nil } func (r *Repository) Migrate(ctx context.Context) error { @@ -473,6 +506,11 @@ func isDuplicateColumnError(err error) bool { return errors.As(err, &mysqlErr) && mysqlErr.Number == 1060 } +func isMissingTableError(err error) bool { + var mysqlErr *mysqlerr.MySQLError + return errors.As(err, &mysqlErr) && mysqlErr.Number == 1146 +} + func applyActive(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, userID int64, occurredAtMS int64, nowMS int64) error { if err := ensureAppDay(ctx, tx, app, day, countryID, nowMS); err != nil { return err diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index c6ebf25b..36e675a7 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -750,6 +750,30 @@ type LuckyGiftRewardReceipt struct { GrantedAtMS int64 } +// RoomTurnoverRewardCommand 是 activity-service 每周房间流水奖励的 COIN 入账命令。 +type RoomTurnoverRewardCommand struct { + AppCode string + CommandID string + TargetUserID int64 + Amount int64 + SettlementID string + RoomID string + PeriodStartMS int64 + PeriodEndMS int64 + CoinSpent int64 + TierID int64 + TierCode string + Reason string +} + +// RoomTurnoverRewardReceipt 是房间流水奖励入账后的稳定回执。 +type RoomTurnoverRewardReceipt struct { + TransactionID string + Balance AssetBalance + Amount int64 + GrantedAtMS int64 +} + // GameCoinChangeCommand 是 game-service 对钱包发起的游戏专用金币改账命令。 type GameCoinChangeCommand struct { AppCode string diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index 32d96f64..58a1841b 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -31,6 +31,7 @@ type Repository interface { TransferSalaryToCoinSeller(ctx context.Context, command ledger.SalaryTransferToCoinSellerCommand) (ledger.SalaryTransferToCoinSellerReceipt, error) CreditTaskReward(ctx context.Context, command ledger.TaskRewardCommand) (ledger.TaskRewardReceipt, error) CreditLuckyGiftReward(ctx context.Context, command ledger.LuckyGiftRewardCommand) (ledger.LuckyGiftRewardReceipt, error) + CreditRoomTurnoverReward(ctx context.Context, command ledger.RoomTurnoverRewardCommand) (ledger.RoomTurnoverRewardReceipt, error) ApplyGameCoinChange(ctx context.Context, command ledger.GameCoinChangeCommand) (ledger.GameCoinChangeReceipt, error) GetRedPacketConfig(ctx context.Context, appCode string) (ledger.RedPacketConfig, error) UpdateRedPacketConfig(ctx context.Context, config ledger.RedPacketConfig) (ledger.RedPacketConfig, error) @@ -492,6 +493,33 @@ func (s *Service) CreditLuckyGiftReward(ctx context.Context, command ledger.Luck return s.repository.CreditLuckyGiftReward(ctx, command) } +// CreditRoomTurnoverReward 发放每周房间流水奖励金币;结算归 activity-service,钱包只负责幂等入账。 +func (s *Service) CreditRoomTurnoverReward(ctx context.Context, command ledger.RoomTurnoverRewardCommand) (ledger.RoomTurnoverRewardReceipt, error) { + // 钱包只接受 activity-service 已经生成好的结算命令;缺 settlement、room 或正向金额时直接拒绝,避免钱包自己推断活动规则。 + if command.CommandID == "" || command.TargetUserID <= 0 || command.Amount <= 0 || command.SettlementID == "" || command.RoomID == "" { + return ledger.RoomTurnoverRewardReceipt{}, xerr.New(xerr.InvalidArgument, "room turnover reward command is incomplete") + } + // 周期、流水和档位是账务元数据的一部分,必须随交易落库,后续对账才能从钱包交易反查是哪一周、哪个房间、哪个档位。 + if command.PeriodStartMS <= 0 || command.PeriodEndMS <= command.PeriodStartMS || command.CoinSpent <= 0 || command.TierID <= 0 { + return ledger.RoomTurnoverRewardReceipt{}, xerr.New(xerr.InvalidArgument, "room turnover reward period or tier is invalid") + } + command.Reason = strings.TrimSpace(command.Reason) + if command.Reason == "" { + return ledger.RoomTurnoverRewardReceipt{}, xerr.New(xerr.InvalidArgument, "reason is required") + } + if s.repository == nil { + return ledger.RoomTurnoverRewardReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured") + } + command.AppCode = appcode.Normalize(command.AppCode) + command.SettlementID = strings.TrimSpace(command.SettlementID) + command.RoomID = strings.TrimSpace(command.RoomID) + command.TierCode = strings.TrimSpace(command.TierCode) + // AppCode 归一化后写入 context,让 repository 的交易、账户和 outbox 都落到同一个 App 分区。 + ctx = appcode.WithContext(ctx, command.AppCode) + + return s.repository.CreditRoomTurnoverReward(ctx, command) +} + // ApplyGameCoinChange 是游戏平台唯一的 COIN 改账入口,方向由 op_type 控制。 func (s *Service) ApplyGameCoinChange(ctx context.Context, command ledger.GameCoinChangeCommand) (ledger.GameCoinChangeReceipt, error) { if command.CommandID == "" || command.UserID <= 0 || command.PlatformCode == "" || command.GameID == "" || command.ProviderOrderID == "" { diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 43a27c85..0fa8e925 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -26,6 +26,7 @@ const ( bizTypeManualCredit = "manual_credit" bizTypeTaskReward = "task_reward" bizTypeLuckyGiftReward = "lucky_gift_reward" + bizTypeRoomTurnoverReward = "room_turnover_reward" bizTypeCoinSellerTransfer = "coin_seller_transfer" bizTypeCoinSellerStockPurchase = "coin_seller_stock_purchase" bizTypeCoinSellerCoinCompensation = "coin_seller_coin_compensation" @@ -925,6 +926,87 @@ func (r *Repository) CreditLuckyGiftReward(ctx context.Context, command ledger.L return receiptFromLuckyGiftRewardMetadata(transactionID, metadata), nil } +// CreditRoomTurnoverReward 在同一事务里完成每周房间流水奖励 COIN 入账、交易分录和钱包 outbox。 +func (r *Repository) CreditRoomTurnoverReward(ctx context.Context, command ledger.RoomTurnoverRewardCommand) (ledger.RoomTurnoverRewardReceipt, error) { + if r == nil || r.db == nil { + return ledger.RoomTurnoverRewardReceipt{}, xerr.New(xerr.Unavailable, "mysql repository is not configured") + } + ctx = contextWithCommandApp(ctx, command.AppCode) + command.AppCode = appcode.FromContext(ctx) + + tx, err := r.db.BeginTx(ctx, nil) + if err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + defer func() { _ = tx.Rollback() }() + + requestHash := roomTurnoverRewardRequestHash(command) + if txRow, exists, err := r.lookupTransaction(ctx, tx, command.CommandID, requestHash, bizTypeRoomTurnoverReward); err != nil || exists { + if err != nil || !exists { + return ledger.RoomTurnoverRewardReceipt{}, err + } + // command_id 相同且请求摘要一致说明是 activity-service 的重复发奖调用;直接返回原交易回执,不再改余额。 + return r.receiptForRoomTurnoverRewardTransaction(ctx, tx, txRow.TransactionID) + } + + nowMs := time.Now().UnixMilli() + // 锁定房主 COIN 账户后再计算余额,保证同一用户同时收到多笔奖励时 available_after 仍是线性账本结果。 + account, err := r.lockAccount(ctx, tx, command.TargetUserID, ledger.AssetCoin, true, nowMs) + if err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + transactionID := transactionID(command.AppCode, command.CommandID) + balanceAfter := account.AvailableAmount + command.Amount + // metadata 是交易、分录和 outbox 的共享事实快照;后续补发事件或幂等查询都从这里还原原始结算上下文。 + metadata := roomTurnoverRewardMetadata{ + AppCode: command.AppCode, + TargetUserID: command.TargetUserID, + AssetType: ledger.AssetCoin, + Amount: command.Amount, + SettlementID: command.SettlementID, + RoomID: command.RoomID, + PeriodStartMS: command.PeriodStartMS, + PeriodEndMS: command.PeriodEndMS, + CoinSpent: command.CoinSpent, + TierID: command.TierID, + TierCode: command.TierCode, + Reason: command.Reason, + BalanceAfter: balanceAfter, + GrantedAtMS: nowMs, + } + if err := r.insertTransaction(ctx, tx, transactionID, command.CommandID, bizTypeRoomTurnoverReward, requestHash, command.SettlementID, metadata, nowMs); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + // 交易、账户余额、账本分录和 outbox 必须在同一事务提交;任意一步失败都会回滚,避免出现发奖记录和余额不一致。 + if err := r.applyAccountDelta(ctx, tx, account, command.Amount, 0, nowMs); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + if err := r.insertEntry(ctx, tx, walletEntry{ + TransactionID: transactionID, + UserID: command.TargetUserID, + AssetType: ledger.AssetCoin, + AvailableDelta: command.Amount, + FrozenDelta: 0, + AvailableAfter: balanceAfter, + FrozenAfter: account.FrozenAmount, + RoomID: command.RoomID, + CreatedAtMS: nowMs, + }); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + if err := r.insertWalletOutbox(ctx, tx, []walletOutboxEvent{ + balanceChangedEvent(transactionID, command.CommandID, command.TargetUserID, ledger.AssetCoin, command.Amount, 0, balanceAfter, account.FrozenAmount, account.Version+1, metadata, nowMs), + roomTurnoverRewardCreditedEvent(transactionID, command.CommandID, metadata, nowMs), + }); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + if err := tx.Commit(); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + + return receiptFromRoomTurnoverRewardMetadata(transactionID, metadata), nil +} + // ApplyGameCoinChange 在同一事务内完成游戏 COIN 改账、分录和 outbox。 func (r *Repository) ApplyGameCoinChange(ctx context.Context, command ledger.GameCoinChangeCommand) (ledger.GameCoinChangeReceipt, error) { if r == nil || r.db == nil { @@ -2557,6 +2639,23 @@ type luckyGiftRewardMetadata struct { GrantedAtMS int64 `json:"granted_at_ms"` } +type roomTurnoverRewardMetadata struct { + AppCode string `json:"app_code"` + TargetUserID int64 `json:"target_user_id"` + AssetType string `json:"asset_type"` + Amount int64 `json:"amount"` + SettlementID string `json:"settlement_id"` + RoomID string `json:"room_id"` + PeriodStartMS int64 `json:"period_start_ms"` + PeriodEndMS int64 `json:"period_end_ms"` + CoinSpent int64 `json:"coin_spent"` + TierID int64 `json:"tier_id"` + TierCode string `json:"tier_code"` + Reason string `json:"reason"` + BalanceAfter int64 `json:"balance_after"` + GrantedAtMS int64 `json:"granted_at_ms"` +} + type gameCoinMetadata struct { AppCode string `json:"app_code"` UserID int64 `json:"user_id"` @@ -2729,6 +2828,38 @@ func receiptFromLuckyGiftRewardMetadata(transactionID string, metadata luckyGift } } +func (r *Repository) receiptForRoomTurnoverRewardTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.RoomTurnoverRewardReceipt, error) { + var metadataJSON string + if err := tx.QueryRowContext(ctx, + `SELECT COALESCE(CAST(metadata_json AS CHAR), '{}') + FROM wallet_transactions + WHERE app_code = ? AND transaction_id = ?`, + appcode.FromContext(ctx), + transactionID, + ).Scan(&metadataJSON); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + var metadata roomTurnoverRewardMetadata + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err != nil { + return ledger.RoomTurnoverRewardReceipt{}, err + } + return receiptFromRoomTurnoverRewardMetadata(transactionID, metadata), nil +} + +func receiptFromRoomTurnoverRewardMetadata(transactionID string, metadata roomTurnoverRewardMetadata) ledger.RoomTurnoverRewardReceipt { + return ledger.RoomTurnoverRewardReceipt{ + TransactionID: transactionID, + Balance: ledger.AssetBalance{ + AppCode: metadata.AppCode, + UserID: metadata.TargetUserID, + AssetType: metadata.AssetType, + AvailableAmount: metadata.BalanceAfter, + }, + Amount: metadata.Amount, + GrantedAtMS: metadata.GrantedAtMS, + } +} + func (r *Repository) receiptForGameTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.GameCoinChangeReceipt, error) { var metadataJSON string if err := tx.QueryRowContext(ctx, @@ -3006,6 +3137,35 @@ func luckyGiftRewardCreditedEvent(transactionID string, commandID string, metada } } +func roomTurnoverRewardCreditedEvent(transactionID string, commandID string, metadata roomTurnoverRewardMetadata, nowMs int64) walletOutboxEvent { + return walletOutboxEvent{ + EventID: eventID(transactionID, "WalletRoomTurnoverRewardCredited", metadata.TargetUserID, ledger.AssetCoin), + EventType: "WalletRoomTurnoverRewardCredited", + TransactionID: transactionID, + CommandID: commandID, + UserID: metadata.TargetUserID, + AssetType: ledger.AssetCoin, + AvailableDelta: metadata.Amount, + FrozenDelta: 0, + Payload: map[string]any{ + "transaction_id": transactionID, + "command_id": commandID, + "user_id": metadata.TargetUserID, + "settlement_id": metadata.SettlementID, + "room_id": metadata.RoomID, + "period_start_ms": metadata.PeriodStartMS, + "period_end_ms": metadata.PeriodEndMS, + "coin_spent": metadata.CoinSpent, + "tier_id": metadata.TierID, + "tier_code": metadata.TierCode, + "amount": metadata.Amount, + "reason": metadata.Reason, + "created_at_ms": nowMs, + }, + CreatedAtMS: nowMs, + } +} + func coinSellerStockCreditedEvent(transactionID string, commandID string, metadata coinSellerStockMetadata, nowMs int64) walletOutboxEvent { eventType := "WalletCoinSellerCoinCompensated" if metadata.StockType == ledger.StockTypeUSDTPurchase { @@ -3258,6 +3418,22 @@ func luckyGiftRewardRequestHash(command ledger.LuckyGiftRewardCommand) string { )) } +func roomTurnoverRewardRequestHash(command ledger.RoomTurnoverRewardCommand) string { + return stableHash(fmt.Sprintf("room_turnover_reward|%s|%d|%d|%s|%s|%d|%d|%d|%d|%s|%s", + appcode.Normalize(command.AppCode), + command.TargetUserID, + command.Amount, + strings.TrimSpace(command.SettlementID), + strings.TrimSpace(command.RoomID), + command.PeriodStartMS, + command.PeriodEndMS, + command.CoinSpent, + command.TierID, + strings.TrimSpace(command.TierCode), + strings.TrimSpace(command.Reason), + )) +} + func gameBizTypeAndDelta(opType string, coinAmount int64) (string, int64, error) { switch ledger.NormalizeGameOpType(opType) { case ledger.GameOpDebit: diff --git a/services/wallet-service/internal/transport/grpc/server.go b/services/wallet-service/internal/transport/grpc/server.go index 90286512..0e7d80d6 100644 --- a/services/wallet-service/internal/transport/grpc/server.go +++ b/services/wallet-service/internal/transport/grpc/server.go @@ -773,6 +773,42 @@ func (s *Server) CreditLuckyGiftReward(ctx context.Context, req *walletv1.Credit }, nil } +// CreditRoomTurnoverReward 处理 activity-service 每周房间流水奖励金币入账。 +func (s *Server) CreditRoomTurnoverReward(ctx context.Context, req *walletv1.CreditRoomTurnoverRewardRequest) (*walletv1.CreditRoomTurnoverRewardResponse, error) { + // gRPC 层不解释活动规则,只把 activity-service 的结算命令转换为钱包领域命令。 + ctx = appcode.WithContext(ctx, req.GetAppCode()) + receipt, err := s.svc.CreditRoomTurnoverReward(ctx, ledger.RoomTurnoverRewardCommand{ + AppCode: req.GetAppCode(), + CommandID: req.GetCommandId(), + TargetUserID: req.GetTargetUserId(), + Amount: req.GetAmount(), + SettlementID: req.GetSettlementId(), + RoomID: req.GetRoomId(), + PeriodStartMS: req.GetPeriodStartMs(), + PeriodEndMS: req.GetPeriodEndMs(), + CoinSpent: req.GetCoinSpent(), + TierID: req.GetTierId(), + TierCode: req.GetTierCode(), + Reason: req.GetReason(), + }) + if err != nil { + return nil, xerr.ToGRPCError(err) + } + + return &walletv1.CreditRoomTurnoverRewardResponse{ + TransactionId: receipt.TransactionID, + Amount: receipt.Amount, + GrantedAtMs: receipt.GrantedAtMS, + Balance: &walletv1.AssetBalance{ + AppCode: receipt.Balance.AppCode, + AssetType: receipt.Balance.AssetType, + AvailableAmount: receipt.Balance.AvailableAmount, + FrozenAmount: receipt.Balance.FrozenAmount, + Version: receipt.Balance.Version, + }, + }, nil +} + // ApplyGameCoinChange 处理 game-service 发起的游戏专用金币改账。 func (s *Server) ApplyGameCoinChange(ctx context.Context, req *walletv1.ApplyGameCoinChangeRequest) (*walletv1.ApplyGameCoinChangeResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) diff --git a/tools/cumulative-recharge-local-flow/main.go b/tools/cumulative-recharge-local-flow/main.go new file mode 100644 index 00000000..dd38b5f0 --- /dev/null +++ b/tools/cumulative-recharge-local-flow/main.go @@ -0,0 +1,505 @@ +package main + +import ( + "context" + "database/sql" + "encoding/json" + "flag" + "fmt" + "log" + "sort" + "time" + + _ "github.com/go-sql-driver/mysql" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + activityv1 "hyapp.local/api/proto/activity/v1" + walletv1 "hyapp.local/api/proto/wallet/v1" +) + +const ( + appCode = "lalu" + operatorAdminID = int64(900100100) + rechargeSource = "cumulative_recharge_reward" + groupItemWalletAsset = "wallet_asset" + assetCoin = "COIN" + statusActive = "active" + statusDisabled = "disabled" + tierStatusInactive = "inactive" +) + +type walletOutboxFact struct { + EventID string + TransactionID string + CommandID string + PayloadJSON string + CreatedAtMS int64 + AvailableDelta int64 +} + +type cycle struct { + Key string + StartMS int64 + EndMS int64 +} + +func main() { + var ( + walletAddr = flag.String("wallet_addr", "127.0.0.1:13004", "wallet-service gRPC address") + activityAddr = flag.String("activity_addr", "127.0.0.1:13006", "activity-service gRPC address") + activityDSN = flag.String("activity_dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC", "activity MySQL DSN") + walletDSN = flag.String("wallet_dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC", "wallet MySQL DSN") + mode = flag.String("mode", "happy", "flow mode: happy or boundary") + ) + flag.Parse() + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + walletConn, err := grpc.DialContext(ctx, *walletAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + must("dial wallet-service", err) + defer walletConn.Close() + activityConn, err := grpc.DialContext(ctx, *activityAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + must("dial activity-service", err) + defer activityConn.Close() + + activityDB, err := sql.Open("mysql", *activityDSN) + must("open activity mysql", err) + defer activityDB.Close() + must("ping activity mysql", activityDB.PingContext(ctx)) + walletDB, err := sql.Open("mysql", *walletDSN) + must("open wallet mysql", err) + defer walletDB.Close() + must("ping wallet mysql", walletDB.PingContext(ctx)) + + walletClient := walletv1.NewWalletServiceClient(walletConn) + rewardClient := activityv1.NewCumulativeRechargeRewardServiceClient(activityConn) + adminClient := activityv1.NewAdminCumulativeRechargeRewardServiceClient(activityConn) + + if *mode == "boundary" { + runBoundaryFlow(ctx, walletClient, rewardClient, adminClient, activityDB, walletDB) + return + } + + runID := fmt.Sprintf("crr_%d", time.Now().UnixMilli()) + targetUserID := int64(760000000000) + time.Now().Unix()%10000000 + sellerUserID := targetUserID + 100000000 + now := time.Now().UTC() + currentCycle := cycleForTime(now) + nextCycle := cycleForTime(time.UnixMilli(currentCycle.EndMS).UTC().Add(2 * time.Hour)) + + group100 := createCoinRewardGroup(ctx, walletClient, runID, "100", 1000) + group200 := createCoinRewardGroup(ctx, walletClient, runID, "200", 2000) + updateConfig(ctx, adminClient, runID, group100, group200) + + google := consumeRecharge(ctx, rewardClient, runID, "google", targetUserID, "google_play", 5_400_000, 6_000, now.Add(1*time.Minute)) + assert(len(google.Grants) == 0 && google.GetReason() == "no_tier_matched", "google $60 should not grant a tier") + statusAfterGoogle := getStatus(ctx, rewardClient, targetUserID) + assert(statusAfterGoogle.GetProgress().GetTotalUsdMinor() == 6_000, "google progress should be $60.00") + + mifapay := consumeRecharge(ctx, rewardClient, runID, "mifapay", targetUserID, "mifapay", 4_500_000, 5_000, now.Add(2*time.Minute)) + assertGrantThresholds("mifapay should unlock only $100 tier", mifapay.GetGrants(), []int64{10_000}) + statusAfterMifapay := getStatus(ctx, rewardClient, targetUserID) + assert(statusAfterMifapay.GetProgress().GetTotalUsdMinor() == 11_000, "google+mifapay progress should be $110.00") + + transfer := runCoinSellerTransfer(ctx, walletClient, walletDB, runID, sellerUserID, targetUserID) + coinSellerUSDMinor := transfer.AvailableDelta * 100 / 90_000 + assert(transfer.AvailableDelta == 9_000_000 && coinSellerUSDMinor == 10_000, "coin seller transfer should convert 9,000,000 coins to $100.00") + coinSeller := consumeRechargeFromWalletFact(ctx, rewardClient, targetUserID, transfer, coinSellerUSDMinor) + assertGrantThresholds("coin seller transfer should unlock only $200 tier", coinSeller.GetGrants(), []int64{20_000}) + statusAfterCoinSeller := getStatus(ctx, rewardClient, targetUserID) + assert(statusAfterCoinSeller.GetProgress().GetTotalUsdMinor() == 21_000, "current cycle progress should be $210.00") + + nextWeek := consumeRecharge(ctx, rewardClient, runID, "nextweek-google", targetUserID, "google_play", 9_000_000, 10_000, time.UnixMilli(nextCycle.StartMS).UTC().Add(time.Hour)) + assertGrantThresholds("next week $100 should unlock only new $100 tier", nextWeek.GetGrants(), []int64{10_000}) + + currentProgress := queryProgress(ctx, activityDB, targetUserID, currentCycle.Key) + nextProgress := queryProgress(ctx, activityDB, targetUserID, nextCycle.Key) + assert(currentProgress == 21_000, "current cycle DB progress should stay $210.00") + assert(nextProgress == 10_000, "next cycle DB progress should reset to $100.00") + + currentGrants := queryGrantSummary(ctx, activityDB, targetUserID, currentCycle.Key) + nextGrants := queryGrantSummary(ctx, activityDB, targetUserID, nextCycle.Key) + assert(currentGrants.Count == 2 && currentGrants.Granted == 2, "current cycle should have two granted tiers") + assert(nextGrants.Count == 1 && nextGrants.Granted == 1, "next cycle should have one granted tier") + + walletReward := queryWalletRewardSummary(ctx, walletDB, targetUserID) + assert(walletReward.Count == 3 && walletReward.CoinDelta == 4_000, "wallet should receive three reward group grants totaling 4,000 COIN") + + out := map[string]any{ + "run_id": runID, + "target_user_id": targetUserID, + "seller_user_id": sellerUserID, + "current_cycle": currentCycle.Key, + "next_cycle": nextCycle.Key, + "events": []map[string]any{ + {"type": "google_play", "usd_minor": 6000, "grant_thresholds": thresholds(google.GetGrants())}, + {"type": "mifapay", "usd_minor": 5000, "grant_thresholds": thresholds(mifapay.GetGrants())}, + {"type": "coin_seller_transfer", "coins": transfer.AvailableDelta, "usd_minor": coinSellerUSDMinor, "grant_thresholds": thresholds(coinSeller.GetGrants())}, + {"type": "next_week_google_play", "usd_minor": 10000, "grant_thresholds": thresholds(nextWeek.GetGrants())}, + }, + "progress_usd_minor": map[string]int64{currentCycle.Key: currentProgress, nextCycle.Key: nextProgress}, + "activity_grants": map[string]grantSummary{currentCycle.Key: currentGrants, nextCycle.Key: nextGrants}, + "wallet_reward": walletReward, + } + encoded, _ := json.MarshalIndent(out, "", " ") + fmt.Println(string(encoded)) +} + +func createCoinRewardGroup(ctx context.Context, client walletv1.WalletServiceClient, runID string, suffix string, coinAmount int64) int64 { + resp, err := client.CreateResourceGroup(ctx, &walletv1.CreateResourceGroupRequest{ + RequestId: fmt.Sprintf("%s_create_group_%s", runID, suffix), + AppCode: appCode, + GroupCode: fmt.Sprintf("%s_group_%s", runID, suffix), + Name: fmt.Sprintf("CRR local reward %s", suffix), + Status: statusActive, + Description: "local cumulative recharge flow verification", + SortOrder: 1, + OperatorUserId: operatorAdminID, + Items: []*walletv1.ResourceGroupItemInput{{ + ItemType: groupItemWalletAsset, + WalletAssetType: assetCoin, + WalletAssetAmount: coinAmount, + SortOrder: 1, + }}, + }) + must("create wallet reward group "+suffix, err) + assert(resp.GetGroup().GetGroupId() > 0, "created resource group id should be positive") + return resp.GetGroup().GetGroupId() +} + +func updateConfig(ctx context.Context, client activityv1.AdminCumulativeRechargeRewardServiceClient, runID string, group100 int64, group200 int64) { + _, err := updateConfigWithTiers(ctx, client, runID, true, []*activityv1.CumulativeRechargeRewardTier{ + {TierCode: runID + "_100", TierName: "Local $100", ThresholdUsdMinor: 10_000, ResourceGroupId: group100, Status: statusActive, SortOrder: 1}, + {TierCode: runID + "_200", TierName: "Local $200", ThresholdUsdMinor: 20_000, ResourceGroupId: group200, Status: statusActive, SortOrder: 2}, + }) + must("update cumulative recharge config", err) +} + +func updateConfigWithTiers(ctx context.Context, client activityv1.AdminCumulativeRechargeRewardServiceClient, runID string, enabled bool, tiers []*activityv1.CumulativeRechargeRewardTier) (*activityv1.UpdateCumulativeRechargeRewardConfigResponse, error) { + return client.UpdateCumulativeRechargeRewardConfig(ctx, &activityv1.UpdateCumulativeRechargeRewardConfigRequest{ + Meta: meta(runID + "_update_config"), + Enabled: enabled, + OperatorAdminId: operatorAdminID, + Tiers: tiers, + }) +} + +func consumeRecharge(ctx context.Context, client activityv1.CumulativeRechargeRewardServiceClient, runID string, name string, userID int64, rechargeType string, coinAmount int64, usdMinor int64, occurredAt time.Time) *activityv1.ConsumeCumulativeRechargeRewardResponse { + resp, err := consumeRechargeAllowError(ctx, client, runID, name, userID, rechargeType, coinAmount, usdMinor, occurredAt) + must("consume recharge "+name, err) + return resp +} + +func consumeRechargeAllowError(ctx context.Context, client activityv1.CumulativeRechargeRewardServiceClient, runID string, name string, userID int64, rechargeType string, coinAmount int64, usdMinor int64, occurredAt time.Time) (*activityv1.ConsumeCumulativeRechargeRewardResponse, error) { + payload, _ := json.Marshal(map[string]any{ + "recharge_type": rechargeType, + "coin_amount": coinAmount, + "recharge_usd_minor": usdMinor, + }) + resp, err := client.ConsumeCumulativeRechargeReward(ctx, &activityv1.ConsumeCumulativeRechargeRewardRequest{ + Meta: meta(runID + "_" + name), + EventId: fmt.Sprintf("%s_event_%s", runID, name), + TransactionId: fmt.Sprintf("%s_tx_%s", runID, name), + CommandId: fmt.Sprintf("%s_cmd_%s", runID, name), + UserId: userID, + RechargeCoinAmount: coinAmount, + RechargeSequence: time.Now().UnixNano(), + RechargeType: rechargeType, + QualifyingUsdMinor: usdMinor, + PayloadJson: string(payload), + OccurredAtMs: occurredAt.UnixMilli(), + }) + return resp, err +} + +func consumeRechargeFromWalletFact(ctx context.Context, client activityv1.CumulativeRechargeRewardServiceClient, userID int64, fact walletOutboxFact, usdMinor int64) *activityv1.ConsumeCumulativeRechargeRewardResponse { + resp, err := client.ConsumeCumulativeRechargeReward(ctx, &activityv1.ConsumeCumulativeRechargeRewardRequest{ + Meta: meta("coin_seller_wallet_fact"), + EventId: fact.EventID, + TransactionId: fact.TransactionID, + CommandId: fact.CommandID, + UserId: userID, + RechargeCoinAmount: fact.AvailableDelta, + RechargeType: "coin_seller_transfer", + QualifyingUsdMinor: usdMinor, + PayloadJson: fact.PayloadJSON, + OccurredAtMs: fact.CreatedAtMS, + }) + must("consume coin seller wallet fact", err) + return resp +} + +func runCoinSellerTransfer(ctx context.Context, client walletv1.WalletServiceClient, db *sql.DB, runID string, sellerUserID int64, targetUserID int64) walletOutboxFact { + _, err := client.AdminCreditCoinSellerStock(ctx, &walletv1.AdminCreditCoinSellerStockRequest{ + CommandId: fmt.Sprintf("%s_stock", runID), + SellerUserId: sellerUserID, + StockType: "usdt_purchase", + CoinAmount: 9_000_000, + PaidCurrencyCode: "USDT", + PaidAmountMicro: 100_000_000, + PaymentRef: fmt.Sprintf("%s_payment", runID), + EvidenceRef: "local-flow", + OperatorUserId: operatorAdminID, + Reason: "local cumulative recharge flow", + AppCode: appCode, + }) + must("credit coin seller stock", err) + transfer, err := client.TransferCoinFromSeller(ctx, &walletv1.TransferCoinFromSellerRequest{ + CommandId: fmt.Sprintf("%s_seller_transfer", runID), + SellerUserId: sellerUserID, + TargetUserId: targetUserID, + Amount: 9_000_000, + Reason: "local cumulative recharge flow", + AppCode: appCode, + SellerRegionId: 1, + TargetRegionId: 1, + }) + must("transfer coin from seller", err) + + var fact walletOutboxFact + err = db.QueryRowContext(ctx, ` + SELECT event_id, transaction_id, command_id, COALESCE(payload, '{}'), created_at_ms, available_delta + FROM wallet_outbox + WHERE app_code = ? AND transaction_id = ? AND user_id = ? AND event_type = 'WalletRechargeRecorded' + LIMIT 1`, + appCode, transfer.GetTransactionId(), targetUserID, + ).Scan(&fact.EventID, &fact.TransactionID, &fact.CommandID, &fact.PayloadJSON, &fact.CreatedAtMS, &fact.AvailableDelta) + must("read coin seller WalletRechargeRecorded outbox", err) + return fact +} + +func setResourceGroupStatus(ctx context.Context, client walletv1.WalletServiceClient, runID string, groupID int64, status string) { + _, err := client.SetResourceGroupStatus(ctx, &walletv1.SetResourceGroupStatusRequest{ + RequestId: fmt.Sprintf("%s_group_status_%d_%s", runID, groupID, status), + AppCode: appCode, + GroupId: groupID, + Status: status, + OperatorUserId: operatorAdminID, + }) + must("set resource group status "+status, err) +} + +func getStatus(ctx context.Context, client activityv1.CumulativeRechargeRewardServiceClient, userID int64) *activityv1.CumulativeRechargeRewardStatus { + resp, err := client.GetCumulativeRechargeRewardStatus(ctx, &activityv1.GetCumulativeRechargeRewardStatusRequest{Meta: meta("get_status"), UserId: userID}) + must("get cumulative recharge status", err) + return resp.GetStatus() +} + +func runBoundaryFlow(ctx context.Context, walletClient walletv1.WalletServiceClient, rewardClient activityv1.CumulativeRechargeRewardServiceClient, adminClient activityv1.AdminCumulativeRechargeRewardServiceClient, activityDB *sql.DB, walletDB *sql.DB) { + runID := fmt.Sprintf("crr_boundary_%d", time.Now().UnixMilli()) + baseUserID := int64(761000000000) + time.Now().Unix()%10000000 + now := time.Now().UTC() + currentCycle := cycleForTime(now) + nextCycle := cycleForTime(time.UnixMilli(currentCycle.EndMS).UTC().Add(time.Millisecond)) + + group100 := createCoinRewardGroup(ctx, walletClient, runID, "100", 1000) + group200 := createCoinRewardGroup(ctx, walletClient, runID, "200", 2000) + + updateConfig(ctx, adminClient, runID, group100, group200) + duplicate := consumeRecharge(ctx, rewardClient, runID, "duplicate", baseUserID+1, "google_play", 13_500_000, 15_000, now.Add(10*time.Minute)) + assertGrantThresholds("duplicate first event should grant $100", duplicate.GetGrants(), []int64{10_000}) + duplicateAgain := consumeRecharge(ctx, rewardClient, runID, "duplicate", baseUserID+1, "google_play", 13_500_000, 15_000, now.Add(10*time.Minute)) + assert(duplicateAgain.GetReason() == "already_consumed" && len(duplicateAgain.GetGrants()) == 0, "duplicate event should be consumed without new grants") + assert(queryProgress(ctx, activityDB, baseUserID+1, currentCycle.Key) == 15_000, "duplicate event must not double progress") + assert(queryGrantSummary(ctx, activityDB, baseUserID+1, currentCycle.Key).Count == 1, "duplicate event must not double grant rows") + + cross := consumeRecharge(ctx, rewardClient, runID, "cross-multiple", baseUserID+2, "mifapay", 22_500_000, 25_000, now.Add(11*time.Minute)) + assertGrantThresholds("single large recharge should cross both tiers", cross.GetGrants(), []int64{10_000, 20_000}) + assert(queryProgress(ctx, activityDB, baseUserID+2, currentCycle.Key) == 25_000, "cross-tier progress should be $250.00") + assert(queryWalletRewardSummary(ctx, walletDB, baseUserID+2).Count == 2, "cross-tier wallet should receive two reward grants") + + _, err := updateConfigWithTiers(ctx, adminClient, runID+"_duplicate_threshold", true, []*activityv1.CumulativeRechargeRewardTier{ + {TierCode: runID + "_dup_a", TierName: "Duplicate A", ThresholdUsdMinor: 10_000, ResourceGroupId: group100, Status: statusActive, SortOrder: 1}, + {TierCode: runID + "_dup_b", TierName: "Duplicate B", ThresholdUsdMinor: 10_000, ResourceGroupId: group200, Status: statusActive, SortOrder: 2}, + }) + assert(err != nil, "duplicate active thresholds must be rejected") + + _, err = updateConfigWithTiers(ctx, adminClient, runID+"_disabled", false, []*activityv1.CumulativeRechargeRewardTier{ + {TierCode: runID + "_disabled_100", TierName: "Disabled $100", ThresholdUsdMinor: 10_000, ResourceGroupId: group100, Status: statusActive, SortOrder: 1}, + {TierCode: runID + "_disabled_200", TierName: "Disabled $200", ThresholdUsdMinor: 20_000, ResourceGroupId: group200, Status: statusActive, SortOrder: 2}, + }) + must("disable cumulative recharge config", err) + disabled := consumeRecharge(ctx, rewardClient, runID, "disabled-event", baseUserID+3, "google_play", 22_500_000, 25_000, now.Add(12*time.Minute)) + assert(disabled.GetReason() == "disabled" && len(disabled.GetGrants()) == 0, "disabled config should consume event without grants") + assert(queryProgress(ctx, activityDB, baseUserID+3, currentCycle.Key) == 0, "disabled config should not update progress") + updateConfig(ctx, adminClient, runID+"_reenable_after_disabled", group100, group200) + disabledAgain := consumeRecharge(ctx, rewardClient, runID, "disabled-event", baseUserID+3, "google_play", 22_500_000, 25_000, now.Add(12*time.Minute)) + assert(disabledAgain.GetReason() == "already_consumed" && queryProgress(ctx, activityDB, baseUserID+3, currentCycle.Key) == 0, "disabled-period event must not backfill after re-enable") + + _, err = updateConfigWithTiers(ctx, adminClient, runID+"_inactive", true, []*activityv1.CumulativeRechargeRewardTier{ + {TierCode: runID + "_inactive_100", TierName: "Inactive $100", ThresholdUsdMinor: 10_000, ResourceGroupId: group100, Status: tierStatusInactive, SortOrder: 1}, + {TierCode: runID + "_active_200", TierName: "Active $200", ThresholdUsdMinor: 20_000, ResourceGroupId: group200, Status: statusActive, SortOrder: 2}, + }) + must("set inactive tier config", err) + inactive := consumeRecharge(ctx, rewardClient, runID, "inactive-tier", baseUserID+4, "mifapay", 22_500_000, 25_000, now.Add(13*time.Minute)) + assertGrantThresholds("inactive $100 tier should be ignored", inactive.GetGrants(), []int64{20_000}) + assert(queryGrantSummary(ctx, activityDB, baseUserID+4, currentCycle.Key).Count == 1, "inactive tier should not create a grant row") + + failingGroup := createCoinRewardGroup(ctx, walletClient, runID, "disabled_group", 1000) + setResourceGroupStatus(ctx, walletClient, runID, failingGroup, statusDisabled) + _, err = updateConfigWithTiers(ctx, adminClient, runID+"_failed_retry", true, []*activityv1.CumulativeRechargeRewardTier{ + {TierCode: runID + "_failed_100", TierName: "Failed then retry", ThresholdUsdMinor: 10_000, ResourceGroupId: failingGroup, Status: statusActive, SortOrder: 1}, + }) + must("set disabled resource group tier", err) + _, err = consumeRechargeAllowError(ctx, rewardClient, runID, "failed-wallet", baseUserID+5, "google_play", 13_500_000, 15_000, now.Add(14*time.Minute)) + assert(err != nil, "disabled wallet resource group should fail grant") + assert(queryGrantStatus(ctx, activityDB, baseUserID+5, currentCycle.Key, 10_000) == "failed", "failed wallet grant should persist failed status") + setResourceGroupStatus(ctx, walletClient, runID, failingGroup, statusActive) + retried := consumeRecharge(ctx, rewardClient, runID, "failed-wallet", baseUserID+5, "google_play", 13_500_000, 15_000, now.Add(14*time.Minute)) + assertGrantThresholds("same event retry should grant after group enabled", retried.GetGrants(), []int64{10_000}) + assert(queryProgress(ctx, activityDB, baseUserID+5, currentCycle.Key) == 15_000, "failed retry must not double progress") + assert(queryGrantStatus(ctx, activityDB, baseUserID+5, currentCycle.Key, 10_000) == "granted", "retried wallet grant should be granted") + + updateConfig(ctx, adminClient, runID+"_week_boundary", group100, group200) + endBoundary := consumeRecharge(ctx, rewardClient, runID, "week-end", baseUserID+6, "google_play", 9_000_000, 10_000, time.UnixMilli(currentCycle.EndMS).UTC()) + assertGrantThresholds("event at cycle end should belong current cycle", endBoundary.GetGrants(), []int64{10_000}) + nextBoundary := consumeRecharge(ctx, rewardClient, runID, "week-next", baseUserID+6, "google_play", 9_000_000, 10_000, time.UnixMilli(currentCycle.EndMS+1).UTC()) + assertGrantThresholds("event after cycle end should belong next cycle", nextBoundary.GetGrants(), []int64{10_000}) + assert(queryProgress(ctx, activityDB, baseUserID+6, currentCycle.Key) == 10_000, "cycle end progress should stay current week") + assert(queryProgress(ctx, activityDB, baseUserID+6, nextCycle.Key) == 10_000, "cycle start progress should reset next week") + + _, err = consumeRechargeAllowError(ctx, rewardClient, runID, "zero-usd", baseUserID+7, "google_play", 10_000, 0, now.Add(15*time.Minute)) + assert(err != nil, "zero qualifying USD event must be rejected by direct consume entry") + assert(queryProgress(ctx, activityDB, baseUserID+7, currentCycle.Key) == 0, "zero qualifying USD event must not write progress") + + updateConfig(ctx, adminClient, runID+"_restore", group100, group200) + out := map[string]any{ + "mode": "boundary", + "run_id": runID, + "base_user_id": baseUserID, + "current_cycle": currentCycle.Key, + "next_cycle": nextCycle.Key, + "cases": map[string]any{ + "duplicate_event": map[string]any{"progress_usd_minor": queryProgress(ctx, activityDB, baseUserID+1, currentCycle.Key), "grant_count": queryGrantSummary(ctx, activityDB, baseUserID+1, currentCycle.Key).Count}, + "cross_multiple_tiers": map[string]any{"grant_thresholds": thresholds(cross.GetGrants()), "wallet_grants": queryWalletRewardSummary(ctx, walletDB, baseUserID+2).Count}, + "disabled_no_backfill": map[string]any{"first_reason": disabled.GetReason(), "retry_reason": disabledAgain.GetReason(), "progress_usd_minor": queryProgress(ctx, activityDB, baseUserID+3, currentCycle.Key)}, + "inactive_tier_ignored": map[string]any{"grant_thresholds": thresholds(inactive.GetGrants())}, + "failed_retry": map[string]any{"final_status": queryGrantStatus(ctx, activityDB, baseUserID+5, currentCycle.Key, 10_000), "progress_usd_minor": queryProgress(ctx, activityDB, baseUserID+5, currentCycle.Key)}, + "week_boundary": map[string]any{"current_progress": queryProgress(ctx, activityDB, baseUserID+6, currentCycle.Key), "next_progress": queryProgress(ctx, activityDB, baseUserID+6, nextCycle.Key)}, + "zero_usd_rejected": map[string]any{"progress_usd_minor": queryProgress(ctx, activityDB, baseUserID+7, currentCycle.Key)}, + }, + } + encoded, _ := json.MarshalIndent(out, "", " ") + fmt.Println(string(encoded)) +} + +func queryProgress(ctx context.Context, db *sql.DB, userID int64, cycleKey string) int64 { + var total sql.NullInt64 + err := db.QueryRowContext(ctx, ` + SELECT total_usd_minor + FROM cumulative_recharge_reward_progress + WHERE app_code = ? AND user_id = ? AND cycle_key = ?`, + appCode, userID, cycleKey, + ).Scan(&total) + if err == sql.ErrNoRows { + return 0 + } + must("query cumulative progress "+cycleKey, err) + return total.Int64 +} + +type grantSummary struct { + Count int64 `json:"count"` + Granted int64 `json:"granted"` +} + +func queryGrantSummary(ctx context.Context, db *sql.DB, userID int64, cycleKey string) grantSummary { + var summary grantSummary + err := db.QueryRowContext(ctx, ` + SELECT COUNT(*), COALESCE(SUM(CASE WHEN status = 'granted' THEN 1 ELSE 0 END), 0) + FROM cumulative_recharge_reward_grants + WHERE app_code = ? AND user_id = ? AND cycle_key = ?`, + appCode, userID, cycleKey, + ).Scan(&summary.Count, &summary.Granted) + must("query cumulative grants "+cycleKey, err) + return summary +} + +func queryGrantStatus(ctx context.Context, db *sql.DB, userID int64, cycleKey string, thresholdUSDMinor int64) string { + var status string + err := db.QueryRowContext(ctx, ` + SELECT status + FROM cumulative_recharge_reward_grants + WHERE app_code = ? AND user_id = ? AND cycle_key = ? AND threshold_usd_minor = ? + ORDER BY created_at_ms DESC + LIMIT 1`, + appCode, userID, cycleKey, thresholdUSDMinor, + ).Scan(&status) + must("query cumulative grant status", err) + return status +} + +type walletRewardSummary struct { + Count int64 `json:"count"` + CoinDelta int64 `json:"coin_delta"` +} + +func queryWalletRewardSummary(ctx context.Context, db *sql.DB, userID int64) walletRewardSummary { + var summary walletRewardSummary + err := db.QueryRowContext(ctx, ` + SELECT COUNT(DISTINCT rg.grant_id), COALESCE(SUM(we.available_delta), 0) + FROM resource_grants rg + JOIN resource_grant_items rgi ON rgi.app_code = rg.app_code AND rgi.grant_id = rg.grant_id + JOIN wallet_entries we ON we.app_code = rgi.app_code AND we.transaction_id = rgi.wallet_transaction_id AND we.user_id = rg.target_user_id + WHERE rg.app_code = ? AND rg.target_user_id = ? AND rg.grant_source = ? AND we.asset_type = ?`, + appCode, userID, rechargeSource, assetCoin, + ).Scan(&summary.Count, &summary.CoinDelta) + must("query wallet reward grants", err) + return summary +} + +func meta(requestID string) *activityv1.RequestMeta { + return &activityv1.RequestMeta{ + RequestId: requestID, + Caller: "local-cumulative-recharge-flow", + AppCode: appCode, + SentAtMs: time.Now().UnixMilli(), + } +} + +func cycleForTime(value time.Time) cycle { + utc := value.UTC() + dayStart := time.Date(utc.Year(), utc.Month(), utc.Day(), 0, 0, 0, 0, time.UTC) + daysSinceMonday := (int(dayStart.Weekday()) + 6) % 7 + start := dayStart.AddDate(0, 0, -daysSinceMonday) + end := start.AddDate(0, 0, 7) + isoYear, isoWeek := start.ISOWeek() + return cycle{Key: fmt.Sprintf("%04d-W%02d", isoYear, isoWeek), StartMS: start.UnixMilli(), EndMS: end.UnixMilli() - 1} +} + +func assertGrantThresholds(message string, grants []*activityv1.CumulativeRechargeRewardGrant, want []int64) { + got := thresholds(grants) + if len(got) != len(want) { + log.Fatalf("%s: got %v want %v", message, got, want) + } + for i := range want { + if got[i] != want[i] { + log.Fatalf("%s: got %v want %v", message, got, want) + } + } +} + +func thresholds(grants []*activityv1.CumulativeRechargeRewardGrant) []int64 { + items := make([]int64, 0, len(grants)) + for _, grant := range grants { + if grant == nil { + continue + } + items = append(items, grant.GetThresholdUsdMinor()) + } + sort.Slice(items, func(i, j int) bool { return items[i] < items[j] }) + return items +} + +func assert(ok bool, message string) { + if !ok { + log.Fatal(message) + } +} + +func must(action string, err error) { + if err != nil { + log.Fatalf("%s: %v", action, err) + } +} diff --git a/tools/weekly-star-local-boundary/main.go b/tools/weekly-star-local-boundary/main.go new file mode 100644 index 00000000..cf32abaf --- /dev/null +++ b/tools/weekly-star-local-boundary/main.go @@ -0,0 +1,660 @@ +package main + +import ( + "context" + "database/sql" + "encoding/json" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + activityv1 "hyapp.local/api/proto/activity/v1" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" +) + +const ( + defaultAppCode = "lalu" + boundaryTitlePrefix = "Local Weekly Star Boundary" + activityCode = "weekly_star" + statusActive = "active" + statusDisabled = "disabled" + rewardGroupTop1ID = int64(930001) + rewardGroupTop2ID = int64(930002) + rewardGroupTop3ID = int64(930003) + testOperatorAdmin = int64(900001) + testTargetAnchorID = int64(990001) + localBoundaryRoomID = "weekly-star-boundary-room" +) + +type config struct { + activityAddr string + activityDSN string + walletDSN string + appCode string + regionID int64 +} + +type clients struct { + admin activityv1.AdminWeeklyStarServiceClient + app activityv1.WeeklyStarServiceClient + room activityv1.RoomEventConsumerServiceClient + cron activityv1.ActivityCronServiceClient +} + +type boundarySummary struct { + RunID string `json:"run_id"` + RegionID int64 `json:"region_id"` + Passed []string `json:"passed"` + Skipped []string `json:"skipped"` + Diagnostics map[string]string `json:"diagnostics"` +} + +type leaderboardEntry struct { + RankNo int32 `json:"rank_no"` + UserID int64 `json:"user_id"` + Score int64 `json:"score"` +} + +type settlementRow struct { + RankNo int32 + UserID int64 + Score int64 + ResourceGroupID int64 + Status string +} + +type cycleWindow struct { + startMS int64 + endMS int64 +} + +func main() { + cfg := config{} + flag.StringVar(&cfg.activityAddr, "activity-addr", "127.0.0.1:13006", "activity-service gRPC address") + flag.StringVar(&cfg.activityDSN, "activity-dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC", "activity MySQL DSN") + flag.StringVar(&cfg.walletDSN, "wallet-dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC", "wallet MySQL DSN") + flag.StringVar(&cfg.appCode, "app-code", defaultAppCode, "app code") + flag.Int64Var(&cfg.regionID, "region-id", 991686, "local boundary-test region id") + flag.Parse() + + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + activityDB := mustOpenDB(ctx, cfg.activityDSN) + defer activityDB.Close() + walletDB := mustOpenDB(ctx, cfg.walletDSN) + defer walletDB.Close() + + runID := fmt.Sprintf("%d", time.Now().UTC().UnixMilli()) + cleanupBoundaryCycles(ctx, activityDB, cfg) + seedWalletRewardGroups(ctx, walletDB, cfg.appCode) + + conn, err := grpc.DialContext(ctx, cfg.activityAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + if err != nil { + log.Fatalf("dial activity-service: %v", err) + } + defer conn.Close() + clients := clients{ + admin: activityv1.NewAdminWeeklyStarServiceClient(conn), + app: activityv1.NewWeeklyStarServiceClient(conn), + room: activityv1.NewRoomEventConsumerServiceClient(conn), + cron: activityv1.NewActivityCronServiceClient(conn), + } + + summary := boundarySummary{ + RunID: runID, + RegionID: cfg.regionID, + Passed: make([]string, 0), + Skipped: make([]string, 0), + Diagnostics: make(map[string]string), + } + + runOverlapRejected(ctx, clients, cfg, runID, &summary) + runValidationRejected(ctx, clients, cfg, runID, &summary) + runRegionFallback(ctx, activityDB, clients, cfg, runID, &summary) + runTimeBoundaryAndIgnoredGift(ctx, clients, cfg, runID, &summary) + runTieBreaking(ctx, clients, cfg, runID, &summary) + runDisabledCycleIgnored(ctx, clients, cfg, runID, &summary) + runIdempotentAndBeforeStartIgnored(ctx, clients, cfg, runID, &summary) + runTop3SettlementGrantsOnlyWinners(ctx, activityDB, walletDB, clients, cfg, runID, &summary) + runNoScoreSettlement(ctx, activityDB, walletDB, clients, cfg, runID, &summary) + + encoder := json.NewEncoder(os.Stdout) + encoder.SetIndent("", " ") + if err := encoder.Encode(summary); err != nil { + log.Fatalf("encode boundary summary: %v", err) + } +} + +func runOverlapRejected(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + gifts := giftsFor("overlap", runID) + baseCycle := createCycle(ctx, clients.admin, cfg, cfg.regionID+10, fmt.Sprintf("%s overlap base %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, gifts) + _, err := createCycleAllowError(ctx, clients.admin, cfg, cfg.regionID+10, fmt.Sprintf("%s overlap conflict %s", boundaryTitlePrefix, runID), statusActive, window.startMS+1_000, window.endMS-1_000, gifts) + if status.Code(err) != codes.FailedPrecondition { + log.Fatalf("overlap should be rejected with FailedPrecondition, got %v", err) + } + summary.Diagnostics["overlap_base_cycle"] = baseCycle.GetCycleId() + pass(summary, "overlap_active_cycle_rejected") +} + +func runValidationRejected(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + twoGifts := []string{"weekly_star_boundary_invalid_a_" + runID, "weekly_star_boundary_invalid_b_" + runID} + _, giftErr := createCycleAllowError(ctx, clients.admin, cfg, cfg.regionID+20, fmt.Sprintf("%s invalid gift count %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, twoGifts) + if status.Code(giftErr) != codes.InvalidArgument { + log.Fatalf("cycle with two gifts should be InvalidArgument, got %v", giftErr) + } + _, rewardErr := createCycleWithRewardsAllowError(ctx, clients.admin, cfg, cfg.regionID+21, fmt.Sprintf("%s missing reward %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, giftsFor("missing_reward", runID), []*activityv1.WeeklyStarReward{ + {RankNo: 1, ResourceGroupId: rewardGroupTop1ID}, + {RankNo: 2, ResourceGroupId: rewardGroupTop2ID}, + }) + if status.Code(rewardErr) != codes.InvalidArgument { + log.Fatalf("cycle missing top3 reward should be InvalidArgument, got %v", rewardErr) + } + pass(summary, "exactly_three_gifts_and_top3_rewards_required") +} + +func runRegionFallback(ctx context.Context, db *sql.DB, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + defaultGifts := giftsFor("default_region", runID) + concreteGifts := giftsFor("concrete_region", runID) + defaultCycle, err := createCycleAllowError(ctx, clients.admin, cfg, 0, fmt.Sprintf("%s default region %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, defaultGifts) + if err != nil { + existingID, ok := currentCycleIDFromDB(ctx, db, cfg, 0, time.Now().UTC().UnixMilli()) + if !ok { + log.Fatalf("create default cycle failed and no existing default current cycle is available: %v", err) + } + summary.Skipped = append(summary.Skipped, "controlled_default_cycle_create: existing active default cycle "+existingID) + defaultCycle = &activityv1.WeeklyStarCycle{CycleId: existingID, RegionId: 0} + } + concreteCycle := createCycle(ctx, clients.admin, cfg, cfg.regionID+30, fmt.Sprintf("%s concrete region %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, concreteGifts) + + concreteCurrent := getCurrent(ctx, clients.app, cfg, cfg.regionID+30, 710001) + if concreteCurrent.GetCycle().GetCycleId() != concreteCycle.GetCycleId() { + log.Fatalf("concrete region should preempt default, got %s want %s", concreteCurrent.GetCycle().GetCycleId(), concreteCycle.GetCycleId()) + } + defaultCurrent := getCurrent(ctx, clients.app, cfg, cfg.regionID+31, 710001) + if defaultCurrent.GetCycle().GetRegionId() != 0 || defaultCurrent.GetCycle().GetCycleId() == concreteCycle.GetCycleId() || defaultCurrent.GetCycle().GetCycleId() == "" { + log.Fatalf("region without concrete cycle should fall back to default, got cycle=%s region=%d", defaultCurrent.GetCycle().GetCycleId(), defaultCurrent.GetCycle().GetRegionId()) + } + summary.Diagnostics["default_cycle_used"] = defaultCycle.GetCycleId() + summary.Diagnostics["concrete_cycle_used"] = concreteCycle.GetCycleId() + pass(summary, "region_specific_cycle_preempts_default_and_default_fallback_works") +} + +func runTimeBoundaryAndIgnoredGift(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + regionID := cfg.regionID + 40 + gifts := giftsFor("time_boundary", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s time boundary %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, gifts) + + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "time-start"), 720001, gifts[0], 100, window.startMS, 1) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "time-end"), 720002, gifts[0], 200, window.endMS, 2) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "time-non-config"), 720003, "weekly_star_boundary_not_configured_"+runID, 300, window.startMS+1_000, 3) + + entries := listLeaderboard(ctx, clients.admin, cfg, regionID, cycle.GetCycleId()) + assertLeaderboardExact("time boundary", entries, []leaderboardEntry{{RankNo: 1, UserID: 720001, Score: 100}}) + summary.Diagnostics["time_boundary_cycle"] = cycle.GetCycleId() + pass(summary, "start_inclusive_end_exclusive_and_non_configured_gift_ignored") +} + +func runTieBreaking(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + regionID := cfg.regionID + 50 + gifts := giftsFor("tie_breaking", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s tie breaking %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, gifts) + + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "tie-later-small-id"), 730001, gifts[0], 1000, window.startMS+2_000, 1) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "tie-later-large-id"), 730002, gifts[0], 1000, window.startMS+2_000, 2) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "tie-earliest"), 730003, gifts[0], 1000, window.startMS+1_000, 3) + + entries := listLeaderboard(ctx, clients.admin, cfg, regionID, cycle.GetCycleId()) + assertLeaderboardExact("tie breaking", entries, []leaderboardEntry{ + {RankNo: 1, UserID: 730003, Score: 1000}, + {RankNo: 2, UserID: 730001, Score: 1000}, + {RankNo: 3, UserID: 730002, Score: 1000}, + }) + summary.Diagnostics["tie_breaking_cycle"] = cycle.GetCycleId() + pass(summary, "tie_breaking_score_first_scored_at_user_id") +} + +func runDisabledCycleIgnored(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + regionID := cfg.regionID + 60 + gifts := giftsFor("disabled", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s disabled ignored %s", boundaryTitlePrefix, runID), statusDisabled, window.startMS, window.endMS, gifts) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "disabled-gift"), 740001, gifts[0], 777, window.startMS+1_000, 1) + entries := listLeaderboard(ctx, clients.admin, cfg, regionID, cycle.GetCycleId()) + if len(entries) != 0 { + log.Fatalf("disabled cycle should ignore gift events, got leaderboard %+v", entries) + } + summary.Diagnostics["disabled_cycle"] = cycle.GetCycleId() + pass(summary, "disabled_cycle_ignored") +} + +func runIdempotentAndBeforeStartIgnored(ctx context.Context, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + regionID := cfg.regionID + 65 + gifts := giftsFor("idempotency", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s idempotency %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, gifts) + + // A gift before the configured UTC window must not create score, even when the + // gift id is configured; otherwise delayed or wrongly timestamped events can + // leak into the leaderboard before the cycle actually begins. + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "before-start"), 750001, gifts[0], 900, window.startMS-1, 1) + // The first in-window event should score once, and the second delivery with + // the same source_event_id must be treated as replay protection rather than a + // second gift spend. This is the room event idempotency boundary that protects + // RocketMQ retries and local replay tooling. + duplicateID := eventID(runID, "duplicate-score") + consumeGiftEvent(ctx, clients.room, cfg, regionID, duplicateID, 750002, gifts[0], 600, window.startMS+1_000, 2) + consumeGiftEvent(ctx, clients.room, cfg, regionID, duplicateID, 750002, gifts[0], 600, window.startMS+1_000, 2) + + entries := listLeaderboard(ctx, clients.admin, cfg, regionID, cycle.GetCycleId()) + assertLeaderboardExact("idempotency", entries, []leaderboardEntry{{RankNo: 1, UserID: 750002, Score: 600}}) + summary.Diagnostics["idempotency_cycle"] = cycle.GetCycleId() + pass(summary, "before_start_ignored_and_duplicate_event_id_idempotent") +} + +func runTop3SettlementGrantsOnlyWinners(ctx context.Context, activityDB *sql.DB, walletDB *sql.DB, clients clients, cfg config, runID string, summary *boundarySummary) { + window := currentWindow() + regionID := cfg.regionID + 68 + gifts := giftsFor("top3_settlement", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s top3 settlement %s", boundaryTitlePrefix, runID), statusActive, window.startMS, window.endMS, gifts) + + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "settle-top1"), 760001, gifts[0], 1_200, window.startMS+1_000, 1) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "settle-top2"), 760002, gifts[0], 900, window.startMS+2_000, 2) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "settle-top3"), 760003, gifts[0], 800, window.startMS+3_000, 3) + consumeGiftEvent(ctx, clients.room, cfg, regionID, eventID(runID, "settle-fourth"), 760004, gifts[0], 700, window.startMS+4_000, 4) + + // The test first records score in a normal current cycle, then moves only this + // cycle's end time into the past. This keeps the event-consume path realistic + // while making settlement deterministic without waiting for wall-clock time. + nowMS := time.Now().UTC().UnixMilli() + mustExec(ctx, activityDB, ` + UPDATE weekly_star_cycles + SET end_ms = ?, updated_at_ms = ? + WHERE app_code = ? AND cycle_id = ?`, + nowMS-1, nowMS, cfg.appCode, cycle.GetCycleId(), + ) + triggerWeeklyStarSettlementUntilSettled(ctx, activityDB, clients, cfg, runID, "top3-settlement", cycle.GetCycleId()) + + rows := settlementRowsFromDB(ctx, activityDB, cfg, cycle.GetCycleId()) + expected := []settlementRow{ + {RankNo: 1, UserID: 760001, Score: 1_200, ResourceGroupID: rewardGroupTop1ID, Status: "granted"}, + {RankNo: 2, UserID: 760002, Score: 900, ResourceGroupID: rewardGroupTop2ID, Status: "granted"}, + {RankNo: 3, UserID: 760003, Score: 800, ResourceGroupID: rewardGroupTop3ID, Status: "granted"}, + } + if len(rows) != len(expected) { + log.Fatalf("top3 settlement row count mismatch: got %d want %d rows=%+v", len(rows), len(expected), rows) + } + for index, want := range expected { + if rows[index] != want { + log.Fatalf("top3 settlement row %d mismatch: got %+v want %+v", index+1, rows[index], want) + } + } + if countWalletGrantsForCycle(ctx, walletDB, cfg, cycle.GetCycleId()) != 3 { + log.Fatalf("top3 settlement should create exactly 3 wallet grants") + } + summary.Diagnostics["top3_settlement_cycle"] = cycle.GetCycleId() + pass(summary, "settlement_grants_top3_only") +} + +func runNoScoreSettlement(ctx context.Context, activityDB *sql.DB, walletDB *sql.DB, clients clients, cfg config, runID string, summary *boundarySummary) { + // Use an old, isolated window and a single-cycle batch so this boundary check + // settles the cycle created by this run instead of depending on whatever old + // local test data may already be due in the developer database. + oldWindowStart := time.Date(2001, time.January, 1, 0, 0, 0, 0, time.UTC).Add(time.Duration(time.Now().UTC().UnixNano()%int64(time.Hour)) * time.Nanosecond) + oldWindowEnd := oldWindowStart.Add(time.Hour) + regionID := cfg.regionID + 70 + gifts := giftsFor("no_score", runID) + cycle := createCycle(ctx, clients.admin, cfg, regionID, fmt.Sprintf("%s no score settlement %s", boundaryTitlePrefix, runID), statusActive, oldWindowStart.UnixMilli(), oldWindowEnd.UnixMilli(), gifts) + + resp, err := clients.cron.ProcessWeeklyStarSettlementBatch(ctx, &activityv1.CronBatchRequest{ + Meta: meta(cfg, "weekly-star-boundary-cron-"+runID), + RunId: "weekly-star-boundary-" + runID, + WorkerId: "weekly-star-boundary", + BatchSize: 1, + LockTtlMs: int64((30 * time.Second) / time.Millisecond), + }) + if err != nil { + log.Fatalf("no-score settlement cron failed: %v", err) + } + if resp.GetClaimedCount() != 1 || resp.GetProcessedCount() != 1 || resp.GetSuccessCount() != 1 || resp.GetFailureCount() != 0 { + log.Fatalf("unexpected no-score cron result: claimed=%d processed=%d success=%d failure=%d", resp.GetClaimedCount(), resp.GetProcessedCount(), resp.GetSuccessCount(), resp.GetFailureCount()) + } + statusValue := cycleStatusFromDB(ctx, activityDB, cfg, cycle.GetCycleId()) + if statusValue != "settled" { + log.Fatalf("no-score cycle should be settled, got %s", statusValue) + } + if countSettlements(ctx, activityDB, cfg, cycle.GetCycleId()) != 0 { + log.Fatalf("no-score cycle should not create settlement rows") + } + if countWalletGrantsForCycle(ctx, walletDB, cfg, cycle.GetCycleId()) != 0 { + log.Fatalf("no-score cycle should not create wallet grants") + } + summary.Diagnostics["no_score_cycle"] = cycle.GetCycleId() + pass(summary, "no_score_cycle_settles_without_grants") +} + +func triggerWeeklyStarSettlementUntilSettled(ctx context.Context, db *sql.DB, clients clients, cfg config, runID string, label string, cycleID string) { + for attempt := 1; attempt <= 8; attempt++ { + _, err := clients.cron.ProcessWeeklyStarSettlementBatch(ctx, &activityv1.CronBatchRequest{ + Meta: meta(cfg, fmt.Sprintf("weekly-star-boundary-cron-%s-%s-%d", label, runID, attempt)), + RunId: fmt.Sprintf("weekly-star-boundary-%s-%s-%d", label, runID, attempt), + WorkerId: "weekly-star-boundary", + BatchSize: 5, + LockTtlMs: int64((30 * time.Second) / time.Millisecond), + }) + if err != nil { + log.Fatalf("trigger weekly star settlement %s: %v", cycleID, err) + } + if cycleStatusFromDB(ctx, db, cfg, cycleID) == "settled" { + return + } + time.Sleep(200 * time.Millisecond) + } + log.Fatalf("cycle %s was not settled after repeated cron attempts", cycleID) +} + +func currentWindow() cycleWindow { + now := time.Now().UTC() + return cycleWindow{startMS: now.Add(-2 * time.Minute).UnixMilli(), endMS: now.Add(30 * time.Minute).UnixMilli()} +} + +func giftsFor(label string, runID string) []string { + return []string{ + "weekly_star_boundary_" + label + "_a_" + runID, + "weekly_star_boundary_" + label + "_b_" + runID, + "weekly_star_boundary_" + label + "_c_" + runID, + } +} + +func cleanupBoundaryCycles(ctx context.Context, db *sql.DB, cfg config) { + mustExec(ctx, db, ` + UPDATE weekly_star_cycles + SET status = 'disabled', locked_by = '', lock_until_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND activity_code = ? AND title LIKE ? AND status IN ('active', 'settling')`, + time.Now().UTC().UnixMilli(), cfg.appCode, activityCode, boundaryTitlePrefix+"%", + ) +} + +func seedWalletRewardGroups(ctx context.Context, db *sql.DB, appCode string) { + nowMS := time.Now().UTC().UnixMilli() + type groupSeed struct { + groupID int64 + code string + name string + coins int64 + } + seeds := []groupSeed{ + {groupID: rewardGroupTop1ID, code: "weekly_star_local_top1", name: "Weekly Star Local Top 1", coins: 111_000}, + {groupID: rewardGroupTop2ID, code: "weekly_star_local_top2", name: "Weekly Star Local Top 2", coins: 66_000}, + {groupID: rewardGroupTop3ID, code: "weekly_star_local_top3", name: "Weekly Star Local Top 3", coins: 33_000}, + } + for index, seed := range seeds { + mustExec(ctx, db, ` + INSERT INTO resource_groups ( + app_code, group_id, group_code, name, status, description, sort_order, + created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 'active', 'local weekly star boundary reward group', ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + name = VALUES(name), status = 'active', description = VALUES(description), + sort_order = VALUES(sort_order), updated_by_user_id = VALUES(updated_by_user_id), updated_at_ms = VALUES(updated_at_ms)`, + appCode, seed.groupID, seed.code, seed.name, index+1, testOperatorAdmin, testOperatorAdmin, nowMS, nowMS, + ) + mustExec(ctx, db, ` + INSERT INTO resource_group_items ( + app_code, group_id, item_type, resource_id, wallet_asset_type, wallet_asset_amount, + quantity, duration_ms, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, 'wallet_asset', 0, 'COIN', ?, 1, 0, 1, ?, ?) + ON DUPLICATE KEY UPDATE + wallet_asset_amount = VALUES(wallet_asset_amount), sort_order = VALUES(sort_order), updated_at_ms = VALUES(updated_at_ms)`, + appCode, seed.groupID, seed.coins, nowMS, nowMS, + ) + } +} + +func createCycle(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg config, regionID int64, title string, cycleStatus string, startMS int64, endMS int64, gifts []string) *activityv1.WeeklyStarCycle { + cycle, err := createCycleAllowError(ctx, client, cfg, regionID, title, cycleStatus, startMS, endMS, gifts) + if err != nil { + log.Fatalf("create cycle %q: %v", title, err) + } + return cycle +} + +func createCycleAllowError(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg config, regionID int64, title string, cycleStatus string, startMS int64, endMS int64, gifts []string) (*activityv1.WeeklyStarCycle, error) { + return createCycleWithRewardsAllowError(ctx, client, cfg, regionID, title, cycleStatus, startMS, endMS, gifts, []*activityv1.WeeklyStarReward{ + {RankNo: 1, ResourceGroupId: rewardGroupTop1ID}, + {RankNo: 2, ResourceGroupId: rewardGroupTop2ID}, + {RankNo: 3, ResourceGroupId: rewardGroupTop3ID}, + }) +} + +func createCycleWithRewardsAllowError(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg config, regionID int64, title string, cycleStatus string, startMS int64, endMS int64, gifts []string, rewards []*activityv1.WeeklyStarReward) (*activityv1.WeeklyStarCycle, error) { + giftItems := make([]*activityv1.WeeklyStarGift, 0, len(gifts)) + for index, gift := range gifts { + giftItems = append(giftItems, &activityv1.WeeklyStarGift{GiftId: gift, SortOrder: int32(index + 1)}) + } + resp, err := client.CreateWeeklyStarCycle(ctx, &activityv1.UpsertWeeklyStarCycleRequest{ + Meta: meta(cfg, "weekly-star-boundary-create-"+sanitize(title)), + Cycle: &activityv1.WeeklyStarCycle{ + ActivityCode: activityCode, + RegionId: regionID, + Title: title, + Status: cycleStatus, + StartMs: startMS, + EndMs: endMS, + Gifts: giftItems, + Rewards: rewards, + }, + OperatorAdminId: testOperatorAdmin, + }) + if err != nil { + return nil, err + } + if resp.GetCycle().GetCycleId() == "" { + return nil, fmt.Errorf("empty cycle_id") + } + return resp.GetCycle(), nil +} + +func consumeGiftEvent(ctx context.Context, client activityv1.RoomEventConsumerServiceClient, cfg config, regionID int64, eventID string, userID int64, giftID string, score int64, occurredAtMS int64, version int64) { + body, err := proto.Marshal(&roomeventsv1.RoomGiftSent{ + SenderUserId: userID, + TargetUserId: testTargetAnchorID, + GiftId: giftID, + GiftCount: 1, + GiftValue: 1, + BillingReceiptId: eventID + "-receipt", + VisibleRegionId: regionID, + CommandId: eventID + "-command", + CoinSpent: score, + }) + if err != nil { + log.Fatalf("marshal room gift sent: %v", err) + } + _, err = client.ConsumeRoomEvent(ctx, &activityv1.ConsumeRoomEventRequest{ + Meta: meta(cfg, "weekly-star-boundary-event-"+eventID), + Envelope: &roomeventsv1.EventEnvelope{ + EventId: eventID, + RoomId: localBoundaryRoomID, + EventType: "RoomGiftSent", + RoomVersion: version, + OccurredAtMs: occurredAtMS, + Body: body, + AppCode: cfg.appCode, + }, + }) + if err != nil { + log.Fatalf("consume room gift event %s: %v", eventID, err) + } +} + +func getCurrent(ctx context.Context, client activityv1.WeeklyStarServiceClient, cfg config, regionID int64, userID int64) *activityv1.GetWeeklyStarCurrentResponse { + resp, err := client.GetWeeklyStarCurrent(ctx, &activityv1.GetWeeklyStarCurrentRequest{ + Meta: meta(cfg, "weekly-star-boundary-current-"+fmt.Sprint(regionID)), + UserId: userID, + RegionId: regionID, + }) + if err != nil { + log.Fatalf("get current region %d: %v", regionID, err) + } + if resp.GetCycle() == nil { + log.Fatalf("get current region %d returned nil cycle", regionID) + } + return resp +} + +func listLeaderboard(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg config, regionID int64, cycleID string) []leaderboardEntry { + resp, err := client.ListWeeklyStarLeaderboard(ctx, &activityv1.ListWeeklyStarLeaderboardRequest{ + Meta: meta(cfg, "weekly-star-boundary-leaderboard-"+cycleID), + CycleId: cycleID, + RegionId: regionID, + PageSize: 10, + }) + if err != nil { + log.Fatalf("list leaderboard %s: %v", cycleID, err) + } + out := make([]leaderboardEntry, 0, len(resp.GetEntries())) + for _, entry := range resp.GetEntries() { + out = append(out, leaderboardEntry{RankNo: entry.GetRankNo(), UserID: entry.GetUserId(), Score: entry.GetScore()}) + } + return out +} + +func assertLeaderboardExact(label string, actual []leaderboardEntry, expected []leaderboardEntry) { + if len(actual) != len(expected) { + log.Fatalf("%s leaderboard length mismatch: got %d want %d entries=%+v", label, len(actual), len(expected), actual) + } + for index, want := range expected { + if actual[index] != want { + log.Fatalf("%s leaderboard row %d mismatch: got %+v want %+v", label, index+1, actual[index], want) + } + } +} + +func currentCycleIDFromDB(ctx context.Context, db *sql.DB, cfg config, regionID int64, nowMS int64) (string, bool) { + var cycleID string + err := db.QueryRowContext(ctx, ` + SELECT cycle_id + FROM weekly_star_cycles + WHERE app_code = ? AND activity_code = ? AND region_id = ? AND status = 'active' AND start_ms <= ? AND end_ms > ? + ORDER BY start_ms DESC, updated_at_ms DESC + LIMIT 1`, cfg.appCode, activityCode, regionID, nowMS, nowMS, + ).Scan(&cycleID) + if err == sql.ErrNoRows { + return "", false + } + if err != nil { + log.Fatalf("query current cycle from db: %v", err) + } + return cycleID, true +} + +func cycleStatusFromDB(ctx context.Context, db *sql.DB, cfg config, cycleID string) string { + var statusValue string + err := db.QueryRowContext(ctx, ` + SELECT status FROM weekly_star_cycles WHERE app_code = ? AND cycle_id = ?`, cfg.appCode, cycleID, + ).Scan(&statusValue) + if err != nil { + log.Fatalf("query cycle status %s: %v", cycleID, err) + } + return statusValue +} + +func countSettlements(ctx context.Context, db *sql.DB, cfg config, cycleID string) int { + var count int + if err := db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM weekly_star_settlements WHERE app_code = ? AND cycle_id = ?`, cfg.appCode, cycleID, + ).Scan(&count); err != nil { + log.Fatalf("count settlements: %v", err) + } + return count +} + +func countWalletGrantsForCycle(ctx context.Context, db *sql.DB, cfg config, cycleID string) int { + var count int + if err := db.QueryRowContext(ctx, ` + SELECT COUNT(*) FROM resource_grants WHERE app_code = ? AND command_id LIKE ?`, cfg.appCode, "weekly_star:"+cycleID+":%", + ).Scan(&count); err != nil { + log.Fatalf("count wallet grants: %v", err) + } + return count +} + +func settlementRowsFromDB(ctx context.Context, db *sql.DB, cfg config, cycleID string) []settlementRow { + rows, err := db.QueryContext(ctx, ` + SELECT rank_no, user_id, score, resource_group_id, status + FROM weekly_star_settlements + WHERE app_code = ? AND cycle_id = ? + ORDER BY rank_no ASC`, cfg.appCode, cycleID, + ) + if err != nil { + log.Fatalf("query settlement rows: %v", err) + } + defer rows.Close() + out := make([]settlementRow, 0, 3) + for rows.Next() { + var row settlementRow + if err := rows.Scan(&row.RankNo, &row.UserID, &row.Score, &row.ResourceGroupID, &row.Status); err != nil { + log.Fatalf("scan settlement row: %v", err) + } + out = append(out, row) + } + if err := rows.Err(); err != nil { + log.Fatalf("iterate settlement rows: %v", err) + } + return out +} + +func mustOpenDB(ctx context.Context, dsn string) *sql.DB { + db, err := sql.Open("mysql", dsn) + if err != nil { + log.Fatalf("open mysql: %v", err) + } + if err := db.PingContext(ctx); err != nil { + _ = db.Close() + log.Fatalf("ping mysql: %v", err) + } + return db +} + +func mustExec(ctx context.Context, db *sql.DB, query string, args ...any) { + if _, err := db.ExecContext(ctx, query, args...); err != nil { + log.Fatalf("exec mysql setup: %v", err) + } +} + +func meta(cfg config, requestID string) *activityv1.RequestMeta { + return &activityv1.RequestMeta{ + RequestId: requestID, + Caller: "weekly-star-local-boundary", + SentAtMs: time.Now().UTC().UnixMilli(), + AppCode: cfg.appCode, + } +} + +func eventID(runID string, label string) string { + return "weekly-star-boundary-" + runID + "-" + label +} + +func sanitize(value string) string { + return strings.NewReplacer(" ", "-", ":", "-", "/", "-").Replace(value) +} + +func pass(summary *boundarySummary, name string) { + summary.Passed = append(summary.Passed, name) + sort.Strings(summary.Passed) +} diff --git a/tools/weekly-star-local-flow/main.go b/tools/weekly-star-local-flow/main.go new file mode 100644 index 00000000..04bb1b19 --- /dev/null +++ b/tools/weekly-star-local-flow/main.go @@ -0,0 +1,473 @@ +package main + +import ( + "context" + "database/sql" + "encoding/json" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/protobuf/proto" + activityv1 "hyapp.local/api/proto/activity/v1" + roomeventsv1 "hyapp.local/api/proto/events/room/v1" +) + +const ( + defaultAppCode = "lalu" + localTitlePrefix = "Local Weekly Star Flow" + activityCode = "weekly_star" + cycleStatusActive = "active" + rewardGroupTop1ID = int64(930001) + rewardGroupTop2ID = int64(930002) + rewardGroupTop3ID = int64(930003) + testOperatorAdmin = int64(900001) + testTargetAnchorID = int64(990001) +) + +type flowConfig struct { + activityAddr string + activityDSN string + walletDSN string + appCode string + regionID int64 +} + +type flowSummary struct { + RunID string `json:"run_id"` + RegionID int64 `json:"region_id"` + FinishedCycleID string `json:"finished_cycle_id"` + CurrentCycleID string `json:"current_cycle_id"` + SentEvents []string `json:"sent_events"` + Leaderboard []leaderboardSummary `json:"leaderboard"` + Cron cronSummary `json:"cron"` + Settlements []settlementSummary `json:"settlements"` + WalletGrants []walletGrantSummary `json:"wallet_grants"` + CurrentCycleAfter string `json:"current_cycle_after"` + ExpectedAssertions map[string]string `json:"expected_assertions"` +} + +type leaderboardSummary struct { + RankNo int32 `json:"rank_no"` + UserID int64 `json:"user_id"` + Score int64 `json:"score"` +} + +type cronSummary struct { + Claimed int32 `json:"claimed"` + Processed int32 `json:"processed"` + Success int32 `json:"success"` + Failure int32 `json:"failure"` +} + +type settlementSummary struct { + RankNo int32 `json:"rank_no"` + UserID int64 `json:"user_id"` + Score int64 `json:"score"` + ResourceGroupID int64 `json:"resource_group_id"` + WalletCommandID string `json:"wallet_command_id"` + WalletGrantID string `json:"wallet_grant_id"` + Status string `json:"status"` +} + +type walletGrantSummary struct { + CommandID string `json:"command_id"` + GrantID string `json:"grant_id"` + TargetUserID int64 `json:"target_user_id"` + GrantSubjectID string `json:"grant_subject_id"` + Status string `json:"status"` +} + +func main() { + cfg := flowConfig{} + flag.StringVar(&cfg.activityAddr, "activity-addr", "127.0.0.1:13006", "activity-service gRPC address") + flag.StringVar(&cfg.activityDSN, "activity-dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_activity?parseTime=true&charset=utf8mb4&loc=UTC", "activity MySQL DSN") + flag.StringVar(&cfg.walletDSN, "wallet-dsn", "hyapp:hyapp@tcp(127.0.0.1:23306)/hyapp_wallet?parseTime=true&charset=utf8mb4&loc=UTC", "wallet MySQL DSN") + flag.StringVar(&cfg.appCode, "app-code", defaultAppCode, "app code") + flag.Int64Var(&cfg.regionID, "region-id", 990686, "local test region id") + flag.Parse() + if strings.TrimSpace(cfg.appCode) == "" { + log.Fatal("app-code is required") + } + + ctx, cancel := context.WithTimeout(context.Background(), 40*time.Second) + defer cancel() + + // activityDB 只用于准备和交叉验证测试夹具,不能直接写积分、settlement 或周期结果。 + // 真正的周期创建、送礼消费、榜单读取和结算都必须走 activity-service gRPC,才能覆盖线上同一套业务逻辑。 + activityDB := mustOpenDB(ctx, cfg.activityDSN) + defer activityDB.Close() + // walletDB 只用于准备本地资源组和最终审计 wallet grant;奖励发放必须通过 wallet-service GrantResourceGroup。 + walletDB := mustOpenDB(ctx, cfg.walletDSN) + defer walletDB.Close() + + // 只清理本工具创建的本地区域未完成周期,避免旧失败周期被本轮 cron 一起重试。 + mustExec(ctx, activityDB, ` + UPDATE weekly_star_cycles + SET status = 'disabled', locked_by = '', lock_until_ms = 0, updated_at_ms = ? + WHERE app_code = ? AND activity_code = ? AND region_id = ? AND title LIKE ? AND status IN ('active', 'settling')`, + time.Now().UTC().UnixMilli(), cfg.appCode, activityCode, cfg.regionID, localTitlePrefix+"%", + ) + // 奖励资源组由 wallet-service 拥有;这里仅准备本地验证用的 COIN 资源组配置。 + seedWalletRewardGroups(ctx, walletDB, cfg.appCode) + + conn, err := grpc.DialContext(ctx, cfg.activityAddr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock()) + if err != nil { + log.Fatalf("dial activity-service: %v", err) + } + defer conn.Close() + + adminClient := activityv1.NewAdminWeeklyStarServiceClient(conn) + appClient := activityv1.NewWeeklyStarServiceClient(conn) + roomClient := activityv1.NewRoomEventConsumerServiceClient(conn) + cronClient := activityv1.NewActivityCronServiceClient(conn) + + runID := fmt.Sprintf("%d", time.Now().UTC().UnixMilli()) + now := time.Now().UTC() + // 第一个周期刻意设置为已经结束,事件 occurred_at_ms 落在它的 [start,end) 内,cron 可以立即结算。 + // 第二个周期从第一个周期 end_ms 开始覆盖当前时间,用来验证旧周期结算后 current 自动进入下一周期。 + finishedStart := now.Add(-10 * time.Minute).UnixMilli() + finishedEnd := now.Add(-1 * time.Minute).UnixMilli() + currentStart := finishedEnd + currentEnd := now.Add(50 * time.Minute).UnixMilli() + gifts := []string{"weekly_star_flow_gift_a", "weekly_star_flow_gift_b", "weekly_star_flow_gift_c"} + + // 后台配置两个不重叠周期:第一个已经到期用于结算,第二个覆盖当前时间用于验证自动进入下一周期。 + finishedCycle := createCycle(ctx, adminClient, cfg, fmt.Sprintf("%s finished %s", localTitlePrefix, runID), finishedStart, finishedEnd, gifts) + currentCycle := createCycle(ctx, adminClient, cfg, fmt.Sprintf("%s current %s", localTitlePrefix, runID), currentStart, currentEnd, gifts) + + eventTime := finishedEnd - 10_000 + events := []struct { + userID int64 + giftID string + score int64 + }{ + {userID: 701001, giftID: gifts[0], score: 5_000}, + {userID: 701002, giftID: gifts[1], score: 8_000}, + {userID: 701003, giftID: gifts[2], score: 6_500}, + } + sentEventIDs := make([]string, 0, len(events)+1) + for index, event := range events { + eventID := fmt.Sprintf("weekly-star-flow-%s-%d", runID, index+1) + // consumeGiftEvent 调的是 RoomEventConsumerService,不直接调用 weekly-star service。 + // 这样可以同时验证 activity-service 的房间事件 fanout wiring 是否把周星模块挂上。 + consumeGiftEvent(ctx, roomClient, cfg, eventID, event.userID, event.giftID, event.score, eventTime, int64(index+1)) + sentEventIDs = append(sentEventIDs, eventID) + } + // 同一个 source_event_id 再投一次,验证 weekly_star_score_events 的幂等约束不会让榜单重复加分。 + consumeGiftEvent(ctx, roomClient, cfg, sentEventIDs[0], events[0].userID, events[0].giftID, events[0].score, eventTime, 99) + sentEventIDs = append(sentEventIDs, sentEventIDs[0]+" (duplicate)") + + leaderboard := listLeaderboard(ctx, adminClient, cfg, finishedCycle.GetCycleId()) + // 先查榜再结算,验证积分累计发生在送礼事件消费阶段,而不是结算时临时计算。 + assertLeaderboard(leaderboard, []leaderboardSummary{ + {RankNo: 1, UserID: 701002, Score: 8_000}, + {RankNo: 2, UserID: 701003, Score: 6_500}, + {RankNo: 3, UserID: 701001, Score: 5_000}, + }) + + cronResp, err := cronClient.ProcessWeeklyStarSettlementBatch(ctx, &activityv1.CronBatchRequest{ + Meta: meta(cfg, "weekly-star-local-flow-cron-"+runID), + RunId: "weekly-star-local-flow-" + runID, + WorkerId: "weekly-star-local-flow", + BatchSize: 10, + LockTtlMs: int64((30 * time.Second) / time.Millisecond), + }) + if err != nil { + log.Fatalf("process weekly star settlement: %v", err) + } + if cronResp.GetClaimedCount() != 1 || cronResp.GetProcessedCount() != 3 || cronResp.GetSuccessCount() != 3 || cronResp.GetFailureCount() != 0 { + log.Fatalf("unexpected settlement cron result: claimed=%d processed=%d success=%d failure=%d", cronResp.GetClaimedCount(), cronResp.GetProcessedCount(), cronResp.GetSuccessCount(), cronResp.GetFailureCount()) + } + + settlements := listSettlements(ctx, adminClient, cfg, finishedCycle.GetCycleId()) + assertSettlements(settlements) + // activity 侧 granted 只能说明它收到了 wallet 返回;这里再查 wallet.resource_grants,确认奖励确实落到 wallet owner 库。 + grants := listWalletGrants(ctx, walletDB, cfg.appCode, walletCommandIDs(settlements)) + if len(grants) != 3 { + log.Fatalf("expected 3 wallet grants, got %d", len(grants)) + } + + currentResp, err := appClient.GetWeeklyStarCurrent(ctx, &activityv1.GetWeeklyStarCurrentRequest{ + Meta: meta(cfg, "weekly-star-local-flow-current-"+runID), + UserId: 701001, + RegionId: cfg.regionID, + }) + if err != nil { + log.Fatalf("get current weekly star cycle: %v", err) + } + if currentResp.GetCycle().GetCycleId() != currentCycle.GetCycleId() { + log.Fatalf("expected current cycle %s, got %s", currentCycle.GetCycleId(), currentResp.GetCycle().GetCycleId()) + } + + summary := flowSummary{ + RunID: runID, + RegionID: cfg.regionID, + FinishedCycleID: finishedCycle.GetCycleId(), + CurrentCycleID: currentCycle.GetCycleId(), + SentEvents: sentEventIDs, + Leaderboard: leaderboard, + Cron: cronSummary{ + Claimed: cronResp.GetClaimedCount(), + Processed: cronResp.GetProcessedCount(), + Success: cronResp.GetSuccessCount(), + Failure: cronResp.GetFailureCount(), + }, + Settlements: settlements, + WalletGrants: grants, + CurrentCycleAfter: currentResp.GetCycle().GetCycleId(), + ExpectedAssertions: map[string]string{ + "multiple_cycles": "created one ended active cycle and one current active cycle in UTC epoch ms", + "gift_score": "configured gift score equals RoomGiftSent.coin_spent", + "duplicate_event": "same source_event_id did not double-count leaderboard score", + "settlement": "ended cycle settled top1/top2/top3 through wallet GrantResourceGroup", + "next_cycle": "GetWeeklyStarCurrent returned the second cycle after settlement", + }, + } + encoder := json.NewEncoder(os.Stdout) + encoder.SetIndent("", " ") + if err := encoder.Encode(summary); err != nil { + log.Fatalf("encode summary: %v", err) + } +} + +func mustOpenDB(ctx context.Context, dsn string) *sql.DB { + db, err := sql.Open("mysql", dsn) + if err != nil { + log.Fatalf("open mysql: %v", err) + } + if err := db.PingContext(ctx); err != nil { + _ = db.Close() + log.Fatalf("ping mysql: %v", err) + } + return db +} + +func mustExec(ctx context.Context, db *sql.DB, query string, args ...any) { + if _, err := db.ExecContext(ctx, query, args...); err != nil { + log.Fatalf("exec mysql setup: %v", err) + } +} + +func seedWalletRewardGroups(ctx context.Context, db *sql.DB, appCode string) { + nowMS := time.Now().UTC().UnixMilli() + type groupSeed struct { + groupID int64 + code string + name string + coins int64 + } + seeds := []groupSeed{ + {groupID: rewardGroupTop1ID, code: "weekly_star_local_top1", name: "Weekly Star Local Top 1", coins: 111_000}, + {groupID: rewardGroupTop2ID, code: "weekly_star_local_top2", name: "Weekly Star Local Top 2", coins: 66_000}, + {groupID: rewardGroupTop3ID, code: "weekly_star_local_top3", name: "Weekly Star Local Top 3", coins: 33_000}, + } + for index, seed := range seeds { + // 固定 group_id 让 activity 周期配置可以稳定引用;ON DUPLICATE 只更新本工具自己的本地资源组。 + mustExec(ctx, db, ` + INSERT INTO resource_groups ( + app_code, group_id, group_code, name, status, description, sort_order, + created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms + ) VALUES (?, ?, ?, ?, 'active', 'local weekly star flow reward group', ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + name = VALUES(name), status = 'active', description = VALUES(description), + sort_order = VALUES(sort_order), updated_by_user_id = VALUES(updated_by_user_id), updated_at_ms = VALUES(updated_at_ms)`, + appCode, seed.groupID, seed.code, seed.name, index+1, testOperatorAdmin, testOperatorAdmin, nowMS, nowMS, + ) + mustExec(ctx, db, ` + -- wallet_asset item 不依赖具体 resource_id,wallet-service 会把它原子展开成 COIN 入账和 resource_grant_item。 + INSERT INTO resource_group_items ( + app_code, group_id, item_type, resource_id, wallet_asset_type, wallet_asset_amount, + quantity, duration_ms, sort_order, created_at_ms, updated_at_ms + ) VALUES (?, ?, 'wallet_asset', 0, 'COIN', ?, 1, 0, 1, ?, ?) + ON DUPLICATE KEY UPDATE + wallet_asset_amount = VALUES(wallet_asset_amount), sort_order = VALUES(sort_order), updated_at_ms = VALUES(updated_at_ms)`, + appCode, seed.groupID, seed.coins, nowMS, nowMS, + ) + } +} + +func createCycle(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg flowConfig, title string, startMS int64, endMS int64, gifts []string) *activityv1.WeeklyStarCycle { + resp, err := client.CreateWeeklyStarCycle(ctx, &activityv1.UpsertWeeklyStarCycleRequest{ + Meta: meta(cfg, "weekly-star-local-flow-create-"+strings.ReplaceAll(title, " ", "-")), + Cycle: &activityv1.WeeklyStarCycle{ + ActivityCode: activityCode, + RegionId: cfg.regionID, + Title: title, + Status: cycleStatusActive, + StartMs: startMS, + EndMs: endMS, + Gifts: []*activityv1.WeeklyStarGift{ + {GiftId: gifts[0], SortOrder: 1}, + {GiftId: gifts[1], SortOrder: 2}, + {GiftId: gifts[2], SortOrder: 3}, + }, + Rewards: []*activityv1.WeeklyStarReward{ + {RankNo: 1, ResourceGroupId: rewardGroupTop1ID}, + {RankNo: 2, ResourceGroupId: rewardGroupTop2ID}, + {RankNo: 3, ResourceGroupId: rewardGroupTop3ID}, + }, + }, + OperatorAdminId: testOperatorAdmin, + }) + if err != nil { + log.Fatalf("create cycle %q: %v", title, err) + } + if resp.GetCycle().GetCycleId() == "" { + log.Fatalf("create cycle %q returned empty cycle_id", title) + } + return resp.GetCycle() +} + +func consumeGiftEvent(ctx context.Context, client activityv1.RoomEventConsumerServiceClient, cfg flowConfig, eventID string, userID int64, giftID string, score int64, occurredAtMS int64, version int64) { + body, err := proto.Marshal(&roomeventsv1.RoomGiftSent{ + SenderUserId: userID, + TargetUserId: testTargetAnchorID, + GiftId: giftID, + GiftCount: 1, + GiftValue: 1, + BillingReceiptId: eventID + "-receipt", + VisibleRegionId: cfg.regionID, + CommandId: eventID + "-command", + CoinSpent: score, + }) + if err != nil { + log.Fatalf("marshal room gift sent: %v", err) + } + _, err = client.ConsumeRoomEvent(ctx, &activityv1.ConsumeRoomEventRequest{ + Meta: meta(cfg, "weekly-star-local-flow-event-"+eventID), + Envelope: &roomeventsv1.EventEnvelope{ + EventId: eventID, + RoomId: "weekly-star-local-room", + EventType: "RoomGiftSent", + RoomVersion: version, + OccurredAtMs: occurredAtMS, + Body: body, + AppCode: cfg.appCode, + }, + }) + if err != nil { + log.Fatalf("consume room gift event %s: %v", eventID, err) + } +} + +func listLeaderboard(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg flowConfig, cycleID string) []leaderboardSummary { + resp, err := client.ListWeeklyStarLeaderboard(ctx, &activityv1.ListWeeklyStarLeaderboardRequest{ + Meta: meta(cfg, "weekly-star-local-flow-leaderboard-"+cycleID), + CycleId: cycleID, + RegionId: cfg.regionID, + PageSize: 10, + }) + if err != nil { + log.Fatalf("list leaderboard: %v", err) + } + out := make([]leaderboardSummary, 0, len(resp.GetEntries())) + for _, entry := range resp.GetEntries() { + out = append(out, leaderboardSummary{RankNo: entry.GetRankNo(), UserID: entry.GetUserId(), Score: entry.GetScore()}) + } + return out +} + +func assertLeaderboard(actual []leaderboardSummary, expected []leaderboardSummary) { + if len(actual) < len(expected) { + log.Fatalf("expected at least %d leaderboard entries, got %d", len(expected), len(actual)) + } + for index, want := range expected { + got := actual[index] + if got != want { + log.Fatalf("leaderboard row %d mismatch: got %+v want %+v", index+1, got, want) + } + } +} + +func listSettlements(ctx context.Context, client activityv1.AdminWeeklyStarServiceClient, cfg flowConfig, cycleID string) []settlementSummary { + resp, err := client.ListWeeklyStarSettlements(ctx, &activityv1.ListWeeklyStarSettlementsRequest{ + Meta: meta(cfg, "weekly-star-local-flow-settlements-"+cycleID), + CycleId: cycleID, + }) + if err != nil { + log.Fatalf("list settlements: %v", err) + } + out := make([]settlementSummary, 0, len(resp.GetSettlements())) + for _, settlement := range resp.GetSettlements() { + out = append(out, settlementSummary{ + RankNo: settlement.GetRankNo(), + UserID: settlement.GetUserId(), + Score: settlement.GetScore(), + ResourceGroupID: settlement.GetResourceGroupId(), + WalletCommandID: settlement.GetWalletCommandId(), + WalletGrantID: settlement.GetWalletGrantId(), + Status: settlement.GetStatus(), + }) + } + sort.Slice(out, func(i, j int) bool { return out[i].RankNo < out[j].RankNo }) + return out +} + +func assertSettlements(items []settlementSummary) { + if len(items) != 3 { + log.Fatalf("expected 3 settlements, got %d", len(items)) + } + for _, item := range items { + if item.Status != "granted" || item.WalletCommandID == "" || item.WalletGrantID == "" { + log.Fatalf("settlement was not granted: %+v", item) + } + } +} + +func walletCommandIDs(items []settlementSummary) []string { + ids := make([]string, 0, len(items)) + for _, item := range items { + ids = append(ids, item.WalletCommandID) + } + return ids +} + +func listWalletGrants(ctx context.Context, db *sql.DB, appCode string, commandIDs []string) []walletGrantSummary { + if len(commandIDs) == 0 { + return nil + } + placeholders := strings.TrimRight(strings.Repeat("?,", len(commandIDs)), ",") + args := make([]any, 0, len(commandIDs)+1) + args = append(args, appCode) + for _, id := range commandIDs { + args = append(args, id) + } + rows, err := db.QueryContext(ctx, ` + SELECT command_id, grant_id, target_user_id, grant_subject_id, status + FROM resource_grants + WHERE app_code = ? AND command_id IN (`+placeholders+`) + ORDER BY target_user_id ASC`, args...) + if err != nil { + log.Fatalf("query wallet grants: %v", err) + } + defer rows.Close() + out := make([]walletGrantSummary, 0, len(commandIDs)) + for rows.Next() { + var item walletGrantSummary + if err := rows.Scan(&item.CommandID, &item.GrantID, &item.TargetUserID, &item.GrantSubjectID, &item.Status); err != nil { + log.Fatalf("scan wallet grant: %v", err) + } + out = append(out, item) + } + if err := rows.Err(); err != nil { + log.Fatalf("iterate wallet grants: %v", err) + } + return out +} + +func meta(cfg flowConfig, requestID string) *activityv1.RequestMeta { + return &activityv1.RequestMeta{ + RequestId: requestID, + Caller: "weekly-star-local-flow", + SentAtMs: time.Now().UTC().UnixMilli(), + AppCode: cfg.appCode, + } +} From 44e38ab9bbc07b8c2d84dc10dc48bf4769ce30e1 Mon Sep 17 00:00:00 2001 From: zhx Date: Sun, 7 Jun 2026 14:50:19 +0800 Subject: [PATCH 25/28] Update game adapter defaults and statistics overview --- server/admin/internal/modules/payment/dto.go | 11 +- .../admin/internal/modules/payment/handler.go | 22 +- .../deploy/mysql/initdb/001_game_service.sql | 2 +- .../internal/storage/mysql/repository.go | 10 +- .../internal/transport/grpc/server.go | 4 +- .../internal/transport/grpc/server_test.go | 32 +++ .../internal/storage/mysql/query.go | 240 ++++++++++++------ .../internal/storage/mysql/query_test.go | 43 ++++ 8 files changed, 273 insertions(+), 91 deletions(-) diff --git a/server/admin/internal/modules/payment/dto.go b/server/admin/internal/modules/payment/dto.go index feb29e78..dd2a210f 100644 --- a/server/admin/internal/modules/payment/dto.go +++ b/server/admin/internal/modules/payment/dto.go @@ -32,10 +32,13 @@ type rechargeBillDTO struct { } type rechargeBillUserDTO struct { - UserID string `json:"userId"` - DisplayUserID string `json:"displayUserId"` - Username string `json:"username"` - Avatar string `json:"avatar"` + UserID string `json:"userId"` + DisplayUserID string `json:"displayUserId"` + Username string `json:"username"` + Avatar string `json:"avatar"` + CountryCode string `json:"countryCode"` + CountryName string `json:"countryName"` + CountryDisplayName string `json:"countryDisplayName"` } type rechargeProductDTO struct { diff --git a/server/admin/internal/modules/payment/handler.go b/server/admin/internal/modules/payment/handler.go index f09bbf92..40c61514 100644 --- a/server/admin/internal/modules/payment/handler.go +++ b/server/admin/internal/modules/payment/handler.go @@ -84,16 +84,18 @@ func (h *Handler) fillRechargeBillUsers(ctx context.Context, appCode string, ite return nil } -// loadRechargeBillUsers 按 app_code 和用户 ID 批量读取展示资料,返回 map 便于用户列和币商列复用同一次查询结果。 +// loadRechargeBillUsers 按 app_code 和用户 ID 批量读取展示资料;国家只服务后台账单展示,账单金额和区域事实仍以 wallet-service 为准。 func (h *Handler) loadRechargeBillUsers(ctx context.Context, appCode string, userIDs []int64) (map[int64]rechargeBillUserDTO, error) { if h == nil || h.userDB == nil { return nil, errors.New("user mysql is not configured") } - // 本查询只读取 users 表里的展示字段,按照 app_code 和 user_id 精确命中;区域和账单筛选仍以 wallet-service 返回为准。 + // 本查询只读取 users/countries 表里的展示字段,按照 app_code 和 user_id 精确命中;区域和账单筛选仍以 wallet-service 返回为准。 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(userIDs))+`)`, + SELECT u.user_id, COALESCE(u.current_display_user_id, ''), COALESCE(u.username, ''), COALESCE(u.avatar, ''), + COALESCE(u.country, ''), COALESCE(c.country_name, ''), COALESCE(c.country_display_name, '') + FROM users u + LEFT JOIN countries c ON c.app_code = u.app_code AND c.country_code = u.country + WHERE u.app_code = ? AND u.user_id IN (`+placeholders(len(userIDs))+`)`, append([]any{appCode}, int64Args(userIDs)...)..., ) if err != nil { @@ -105,7 +107,15 @@ func (h *Handler) loadRechargeBillUsers(ctx context.Context, appCode string, use for rows.Next() { var profile rechargeBillUserDTO var userID int64 - if err := rows.Scan(&userID, &profile.DisplayUserID, &profile.Username, &profile.Avatar); err != nil { + if err := rows.Scan( + &userID, + &profile.DisplayUserID, + &profile.Username, + &profile.Avatar, + &profile.CountryCode, + &profile.CountryName, + &profile.CountryDisplayName, + ); err != nil { return nil, err } profile.UserID = strconv.FormatInt(userID, 10) diff --git a/services/game-service/deploy/mysql/initdb/001_game_service.sql b/services/game-service/deploy/mysql/initdb/001_game_service.sql index 39976f52..7a1c4595 100644 --- a/services/game-service/deploy/mysql/initdb/001_game_service.sql +++ b/services/game-service/deploy/mysql/initdb/001_game_service.sql @@ -12,7 +12,7 @@ CREATE TABLE IF NOT EXISTS game_platforms ( platform_name VARCHAR(128) NOT NULL COMMENT '平台名称', status VARCHAR(32) NOT NULL COMMENT '业务状态', api_base_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'API 基准 URL', - adapter_type VARCHAR(64) NOT NULL DEFAULT 'demo' COMMENT '适配器类型', + adapter_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT '适配器类型', callback_secret_ciphertext VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '回调密钥密文', callback_ip_whitelist JSON NULL COMMENT '回调IP白名单', adapter_config JSON NULL COMMENT '适配器配置', diff --git a/services/game-service/internal/storage/mysql/repository.go b/services/game-service/internal/storage/mysql/repository.go index b62cddba..5a5092fa 100644 --- a/services/game-service/internal/storage/mysql/repository.go +++ b/services/game-service/internal/storage/mysql/repository.go @@ -66,7 +66,7 @@ func (r *Repository) Migrate(ctx context.Context) error { platform_name VARCHAR(128) NOT NULL, status VARCHAR(32) NOT NULL, api_base_url VARCHAR(512) NOT NULL DEFAULT '', - adapter_type VARCHAR(64) NOT NULL DEFAULT 'demo', + adapter_type VARCHAR(64) NOT NULL DEFAULT '', callback_secret_ciphertext VARCHAR(1024) NOT NULL DEFAULT '', callback_ip_whitelist JSON NULL, adapter_config JSON NULL, @@ -251,7 +251,7 @@ func (r *Repository) Migrate(ctx context.Context) error { return err } } - if err := r.ensureColumn(ctx, "game_platforms", "adapter_type", "adapter_type VARCHAR(64) NOT NULL DEFAULT 'demo' AFTER api_base_url"); err != nil { + if err := r.ensureColumn(ctx, "game_platforms", "adapter_type", "adapter_type VARCHAR(64) NOT NULL DEFAULT '' AFTER api_base_url"); err != nil { return err } if err := r.ensureColumn(ctx, "game_catalog", "safe_height", "safe_height INT NOT NULL DEFAULT 0 AFTER orientation"); err != nil { @@ -410,7 +410,7 @@ func (r *Repository) GetLaunchableGame(ctx context.Context, appCode string, game `SELECT c.app_code, c.game_id, c.platform_code, c.provider_game_id, c.game_name, c.category, c.icon_url, c.cover_url, c.launch_mode, c.orientation, c.safe_height, c.min_coin, c.status, c.sort_order, COALESCE(CAST(c.tags AS CHAR), '[]'), c.created_at_ms, c.updated_at_ms, - p.platform_name, p.status, p.api_base_url, COALESCE(p.adapter_type, 'demo'), + p.platform_name, p.status, p.api_base_url, COALESCE(p.adapter_type, ''), p.callback_secret_ciphertext, COALESCE(CAST(p.callback_ip_whitelist AS CHAR), '[]'), COALESCE(CAST(p.adapter_config AS CHAR), '{}') FROM game_catalog c @@ -435,7 +435,7 @@ func (r *Repository) GetLaunchableGame(ctx context.Context, appCode string, game func (r *Repository) GetPlatform(ctx context.Context, appCode string, platformCode string) (gamedomain.Platform, error) { // 回调入口只知道 platform_code,必须按 app_code 隔离查询,防止多租户平台编码冲突。 row := r.db.QueryRowContext(ctx, - `SELECT app_code, platform_code, platform_name, status, api_base_url, COALESCE(adapter_type, 'demo'), + `SELECT app_code, platform_code, platform_name, status, api_base_url, COALESCE(adapter_type, ''), callback_secret_ciphertext, COALESCE(CAST(callback_ip_whitelist AS CHAR), '[]'), COALESCE(CAST(adapter_config AS CHAR), '{}'), sort_order, created_at_ms, updated_at_ms FROM game_platforms @@ -1088,7 +1088,7 @@ func (r *Repository) MarkLevelEventFailed(ctx context.Context, eventID string, f } func (r *Repository) ListPlatforms(ctx context.Context, appCode string, status string) ([]gamedomain.Platform, error) { - query := `SELECT app_code, platform_code, platform_name, status, api_base_url, COALESCE(adapter_type, 'demo'), + query := `SELECT app_code, platform_code, platform_name, status, api_base_url, COALESCE(adapter_type, ''), callback_secret_ciphertext, COALESCE(CAST(callback_ip_whitelist AS CHAR), '[]'), COALESCE(CAST(adapter_config AS CHAR), '{}'), sort_order, created_at_ms, updated_at_ms FROM game_platforms WHERE app_code = ?` diff --git a/services/game-service/internal/transport/grpc/server.go b/services/game-service/internal/transport/grpc/server.go index 60fa90db..93098cfb 100644 --- a/services/game-service/internal/transport/grpc/server.go +++ b/services/game-service/internal/transport/grpc/server.go @@ -412,8 +412,6 @@ func normalizeStatus(status string) string { func normalizeAdapterType(adapterType string) string { // 允许的 adapter 必须在这里登记,后台传错值时直接拒绝,避免落库后回调走错协议。 switch strings.ToLower(strings.TrimSpace(adapterType)) { - case "", gamedomain.AdapterDemo: - return gamedomain.AdapterDemo case gamedomain.AdapterYomiV4: return gamedomain.AdapterYomiV4 case gamedomain.AdapterLeaderCCV1: @@ -422,6 +420,8 @@ func normalizeAdapterType(adapterType string) string { return gamedomain.AdapterZeeOneV1 case gamedomain.AdapterBaishunV1: return gamedomain.AdapterBaishunV1 + case gamedomain.AdapterVivaGamesV1: + return gamedomain.AdapterVivaGamesV1 default: return "" } diff --git a/services/game-service/internal/transport/grpc/server_test.go b/services/game-service/internal/transport/grpc/server_test.go index 770bffdf..0d4ca170 100644 --- a/services/game-service/internal/transport/grpc/server_test.go +++ b/services/game-service/internal/transport/grpc/server_test.go @@ -22,3 +22,35 @@ func TestPlatformToProtoExposesCallbackSecretForAdmin(t *testing.T) { t.Fatal("callback_secret_set = false, want true") } } + +func TestNormalizePlatformAcceptsVivaGamesAdapter(t *testing.T) { + // 平台创建入口会先规范化 adapter_type;新增厂商必须在这里放行,否则后台配置页会被 gRPC 直接拒绝。 + got, err := normalizePlatform(gamedomain.Platform{ + PlatformCode: "vivagames", + PlatformName: "VIVAGAMES", + Status: gamedomain.StatusActive, + AdapterType: gamedomain.AdapterVivaGamesV1, + AdapterConfigJSON: "{}", + }) + if err != nil { + t.Fatalf("normalizePlatform() error = %v", err) + } + if got.AdapterType != gamedomain.AdapterVivaGamesV1 { + t.Fatalf("adapter_type = %q, want %q", got.AdapterType, gamedomain.AdapterVivaGamesV1) + } +} + +func TestNormalizePlatformRejectsDemoAdapter(t *testing.T) { + for _, adapterType := range []string{"", gamedomain.AdapterDemo} { + _, err := normalizePlatform(gamedomain.Platform{ + PlatformCode: "demo", + PlatformName: "Demo", + Status: gamedomain.StatusActive, + AdapterType: adapterType, + AdapterConfigJSON: "{}", + }) + if err == nil { + t.Fatalf("normalizePlatform(adapterType=%q) expected error", adapterType) + } + } +} diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index 999e080d..4c4fb228 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -3,6 +3,7 @@ package mysql import ( "context" "database/sql" + "math" "time" "hyapp/pkg/appcode" @@ -16,38 +17,51 @@ type OverviewQuery struct { } type Overview struct { - AppCode string `json:"app_code"` - StartMS int64 `json:"start_ms"` - EndMS int64 `json:"end_ms"` - CountryID int64 `json:"country_id"` - NewUsers int64 `json:"new_users"` - ActiveUsers int64 `json:"active_users"` - PaidUsers int64 `json:"paid_users"` - RechargeUSDMinor int64 `json:"recharge_usd_minor"` - NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` - CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` - MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` - GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` - CoinSellerTransferCoin int64 `json:"coin_seller_transfer_coin"` - GiftCoinSpent int64 `json:"gift_coin_spent"` - LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` - LuckyGiftPayout int64 `json:"lucky_gift_payout"` - LuckyGiftPayers int64 `json:"lucky_gift_payers"` - LuckyGiftProfit int64 `json:"lucky_gift_profit"` - LuckyGiftPayoutRate float64 `json:"lucky_gift_payout_rate"` - LuckyGiftProfitRate float64 `json:"lucky_gift_profit_rate"` - GameTurnover int64 `json:"game_turnover"` - GamePayout int64 `json:"game_payout"` - GameRefund int64 `json:"game_refund"` - GamePlayers int64 `json:"game_players"` - GameProfit int64 `json:"game_profit"` - GameProfitRate float64 `json:"game_profit_rate"` - ARPUUSDMinor int64 `json:"arpu_usd_minor"` - ARPPUUSDMinor int64 `json:"arppu_usd_minor"` - UPValueUSDMinor int64 `json:"up_value_usd_minor"` - Retention Retention `json:"retention"` - GameRanking []GameRank `json:"game_ranking"` - LuckyGiftPools []LuckyGiftPoolStat `json:"lucky_gift_pools"` + AppCode string `json:"app_code"` + StartMS int64 `json:"start_ms"` + EndMS int64 `json:"end_ms"` + CountryID int64 `json:"country_id"` + NewUsers int64 `json:"new_users"` + ActiveUsers int64 `json:"active_users"` + PaidUsers int64 `json:"paid_users"` + RechargeUSDMinor int64 `json:"recharge_usd_minor"` + NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` + CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` + MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` + GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` + CoinSellerTransferCoin int64 `json:"coin_seller_transfer_coin"` + GiftCoinSpent int64 `json:"gift_coin_spent"` + LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` + LuckyGiftPayout int64 `json:"lucky_gift_payout"` + LuckyGiftPayers int64 `json:"lucky_gift_payers"` + LuckyGiftProfit int64 `json:"lucky_gift_profit"` + LuckyGiftPayoutRate float64 `json:"lucky_gift_payout_rate"` + LuckyGiftProfitRate float64 `json:"lucky_gift_profit_rate"` + GameTurnover int64 `json:"game_turnover"` + GamePayout int64 `json:"game_payout"` + GameRefund int64 `json:"game_refund"` + GamePlayers int64 `json:"game_players"` + GameProfit int64 `json:"game_profit"` + GameProfitRate float64 `json:"game_profit_rate"` + ARPUUSDMinor int64 `json:"arpu_usd_minor"` + ARPPUUSDMinor int64 `json:"arppu_usd_minor"` + UPValueUSDMinor int64 `json:"up_value_usd_minor"` + RechargeDeltaRate float64 `json:"recharge_delta_rate"` + NewUserRechargeDeltaRate float64 `json:"new_user_recharge_delta_rate"` + ActiveUsersDeltaRate float64 `json:"active_users_delta_rate"` + PaidUsersDeltaRate float64 `json:"paid_users_delta_rate"` + ARPUDeltaRate float64 `json:"arpu_delta_rate"` + ARPPUDeltaRate float64 `json:"arppu_delta_rate"` + GiftCoinSpentDeltaRate float64 `json:"gift_coin_spent_delta_rate"` + CoinSellerTransferDeltaRate float64 `json:"coin_seller_transfer_coin_delta_rate"` + LuckyGiftTurnoverDeltaRate float64 `json:"lucky_gift_turnover_delta_rate"` + LuckyGiftPayoutDeltaRate float64 `json:"lucky_gift_payout_delta_rate"` + LuckyGiftProfitDeltaRate float64 `json:"lucky_gift_profit_delta_rate"` + GameTurnoverDeltaRate float64 `json:"game_turnover_delta_rate"` + GameProfitDeltaRate float64 `json:"game_profit_delta_rate"` + Retention Retention `json:"retention"` + GameRanking []GameRank `json:"game_ranking"` + LuckyGiftPools []LuckyGiftPoolStat `json:"lucky_gift_pools"` } type Retention struct { @@ -87,48 +101,17 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov } startDay := statDay(query.StartMS) endDay := statDay(query.EndMS - 1) - args := []any{app, startDay, endDay} - countryFilter := "" - if query.CountryID > 0 { - countryFilter = " AND country_id = ?" - args = append(args, query.CountryID) + previousStartDay, previousEndDay := previousStatDayRange(startDay, endDay) + overview, err := r.queryAppDayOverviewTotals(ctx, app, startDay, endDay, query.CountryID) + if err != nil { + return Overview{}, err + } + previous, err := r.queryAppDayOverviewTotals(ctx, app, previousStartDay, previousEndDay, query.CountryID) + if err != nil { + return Overview{}, err } - row := r.db.QueryRowContext(ctx, ` - SELECT COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), - COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), - COALESCE(SUM(coin_seller_recharge_usd_minor),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), - COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), - COALESCE(SUM(gift_coin_spent),0), - COALESCE(SUM(lucky_gift_turnover),0), COALESCE(SUM(lucky_gift_payout),0), COALESCE(SUM(lucky_gift_payers),0), - COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0), - COALESCE(SUM(game_players),0) - FROM stat_app_day_country - WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+countryFilter, args...) - var overview Overview overview.AppCode, overview.StartMS, overview.EndMS, overview.CountryID = app, query.StartMS, query.EndMS, query.CountryID - if err := row.Scan(&overview.NewUsers, &overview.ActiveUsers, &overview.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { - return Overview{}, err - } - // 历史聚合行可能只写了真实 USD 渠道列、没有同步修正 recharge_usd_minor;查询时用渠道合计兜底,但币商转普通金币只展示金币卡片,不进入用户 USDT 充值。 - channelRechargeUSDMinor := overview.MifaPayRechargeUSDMinor + overview.GoogleRechargeUSDMinor - if channelRechargeUSDMinor > overview.RechargeUSDMinor { - overview.RechargeUSDMinor = channelRechargeUSDMinor - } - overview.GameProfit = overview.GameTurnover - overview.GamePayout - overview.GameRefund - overview.GameProfitRate = ratio(overview.GameProfit, overview.GameTurnover) - overview.ARPUUSDMinor = div(overview.RechargeUSDMinor, overview.ActiveUsers) - overview.ARPPUUSDMinor = div(overview.RechargeUSDMinor, overview.PaidUsers) - overview.UPValueUSDMinor = overview.ARPPUUSDMinor - retention, err := r.queryRetention(ctx, app, startDay, endDay, query.CountryID) - if err != nil { - return Overview{}, err - } - overview.Retention = retention - ranking, err := r.queryGameRanking(ctx, app, startDay, endDay, query.CountryID) - if err != nil { - return Overview{}, err - } - overview.GameRanking = ranking + previous.AppCode, previous.CountryID = app, query.CountryID // Pool 明细和顶部汇总来自同一个统计窗口;Databi 用它来下钻展示每个 pool_id 的流水、返奖和利润。 pools, err := r.queryLuckyGiftPools(ctx, app, startDay, endDay, query.CountryID) if err != nil { @@ -142,10 +125,89 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov overview.LuckyGiftPools = activityPools overview.LuckyGiftTurnover, overview.LuckyGiftPayout = sumLuckyGiftPools(activityPools) } + // 上一周期也使用相同的日聚合口径,保证“与昨日相比/前周期相比”不额外查询明细表。 + if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, previousStartDay, previousEndDay, query.CountryID); err != nil { + return Overview{}, err + } else if ok { + previous.LuckyGiftTurnover, previous.LuckyGiftPayout = sumLuckyGiftPools(activityPools) + } + applyOverviewDerivedMetrics(&overview) + applyOverviewDerivedMetrics(&previous) + overview.applyDeltaRates(previous) + retention, err := r.queryRetention(ctx, app, startDay, endDay, query.CountryID) + if err != nil { + return Overview{}, err + } + overview.Retention = retention + ranking, err := r.queryGameRanking(ctx, app, startDay, endDay, query.CountryID) + if err != nil { + return Overview{}, err + } + overview.GameRanking = ranking + return overview, nil +} + +func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDay, endDay string, countryID int64) (Overview, error) { + args := []any{app, startDay, endDay} + countryFilter := "" + if countryID > 0 { + countryFilter = " AND country_id = ?" + args = append(args, countryID) + } + row := r.db.QueryRowContext(ctx, ` + SELECT COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), + COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), + COALESCE(SUM(coin_seller_recharge_usd_minor),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), + COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), + COALESCE(SUM(gift_coin_spent),0), + COALESCE(SUM(lucky_gift_turnover),0), COALESCE(SUM(lucky_gift_payout),0), COALESCE(SUM(lucky_gift_payers),0), + COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0), + COALESCE(SUM(game_players),0) + FROM stat_app_day_country + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+countryFilter, args...) + var overview Overview + if err := row.Scan(&overview.NewUsers, &overview.ActiveUsers, &overview.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { + return Overview{}, err + } + return overview, nil +} + +func applyOverviewDerivedMetrics(overview *Overview) { + if overview == nil { + return + } + // 历史聚合行可能只写了真实 USD 渠道列、没有同步修正 recharge_usd_minor;查询时用渠道合计兜底,但币商转普通金币只展示金币卡片,不进入用户 USDT 充值。 + channelRechargeUSDMinor := overview.MifaPayRechargeUSDMinor + overview.GoogleRechargeUSDMinor + if channelRechargeUSDMinor > overview.RechargeUSDMinor { + overview.RechargeUSDMinor = channelRechargeUSDMinor + } + overview.GameProfit = overview.GameTurnover - overview.GamePayout - overview.GameRefund + overview.GameProfitRate = ratio(overview.GameProfit, overview.GameTurnover) + overview.ARPUUSDMinor = div(overview.RechargeUSDMinor, overview.ActiveUsers) + overview.ARPPUUSDMinor = div(overview.RechargeUSDMinor, overview.PaidUsers) + overview.UPValueUSDMinor = overview.ARPPUUSDMinor overview.LuckyGiftProfit = overview.LuckyGiftTurnover - overview.LuckyGiftPayout overview.LuckyGiftPayoutRate = ratio(overview.LuckyGiftPayout, overview.LuckyGiftTurnover) overview.LuckyGiftProfitRate = ratio(overview.LuckyGiftProfit, overview.LuckyGiftTurnover) - return overview, nil +} + +func (overview *Overview) applyDeltaRates(previous Overview) { + if overview == nil { + return + } + overview.RechargeDeltaRate = deltaRate(overview.RechargeUSDMinor, previous.RechargeUSDMinor) + overview.NewUserRechargeDeltaRate = deltaRate(overview.NewUserRechargeUSDMinor, previous.NewUserRechargeUSDMinor) + overview.ActiveUsersDeltaRate = deltaRate(overview.ActiveUsers, previous.ActiveUsers) + overview.PaidUsersDeltaRate = deltaRate(overview.PaidUsers, previous.PaidUsers) + overview.ARPUDeltaRate = deltaRate(overview.ARPUUSDMinor, previous.ARPUUSDMinor) + overview.ARPPUDeltaRate = deltaRate(overview.ARPPUUSDMinor, previous.ARPPUUSDMinor) + overview.GiftCoinSpentDeltaRate = deltaRate(overview.GiftCoinSpent, previous.GiftCoinSpent) + overview.CoinSellerTransferDeltaRate = deltaRate(overview.CoinSellerTransferCoin, previous.CoinSellerTransferCoin) + overview.LuckyGiftTurnoverDeltaRate = deltaRate(overview.LuckyGiftTurnover, previous.LuckyGiftTurnover) + overview.LuckyGiftPayoutDeltaRate = deltaRate(overview.LuckyGiftPayout, previous.LuckyGiftPayout) + overview.LuckyGiftProfitDeltaRate = deltaRate(overview.LuckyGiftProfit, previous.LuckyGiftProfit) + overview.GameTurnoverDeltaRate = deltaRate(overview.GameTurnover, previous.GameTurnover) + overview.GameProfitDeltaRate = deltaRate(overview.GameProfit, previous.GameProfit) } func (r *Repository) queryRetention(ctx context.Context, app, startDay, endDay string, countryID int64) (Retention, error) { @@ -295,6 +357,25 @@ func normalizeRange(startMS, endMS int64) (int64, int64) { return startMS, endMS } +func previousStatDayRange(startDay, endDay string) (string, string) { + start, err := time.Parse("2006-01-02", startDay) + if err != nil { + start = time.Now().UTC() + } + end, err := time.Parse("2006-01-02", endDay) + if err != nil || end.Before(start) { + end = start + } + // Databi 的日期窗口按 UTC stat_day 聚合;上一周期采用同样天数,今日就是昨天,近 7 日就是前 7 日。 + dayCount := int(end.Sub(start)/(24*time.Hour)) + 1 + if dayCount < 1 { + dayCount = 1 + } + previousEnd := start.AddDate(0, 0, -1) + previousStart := start.AddDate(0, 0, -dayCount) + return previousStart.Format("2006-01-02"), previousEnd.Format("2006-01-02") +} + func div(numerator, denominator int64) int64 { if denominator <= 0 { return 0 @@ -302,6 +383,19 @@ func div(numerator, denominator int64) int64 { return numerator / denominator } +func deltaRate(current, previous int64) float64 { + if previous == 0 { + if current == 0 { + return 0 + } + if current > 0 { + return 1 + } + return -1 + } + return float64(current-previous) / math.Abs(float64(previous)) +} + func ratio(numerator, denominator int64) float64 { if denominator <= 0 { return 0 diff --git a/services/statistics-service/internal/storage/mysql/query_test.go b/services/statistics-service/internal/storage/mysql/query_test.go index b0dab2a9..c84e4e7f 100644 --- a/services/statistics-service/internal/storage/mysql/query_test.go +++ b/services/statistics-service/internal/storage/mysql/query_test.go @@ -64,3 +64,46 @@ func TestQueryOverviewUsesActivityLuckyGiftDayStats(t *testing.T) { t.Fatalf("super_lucky pool mismatch: %+v", overview.LuckyGiftPools[0]) } } + +func TestQueryOverviewReturnsPreviousPeriodDeltaRates(t *testing.T) { + ctx := context.Background() + _, file, _, _ := runtime.Caller(0) + statsSchema := mysqlschema.New(t, mysqlschema.Config{ + InitDBPath: mysqlschema.InitDBPath(t, file, "..", "..", "..", "deploy", "mysql", "initdb", "001_statistics_service.sql"), + DatabasePrefix: "hy_stats_query_delta_test", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO stat_app_day_country ( + app_code, stat_day, country_id, active_users, paid_users, recharge_usd_minor, new_user_recharge_usd_minor, + mifapay_recharge_usd_minor, gift_coin_spent, coin_seller_transfer_coin, lucky_gift_turnover, lucky_gift_payout, + game_turnover, game_payout, game_refund, updated_at_ms + ) VALUES + ('lalu', '2026-06-05', 210, 10, 2, 100, 50, 100, 300, 80, 100, 50, 500, 100, 50, 1), + ('lalu', '2026-06-06', 210, 20, 5, 200, 100, 200, 600, 200, 400, 100, 1000, 400, 100, 1)`); err != nil { + t.Fatalf("seed delta statistics: %v", err) + } + + start := time.Date(2026, 6, 6, 0, 0, 0, 0, time.UTC).UnixMilli() + overview, err := repository.QueryOverview(ctx, OverviewQuery{AppCode: "lalu", StartMS: start, EndMS: start + int64(24*time.Hour/time.Millisecond), CountryID: 210}) + if err != nil { + t.Fatalf("query overview: %v", err) + } + if overview.RechargeDeltaRate != 1 || overview.NewUserRechargeDeltaRate != 1 || overview.ActiveUsersDeltaRate != 1 { + t.Fatalf("top delta rates mismatch: %+v", overview) + } + if overview.PaidUsersDeltaRate != 1.5 || overview.ARPUDeltaRate != 0 || overview.ARPPUDeltaRate != -0.2 { + t.Fatalf("user delta rates mismatch: %+v", overview) + } + if overview.GiftCoinSpentDeltaRate != 1 || overview.CoinSellerTransferDeltaRate != 1.5 || overview.LuckyGiftTurnoverDeltaRate != 3 || overview.LuckyGiftPayoutDeltaRate != 1 || overview.LuckyGiftProfitDeltaRate != 5 { + t.Fatalf("coin delta rates mismatch: %+v", overview) + } + if overview.GameTurnoverDeltaRate != 1 || overview.GameProfitDeltaRate < 0.428 || overview.GameProfitDeltaRate > 0.429 { + t.Fatalf("game delta rates mismatch: %+v", overview) + } +} From 1b6c77c6dca1ea2fb2a1391ba992a21265c3d049 Mon Sep 17 00:00:00 2001 From: zhx Date: Mon, 8 Jun 2026 00:55:30 +0800 Subject: [PATCH 26/28] Add regional statistics breakdown --- .../internal/modules/dashboard/handler.go | 11 +- .../internal/modules/dashboard/service.go | 20 +- .../mysql/initdb/001_statistics_service.sql | 36 +- .../statistics-service/internal/app/app.go | 65 ++- .../internal/app/local_flow_test.go | 53 ++- .../internal/app/query_http.go | 11 +- .../internal/storage/mysql/query.go | 401 +++++++++++++++++- .../internal/storage/mysql/query_test.go | 40 ++ .../internal/storage/mysql/repository.go | 207 ++++++--- .../internal/storage/mysql/user/repository.go | 1 + 10 files changed, 723 insertions(+), 122 deletions(-) diff --git a/server/admin/internal/modules/dashboard/handler.go b/server/admin/internal/modules/dashboard/handler.go index def86ae8..f4ca4b40 100644 --- a/server/admin/internal/modules/dashboard/handler.go +++ b/server/admin/internal/modules/dashboard/handler.go @@ -28,10 +28,13 @@ func (h *Handler) DashboardOverview(c *gin.Context) { func (h *Handler) StatisticsOverview(c *gin.Context) { overview, err := h.service.StatisticsOverview(c.Request.Context(), StatisticsQuery{ - AppCode: c.DefaultQuery("app_code", "lalu"), - StartMS: parseInt64(c.Query("start_ms")), - EndMS: parseInt64(c.Query("end_ms")), - CountryID: parseInt64(c.Query("country_id")), + AppCode: c.DefaultQuery("app_code", "lalu"), + StartMS: parseInt64(c.Query("start_ms")), + EndMS: parseInt64(c.Query("end_ms")), + SeriesStartMS: parseInt64(c.Query("series_start_ms")), + SeriesEndMS: parseInt64(c.Query("series_end_ms")), + RegionID: parseInt64(c.Query("region_id")), + CountryID: parseInt64(c.Query("country_id")), }) if err != nil { response.ServerError(c, "获取统计总览失败") diff --git a/server/admin/internal/modules/dashboard/service.go b/server/admin/internal/modules/dashboard/service.go index 6f70dbe5..704118c6 100644 --- a/server/admin/internal/modules/dashboard/service.go +++ b/server/admin/internal/modules/dashboard/service.go @@ -19,10 +19,13 @@ type DashboardService struct { } type StatisticsQuery struct { - AppCode string - StartMS int64 - EndMS int64 - CountryID int64 + AppCode string + StartMS int64 + EndMS int64 + SeriesStartMS int64 + SeriesEndMS int64 + RegionID int64 + CountryID int64 } func NewService(store *repository.Store, cfg config.Config) *DashboardService { @@ -47,6 +50,15 @@ func (s *DashboardService) StatisticsOverview(ctx context.Context, query Statist if query.EndMS > 0 { values.Set("end_ms", strconv.FormatInt(query.EndMS, 10)) } + if query.SeriesStartMS > 0 { + values.Set("series_start_ms", strconv.FormatInt(query.SeriesStartMS, 10)) + } + if query.SeriesEndMS > 0 { + values.Set("series_end_ms", strconv.FormatInt(query.SeriesEndMS, 10)) + } + if query.RegionID > 0 { + values.Set("region_id", strconv.FormatInt(query.RegionID, 10)) + } if query.CountryID > 0 { values.Set("country_id", strconv.FormatInt(query.CountryID, 10)) } diff --git a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql index f7375e78..f8a1ac2c 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -20,7 +20,8 @@ CREATE TABLE IF NOT EXISTS statistics_event_consumption ( CREATE TABLE IF NOT EXISTS stat_app_day_country ( app_code VARCHAR(32) NOT NULL COMMENT '应用编码', stat_day DATE NOT NULL COMMENT 'UTC 统计日', - country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家或区域维度 ID,0 表示未知或全局', + country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家维度 ID,0 表示未知或全局', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域维度 ID,0 表示未知或全局', new_users BIGINT NOT NULL DEFAULT 0 COMMENT '新增用户数', active_users BIGINT NOT NULL DEFAULT 0 COMMENT '当日活跃去重用户数', paid_users BIGINT NOT NULL DEFAULT 0 COMMENT '当日充值去重用户数', @@ -39,17 +40,20 @@ CREATE TABLE IF NOT EXISTS stat_app_day_country ( game_payout BIGINT NOT NULL DEFAULT 0 COMMENT '游戏返奖', game_refund BIGINT NOT NULL DEFAULT 0 COMMENT '游戏退款', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', - PRIMARY KEY (app_code, stat_day, country_id) + PRIMARY KEY (app_code, stat_day, country_id), + KEY idx_stat_app_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='App 国家日统计聚合表'; CREATE TABLE IF NOT EXISTS stat_user_day_activity ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_active_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, user_id), - KEY idx_stat_user_day_country (app_code, stat_day, country_id) + KEY idx_stat_user_day_country (app_code, stat_day, country_id), + KEY idx_stat_user_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户日活跃去重表'; CREATE TABLE IF NOT EXISTS stat_user_registration ( @@ -57,47 +61,56 @@ CREATE TABLE IF NOT EXISTS stat_user_registration ( user_id BIGINT NOT NULL, registered_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, registered_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, user_id), - KEY idx_stat_user_registration_day (app_code, registered_day, country_id) + KEY idx_stat_user_registration_day (app_code, registered_day, country_id), + KEY idx_stat_user_registration_region (app_code, registered_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户注册日留存 cohort 表'; CREATE TABLE IF NOT EXISTS stat_recharge_day_payers ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_paid_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, user_id), - KEY idx_stat_recharge_payer_country (app_code, stat_day, country_id) + KEY idx_stat_recharge_payer_country (app_code, stat_day, country_id), + KEY idx_stat_recharge_payer_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='充值日付费用户去重表'; CREATE TABLE IF NOT EXISTS stat_lucky_gift_day_payers ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_paid_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, user_id), - KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id) + KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id), + KEY idx_stat_lucky_payer_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物日付费去重表'; CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country ( app_code VARCHAR(32) NOT NULL COMMENT '应用编码', stat_day DATE NOT NULL COMMENT 'UTC 统计日', - country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家或区域维度 ID,0 表示未知或全局', + country_id BIGINT NOT NULL DEFAULT 0 COMMENT '国家维度 ID,0 表示未知或全局', + region_id BIGINT NOT NULL DEFAULT 0 COMMENT '区域维度 ID,0 表示未知或全局', pool_id VARCHAR(96) NOT NULL COMMENT '幸运礼物奖池 ID', turnover_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物流水金币', payout_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物返奖金币', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', PRIMARY KEY (app_code, stat_day, country_id, pool_id), - KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id) + KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id), + KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物奖池国家日统计聚合表'; CREATE TABLE IF NOT EXISTS stat_game_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, @@ -105,16 +118,19 @@ CREATE TABLE IF NOT EXISTS stat_game_day_country ( refund_coin BIGINT NOT NULL DEFAULT 0, player_count BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id) + PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id), + KEY idx_stat_game_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏国家日统计聚合表'; CREATE TABLE IF NOT EXISTS stat_game_day_players ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, user_id BIGINT NOT NULL, first_played_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id, user_id) + PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id, user_id), + KEY idx_stat_game_player_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏日参与用户去重表'; diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 646c4706..336c5718 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -152,6 +152,13 @@ func newConsumers(cfg config.Config, repo *mysqlstorage.Repository) ([]*rocketmq if ok { return repo.ConsumeRecharge(appcode.WithContext(ctx, event.AppCode), event) } + stock, ok, err := coinSellerStockEvent(message.Body) + if err != nil { + return err + } + if ok { + return repo.ConsumeCoinSellerStock(appcode.WithContext(ctx, stock.AppCode), stock) + } reward, ok, err := luckyGiftRewardEvent(message.Body) if err != nil || !ok { return err @@ -174,7 +181,8 @@ func newConsumers(cfg config.Config, repo *mysqlstorage.Repository) ([]*rocketmq EventID: gift.EventID + ":active", EventType: "RoomGiftSentActive", UserID: gift.SenderUserID, - CountryID: gift.VisibleRegionID, + CountryID: gift.CountryID, + RegionID: gift.VisibleRegionID, OccurredAtMS: gift.OccurredAtMS, }) } @@ -213,6 +221,7 @@ func userRegisteredEvent(body []byte) (mysqlstorage.UserRegisteredEvent, bool, e AppCode: message.AppCode, EventID: message.EventID, UserID: message.AggregateID, + CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "country_id"), mysqlstorage.Int64(payload, "target_country_id")), RegionID: mysqlstorage.Int64(payload, "region_id"), OccurredAtMS: message.OccurredAtMS, }, true, nil @@ -243,12 +252,41 @@ func rechargeEvent(body []byte) (mysqlstorage.RechargeEvent, bool, error) { USDMinor: usdMinor, CoinAmount: coinAmount, RechargeSequence: mysqlstorage.Int64(payload, "recharge_sequence"), + TargetCountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "target_country_id"), mysqlstorage.Int64(payload, "country_id")), TargetRegionID: regionID, RechargeType: rechargeType, OccurredAtMS: message.OccurredAtMS, }, true, nil } +func coinSellerStockEvent(body []byte) (mysqlstorage.CoinSellerStockEvent, bool, error) { + message, err := walletmq.DecodeWalletOutboxMessage(body) + if err != nil { + return mysqlstorage.CoinSellerStockEvent{}, false, err + } + if message.EventType != "WalletCoinSellerStockPurchased" { + return mysqlstorage.CoinSellerStockEvent{}, false, nil + } + payload := mysqlstorage.DecodeJSON(message.PayloadJSON) + if !boolValue(payload, "counts_as_seller_recharge") { + return mysqlstorage.CoinSellerStockEvent{}, false, nil + } + usdMinor := amountMicroToUSDMinor(mysqlstorage.Int64(payload, "paid_amount_micro")) + if usdMinor <= 0 { + return mysqlstorage.CoinSellerStockEvent{}, false, nil + } + return mysqlstorage.CoinSellerStockEvent{ + AppCode: message.AppCode, + EventID: message.EventID, + SellerUserID: firstNonZeroInt64(mysqlstorage.Int64(payload, "seller_user_id"), message.UserID), + USDMinor: usdMinor, + CoinAmount: firstNonZeroInt64(mysqlstorage.Int64(payload, "coin_amount"), mysqlstorage.Int64(payload, "available_delta")), + CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "country_id"), mysqlstorage.Int64(payload, "seller_country_id")), + RegionID: firstNonZeroInt64(mysqlstorage.Int64(payload, "region_id"), mysqlstorage.Int64(payload, "seller_region_id")), + OccurredAtMS: message.OccurredAtMS, + }, true, nil +} + func rechargeUSDMinorFromPayload(payload map[string]any, rechargeType string) int64 { // 币商向用户转账是普通金币到账事实,只用于充值用户和金币金额统计;即使历史 payload 携带 recharge_usd_minor,也不能进入用户 USDT/USD 充值。 if isCoinSellerRechargeType(rechargeType) { @@ -303,7 +341,8 @@ func luckyGiftRewardEvent(body []byte) (mysqlstorage.LuckyGiftRewardEvent, bool, EventID: message.EventID, EventType: message.EventType, UserID: firstNonZeroInt64(mysqlstorage.Int64(payload, "user_id"), message.UserID), - CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "visible_region_id"), mysqlstorage.Int64(payload, "region_id"), mysqlstorage.Int64(payload, "target_region_id")), + CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "country_id"), mysqlstorage.Int64(payload, "target_country_id")), + RegionID: firstNonZeroInt64(mysqlstorage.Int64(payload, "visible_region_id"), mysqlstorage.Int64(payload, "region_id"), mysqlstorage.Int64(payload, "target_region_id")), PoolID: mysqlstorage.String(payload, "pool_id"), Amount: mysqlstorage.Int64(payload, "amount"), OccurredAtMS: message.OccurredAtMS, @@ -326,6 +365,7 @@ func roomGiftEvent(body []byte) (mysqlstorage.RoomGiftEvent, bool, error) { AppCode: envelope.GetAppCode(), EventID: envelope.GetEventId(), SenderUserID: gift.GetSenderUserId(), + CountryID: 0, VisibleRegionID: gift.GetVisibleRegionId(), GiftValue: gift.GetGiftValue(), CoinSpent: roomGiftCoinSpent(&gift), @@ -362,7 +402,8 @@ func roomJoinActiveEvent(body []byte) (mysqlstorage.UserActiveEvent, bool, error EventID: envelope.GetEventId(), EventType: envelope.GetEventType(), UserID: joined.GetUserId(), - CountryID: joined.GetVisibleRegionId(), + CountryID: 0, + RegionID: joined.GetVisibleRegionId(), OccurredAtMS: envelope.GetOccurredAtMs(), }, true, nil } @@ -380,7 +421,8 @@ func gameOrderEvent(body []byte) (mysqlstorage.GameOrderEvent, bool, error) { AppCode: message.AppCode, EventID: message.EventID, UserID: message.UserID, - CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "visible_region_id"), mysqlstorage.Int64(payload, "region_id")), + CountryID: firstNonZeroInt64(mysqlstorage.Int64(payload, "country_id"), mysqlstorage.Int64(payload, "target_country_id")), + RegionID: firstNonZeroInt64(mysqlstorage.Int64(payload, "visible_region_id"), mysqlstorage.Int64(payload, "region_id")), PlatformCode: message.PlatformCode, GameID: message.GameID, OpType: message.OpType, @@ -443,3 +485,18 @@ func firstNonZeroInt64(values ...int64) int64 { } return 0 } + +func boolValue(payload map[string]any, key string) bool { + switch value := payload[key].(type) { + case bool: + return value + case string: + return strings.EqualFold(strings.TrimSpace(value), "true") || strings.TrimSpace(value) == "1" + case float64: + return value != 0 + case int64: + return value != 0 + default: + return false + } +} diff --git a/services/statistics-service/internal/app/local_flow_test.go b/services/statistics-service/internal/app/local_flow_test.go index 6d9ff8fa..f981acb6 100644 --- a/services/statistics-service/internal/app/local_flow_test.go +++ b/services/statistics-service/internal/app/local_flow_test.go @@ -32,9 +32,10 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { occurredAt := time.Date(2026, 5, 31, 12, 0, 0, 0, time.UTC).UnixMilli() dayStart := time.Date(2026, 5, 31, 0, 0, 0, 0, time.UTC).UnixMilli() const ( - appCode = "lalu" - regionID = int64(210) - userID = int64(42) + appCode = "lalu" + countryID = int64(86) + regionID = int64(210) + userID = int64(42) ) googleRecharge := walletMessage(t, walletmq.WalletOutboxMessage{ @@ -46,6 +47,7 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { UserID: userID, PayloadJSON: mustJSON(t, map[string]any{ "amount_micro": int64(1_500_000), + "country_id": countryID, "region_id": regionID, "channel": "google", "recharge_sequence": int64(1), @@ -60,6 +62,32 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { t.Fatalf("consume google recharge failed: %v", err) } + coinSellerStock := walletMessage(t, walletmq.WalletOutboxMessage{ + AppCode: appCode, + EventID: "WalletCoinSellerStockPurchased:1", + EventType: "WalletCoinSellerStockPurchased", + TransactionID: "wallet_tx_coin_seller_stock_1", + CommandID: "coin_seller_stock_1", + UserID: userID + 10, + PayloadJSON: mustJSON(t, map[string]any{ + "seller_user_id": userID + 10, + "country_id": countryID, + "region_id": regionID, + "coin_amount": int64(400_000), + "paid_amount_micro": int64(4_000_000), + "counts_as_seller_recharge": true, + "stock_type": "usdt_purchase", + }), + OccurredAtMS: occurredAt, + }) + stock, ok, err := coinSellerStockEvent(coinSellerStock) + if err != nil || !ok { + t.Fatalf("decode coin seller stock failed: ok=%v err=%v", ok, err) + } + if err := repo.ConsumeCoinSellerStock(ctx, stock); err != nil { + t.Fatalf("consume coin seller stock failed: %v", err) + } + coinSellerRecharge := walletMessage(t, walletmq.WalletOutboxMessage{ AppCode: appCode, EventID: "WalletRechargeRecorded:coin_seller:1", @@ -70,6 +98,7 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { PayloadJSON: mustJSON(t, map[string]any{ "amount": int64(160_000), "recharge_type": "coin_seller_transfer", + "target_country_id": countryID, "target_region_id": regionID, "recharge_sequence": int64(1), }), @@ -115,6 +144,7 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { "room_id": "room_1", "pool_id": "lucky_100", "amount": int64(300), + "country_id": countryID, "visible_region_id": regionID, }), OccurredAtMS: occurredAt, @@ -128,8 +158,8 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { } for _, message := range []gamemq.GameOutboxMessage{ - gameMessage(appCode, "game_order_debit_1", userID, "debit", 700, regionID, occurredAt), - gameMessage(appCode, "game_order_credit_1", userID, "credit", 200, regionID, occurredAt), + gameMessage(appCode, "game_order_debit_1", userID, "debit", 700, countryID, regionID, occurredAt), + gameMessage(appCode, "game_order_credit_1", userID, "credit", 200, countryID, regionID, occurredAt), } { body, err := gamemq.EncodeGameOutboxMessage(message) if err != nil { @@ -145,15 +175,15 @@ func TestLocalStatisticsDataScreenFlow(t *testing.T) { } overview, err := repo.QueryOverview(ctx, mysqlstorage.OverviewQuery{ - AppCode: appCode, - StartMS: dayStart, - EndMS: dayStart + int64(24*time.Hour/time.Millisecond), - CountryID: regionID, + AppCode: appCode, + StartMS: dayStart, + EndMS: dayStart + int64(24*time.Hour/time.Millisecond), + RegionID: regionID, }) if err != nil { t.Fatalf("query overview failed: %v", err) } - if overview.GoogleRechargeUSDMinor != 150 || overview.CoinSellerRechargeUSDMinor != 0 || overview.CoinSellerTransferCoin != 160_000 || overview.RechargeUSDMinor != 150 || overview.NewUserRechargeUSDMinor != 150 || overview.PaidUsers != 2 { + if overview.GoogleRechargeUSDMinor != 150 || overview.CoinSellerRechargeUSDMinor != 400 || overview.CoinSellerTransferCoin != 160_000 || overview.RechargeUSDMinor != 550 || overview.NewUserRechargeUSDMinor != 150 || overview.PaidUsers != 2 { t.Fatalf("google recharge metrics mismatch: %+v", overview) } if overview.LuckyGiftTurnover != 1_250 || overview.LuckyGiftPayout != 300 || overview.LuckyGiftProfit != 950 || overview.LuckyGiftPayers != 1 { @@ -201,7 +231,7 @@ func roomGiftMessage(t *testing.T, appCode string, eventID string, roomID string return body } -func gameMessage(appCode string, orderID string, userID int64, opType string, amount int64, regionID int64, occurredAt int64) gamemq.GameOutboxMessage { +func gameMessage(appCode string, orderID string, userID int64, opType string, amount int64, countryID int64, regionID int64, occurredAt int64) gamemq.GameOutboxMessage { return gamemq.GameOutboxMessage{ AppCode: appCode, EventID: "GameOrderSettled:" + orderID, @@ -219,6 +249,7 @@ func gameMessage(appCode string, orderID string, userID int64, opType string, am "user_id": userID, "room_id": "room_1", "visible_region_id": regionID, + "country_id": countryID, "region_id": regionID, "op_type": opType, "coin_amount": amount, diff --git a/services/statistics-service/internal/app/query_http.go b/services/statistics-service/internal/app/query_http.go index f1e505be..81a5897b 100644 --- a/services/statistics-service/internal/app/query_http.go +++ b/services/statistics-service/internal/app/query_http.go @@ -65,10 +65,13 @@ func (s *queryHTTPServer) overview(w http.ResponseWriter, r *http.Request) { endMS = startMS + 24*time.Hour.Milliseconds() } overview, err := s.repo.QueryOverview(r.Context(), mysqlstorage.OverviewQuery{ - AppCode: query.Get("app_code"), - StartMS: startMS, - EndMS: endMS, - CountryID: parseInt64(query.Get("country_id")), + AppCode: query.Get("app_code"), + StartMS: startMS, + EndMS: endMS, + SeriesStartMS: parseInt64(query.Get("series_start_ms")), + SeriesEndMS: parseInt64(query.Get("series_end_ms")), + CountryID: parseInt64(query.Get("country_id")), + RegionID: parseInt64(query.Get("region_id")), }) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]any{"error": err.Error()}) diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index 4c4fb228..09b5259d 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -4,16 +4,20 @@ import ( "context" "database/sql" "math" + "sort" "time" "hyapp/pkg/appcode" ) type OverviewQuery struct { - AppCode string - StartMS int64 - EndMS int64 - CountryID int64 + AppCode string + StartMS int64 + EndMS int64 + SeriesStartMS int64 + SeriesEndMS int64 + CountryID int64 + RegionID int64 } type Overview struct { @@ -24,6 +28,7 @@ type Overview struct { NewUsers int64 `json:"new_users"` ActiveUsers int64 `json:"active_users"` PaidUsers int64 `json:"paid_users"` + NewPaidUsers int64 `json:"new_paid_users"` RechargeUSDMinor int64 `json:"recharge_usd_minor"` NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` @@ -50,6 +55,7 @@ type Overview struct { NewUserRechargeDeltaRate float64 `json:"new_user_recharge_delta_rate"` ActiveUsersDeltaRate float64 `json:"active_users_delta_rate"` PaidUsersDeltaRate float64 `json:"paid_users_delta_rate"` + NewPaidUsersDeltaRate float64 `json:"new_paid_users_delta_rate"` ARPUDeltaRate float64 `json:"arpu_delta_rate"` ARPPUDeltaRate float64 `json:"arppu_delta_rate"` GiftCoinSpentDeltaRate float64 `json:"gift_coin_spent_delta_rate"` @@ -60,8 +66,34 @@ type Overview struct { GameTurnoverDeltaRate float64 `json:"game_turnover_delta_rate"` GameProfitDeltaRate float64 `json:"game_profit_delta_rate"` Retention Retention `json:"retention"` + DailySeries []DailySeriesItem `json:"daily_series"` GameRanking []GameRank `json:"game_ranking"` LuckyGiftPools []LuckyGiftPoolStat `json:"lucky_gift_pools"` + CountryBreakdown []CountryBreakdown `json:"country_breakdown"` +} + +type DailySeriesItem struct { + StatDay string `json:"stat_day"` + Label string `json:"label"` + NewUsers int64 `json:"new_users"` + ActiveUsers int64 `json:"active_users"` + PaidUsers int64 `json:"paid_users"` + NewPaidUsers int64 `json:"new_paid_users"` + RechargeUsers int64 `json:"recharge_users"` + RechargeUSDMinor int64 `json:"recharge_usd_minor"` + NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` + CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` + MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` + GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` + CoinSellerTransferCoin int64 `json:"coin_seller_transfer_coin"` + GiftCoinSpent int64 `json:"gift_coin_spent"` + LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` + LuckyGiftPayout int64 `json:"lucky_gift_payout"` + LuckyGiftProfit int64 `json:"lucky_gift_profit"` + GameTurnover int64 `json:"game_turnover"` + GameProfit int64 `json:"game_profit"` + ARPUUSDMinor int64 `json:"arpu_usd_minor"` + ARPPUUSDMinor int64 `json:"arppu_usd_minor"` } type Retention struct { @@ -94,6 +126,35 @@ type LuckyGiftPoolStat struct { ProfitRate float64 `json:"profit_rate"` } +type CountryBreakdown struct { + CountryID int64 `json:"country_id"` + RegionID int64 `json:"region_id"` + NewUsers int64 `json:"new_users"` + ActiveUsers int64 `json:"active_users"` + PaidUsers int64 `json:"paid_users"` + RechargeUSDMinor int64 `json:"recharge_usd_minor"` + NewUserRechargeUSDMinor int64 `json:"new_user_recharge_usd_minor"` + CoinSellerRechargeUSDMinor int64 `json:"coin_seller_recharge_usd_minor"` + MifaPayRechargeUSDMinor int64 `json:"mifapay_recharge_usd_minor"` + GoogleRechargeUSDMinor int64 `json:"google_recharge_usd_minor"` + CoinSellerTransferCoin int64 `json:"coin_seller_transfer_coin"` + GiftCoinSpent int64 `json:"gift_coin_spent"` + LuckyGiftTurnover int64 `json:"lucky_gift_turnover"` + LuckyGiftPayout int64 `json:"lucky_gift_payout"` + LuckyGiftPayers int64 `json:"lucky_gift_payers"` + LuckyGiftProfit int64 `json:"lucky_gift_profit"` + LuckyGiftPayoutRate float64 `json:"lucky_gift_payout_rate"` + LuckyGiftProfitRate float64 `json:"lucky_gift_profit_rate"` + GameTurnover int64 `json:"game_turnover"` + GamePayout int64 `json:"game_payout"` + GameRefund int64 `json:"game_refund"` + GamePlayers int64 `json:"game_players"` + GameProfit int64 `json:"game_profit"` + GameProfitRate float64 `json:"game_profit_rate"` + ARPUUSDMinor int64 `json:"arpu_usd_minor"` + ARPPUUSDMinor int64 `json:"arppu_usd_minor"` +} + func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Overview, error) { app := appcode.Normalize(query.AppCode) if app == "" { @@ -102,31 +163,38 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov startDay := statDay(query.StartMS) endDay := statDay(query.EndMS - 1) previousStartDay, previousEndDay := previousStatDayRange(startDay, endDay) - overview, err := r.queryAppDayOverviewTotals(ctx, app, startDay, endDay, query.CountryID) + overview, err := r.queryAppDayOverviewTotals(ctx, app, startDay, endDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } - previous, err := r.queryAppDayOverviewTotals(ctx, app, previousStartDay, previousEndDay, query.CountryID) + previous, err := r.queryAppDayOverviewTotals(ctx, app, previousStartDay, previousEndDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } overview.AppCode, overview.StartMS, overview.EndMS, overview.CountryID = app, query.StartMS, query.EndMS, query.CountryID previous.AppCode, previous.CountryID = app, query.CountryID + // 新增付费用户来自日充值用户去重表和注册表的交集;只读聚合小表,避免 Databi 页面回扫钱包或订单明细。 + if overview.NewPaidUsers, err = r.queryNewPaidUsers(ctx, app, startDay, endDay, query.CountryID, query.RegionID); err != nil { + return Overview{}, err + } + if previous.NewPaidUsers, err = r.queryNewPaidUsers(ctx, app, previousStartDay, previousEndDay, query.CountryID, query.RegionID); err != nil { + return Overview{}, err + } // Pool 明细和顶部汇总来自同一个统计窗口;Databi 用它来下钻展示每个 pool_id 的流水、返奖和利润。 - pools, err := r.queryLuckyGiftPools(ctx, app, startDay, endDay, query.CountryID) + pools, err := r.queryLuckyGiftPools(ctx, app, startDay, endDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } overview.LuckyGiftPools = pools // 幸运礼物流水和返奖以 activity-service 的抽奖事实增量日汇总为准;这里仅读小表,避免 Databi 页面扫描 lucky_draw_records。 - if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, startDay, endDay, query.CountryID); err != nil { + if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, startDay, endDay, query.CountryID, query.RegionID); err != nil { return Overview{}, err } else if ok { overview.LuckyGiftPools = activityPools overview.LuckyGiftTurnover, overview.LuckyGiftPayout = sumLuckyGiftPools(activityPools) } // 上一周期也使用相同的日聚合口径,保证“与昨日相比/前周期相比”不额外查询明细表。 - if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, previousStartDay, previousEndDay, query.CountryID); err != nil { + if activityPools, ok, err := r.queryLuckyGiftPoolsFromActivityStats(ctx, app, previousStartDay, previousEndDay, query.CountryID, query.RegionID); err != nil { return Overview{}, err } else if ok { previous.LuckyGiftTurnover, previous.LuckyGiftPayout = sumLuckyGiftPools(activityPools) @@ -134,26 +202,49 @@ func (r *Repository) QueryOverview(ctx context.Context, query OverviewQuery) (Ov applyOverviewDerivedMetrics(&overview) applyOverviewDerivedMetrics(&previous) overview.applyDeltaRates(previous) - retention, err := r.queryRetention(ctx, app, startDay, endDay, query.CountryID) + retention, err := r.queryRetention(ctx, app, startDay, endDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } overview.Retention = retention - ranking, err := r.queryGameRanking(ctx, app, startDay, endDay, query.CountryID) + ranking, err := r.queryGameRanking(ctx, app, startDay, endDay, query.CountryID, query.RegionID) if err != nil { return Overview{}, err } overview.GameRanking = ranking + if query.CountryID <= 0 { + breakdown, err := r.queryCountryBreakdown(ctx, app, startDay, endDay, query.RegionID) + if err != nil { + return Overview{}, err + } + overview.CountryBreakdown = breakdown + } + seriesStartDay, seriesEndDay := startDay, endDay + if query.SeriesStartMS > 0 && query.SeriesEndMS > query.SeriesStartMS { + seriesStartDay = statDay(query.SeriesStartMS) + seriesEndDay = statDay(query.SeriesEndMS - 1) + } + // daily_series 服务卡片内 sparkline 和弹窗折线图;一条 GROUP BY stat_day 查询返回全部指标,避免前端逐日请求。 + dailySeries, err := r.queryDailySeries(ctx, app, seriesStartDay, seriesEndDay, query.CountryID, query.RegionID) + if err != nil { + return Overview{}, err + } + overview.DailySeries = dailySeries return overview, nil } -func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDay, endDay string, countryID int64) (Overview, error) { +func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) (Overview, error) { args := []any{app, startDay, endDay} - countryFilter := "" + filter := "" if countryID > 0 { - countryFilter = " AND country_id = ?" + filter += " AND country_id = ?" args = append(args, countryID) } + if regionID > 0 { + // 旧统计行曾把 region_id 写入 country_id;兼容分支只服务历史读数,新事件写入后会走显式 region_id。 + filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" + args = append(args, regionID, regionID) + } row := r.db.QueryRowContext(ctx, ` SELECT COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), @@ -164,7 +255,7 @@ func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDa COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0), COALESCE(SUM(game_players),0) FROM stat_app_day_country - WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+countryFilter, args...) + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+filter, args...) var overview Overview if err := row.Scan(&overview.NewUsers, &overview.ActiveUsers, &overview.PaidUsers, &overview.RechargeUSDMinor, &overview.NewUserRechargeUSDMinor, &overview.CoinSellerRechargeUSDMinor, &overview.MifaPayRechargeUSDMinor, &overview.GoogleRechargeUSDMinor, &overview.CoinSellerTransferCoin, &overview.GiftCoinSpent, &overview.LuckyGiftTurnover, &overview.LuckyGiftPayout, &overview.LuckyGiftPayers, &overview.GameTurnover, &overview.GamePayout, &overview.GameRefund, &overview.GamePlayers); err != nil { return Overview{}, err @@ -172,12 +263,144 @@ func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDa return overview, nil } +func (r *Repository) queryNewPaidUsers(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) (int64, error) { + args := []any{app, startDay, endDay, startDay, endDay} + filter := "" + if countryID > 0 { + filter += " AND p.country_id = ?" + args = append(args, countryID) + } + if regionID > 0 { + // p 表和 r 表都已经是统计小表,这里只按充值发生地过滤,保证新增付费用户口径和付费用户卡片一致。 + filter += " AND (p.region_id = ? OR (p.region_id = 0 AND p.country_id = ?))" + args = append(args, regionID, regionID) + } + row := r.db.QueryRowContext(ctx, ` + SELECT COUNT(DISTINCT p.user_id) + FROM stat_recharge_day_payers p + JOIN stat_user_registration r ON r.app_code = p.app_code AND r.user_id = p.user_id + WHERE p.app_code = ? AND p.stat_day BETWEEN ? AND ? + AND r.registered_day BETWEEN ? AND ?`+filter, args...) + var count int64 + if err := row.Scan(&count); err != nil && err != sql.ErrNoRows { + return 0, err + } + return count, nil +} + +func (r *Repository) queryDailySeries(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) ([]DailySeriesItem, error) { + args := []any{app, startDay, endDay} + filter := "" + if countryID > 0 { + filter += " AND country_id = ?" + args = append(args, countryID) + } + if regionID > 0 { + // 和总览一致兼容历史 region_id 写到 country_id 的聚合行;新数据优先读显式 region_id。 + filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" + args = append(args, regionID, regionID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), + COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), + COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), + COALESCE(SUM(coin_seller_recharge_usd_minor),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), + COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), + COALESCE(SUM(gift_coin_spent),0), + COALESCE(SUM(lucky_gift_turnover),0), COALESCE(SUM(lucky_gift_payout),0), + COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0) + FROM stat_app_day_country + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+filter+` + GROUP BY stat_day + ORDER BY stat_day ASC`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + out := []DailySeriesItem{} + for rows.Next() { + var item DailySeriesItem + var gamePayout, gameRefund int64 + if err := rows.Scan(&item.StatDay, &item.NewUsers, &item.ActiveUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.GameTurnover, &gamePayout, &gameRefund); err != nil { + return nil, err + } + item.Label = item.StatDay + item.GameProfit = item.GameTurnover - gamePayout - gameRefund + applyDailySeriesDerivedMetrics(&item) + out = append(out, item) + } + if err := rows.Err(); err != nil { + return nil, err + } + newPaidUsersByDay, err := r.queryDailyNewPaidUsers(ctx, app, startDay, endDay, countryID, regionID) + if err != nil { + return nil, err + } + for index := range out { + out[index].NewPaidUsers = newPaidUsersByDay[out[index].StatDay] + } + if activityDaily, ok, err := r.queryLuckyGiftDailyFromActivityStats(ctx, app, startDay, endDay, countryID, regionID); err != nil { + return nil, err + } else if ok { + out = mergeActivityLuckyGiftDaily(out, activityDaily) + } + return out, nil +} + +func (r *Repository) queryDailyNewPaidUsers(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) (map[string]int64, error) { + args := []any{app, startDay, endDay, startDay, endDay} + filter := "" + if countryID > 0 { + filter += " AND p.country_id = ?" + args = append(args, countryID) + } + if regionID > 0 { + filter += " AND (p.region_id = ? OR (p.region_id = 0 AND p.country_id = ?))" + args = append(args, regionID, regionID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT DATE_FORMAT(p.stat_day, '%Y-%m-%d'), COUNT(DISTINCT p.user_id) + FROM stat_recharge_day_payers p + JOIN stat_user_registration r ON r.app_code = p.app_code AND r.user_id = p.user_id + WHERE p.app_code = ? AND p.stat_day BETWEEN ? AND ? + AND r.registered_day BETWEEN ? AND ?`+filter+` + GROUP BY p.stat_day`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + out := map[string]int64{} + for rows.Next() { + var day string + var count int64 + if err := rows.Scan(&day, &count); err != nil { + return nil, err + } + out[day] = count + } + return out, rows.Err() +} + +func applyDailySeriesDerivedMetrics(item *DailySeriesItem) { + if item == nil { + return + } + channelRechargeUSDMinor := item.MifaPayRechargeUSDMinor + item.GoogleRechargeUSDMinor + item.CoinSellerRechargeUSDMinor + if channelRechargeUSDMinor > item.RechargeUSDMinor { + item.RechargeUSDMinor = channelRechargeUSDMinor + } + item.RechargeUsers = item.PaidUsers + item.LuckyGiftProfit = item.LuckyGiftTurnover - item.LuckyGiftPayout + item.ARPUUSDMinor = div(item.RechargeUSDMinor, item.ActiveUsers) + item.ARPPUUSDMinor = div(item.RechargeUSDMinor, item.PaidUsers) +} + func applyOverviewDerivedMetrics(overview *Overview) { if overview == nil { return } - // 历史聚合行可能只写了真实 USD 渠道列、没有同步修正 recharge_usd_minor;查询时用渠道合计兜底,但币商转普通金币只展示金币卡片,不进入用户 USDT 充值。 - channelRechargeUSDMinor := overview.MifaPayRechargeUSDMinor + overview.GoogleRechargeUSDMinor + // 历史聚合行可能只写了真实 USD 渠道列、没有同步修正 recharge_usd_minor;查询时用渠道合计兜底。币商进货是 USDT 充值,币商转普通金币仍只展示金币卡片。 + channelRechargeUSDMinor := overview.MifaPayRechargeUSDMinor + overview.GoogleRechargeUSDMinor + overview.CoinSellerRechargeUSDMinor if channelRechargeUSDMinor > overview.RechargeUSDMinor { overview.RechargeUSDMinor = channelRechargeUSDMinor } @@ -199,6 +422,7 @@ func (overview *Overview) applyDeltaRates(previous Overview) { overview.NewUserRechargeDeltaRate = deltaRate(overview.NewUserRechargeUSDMinor, previous.NewUserRechargeUSDMinor) overview.ActiveUsersDeltaRate = deltaRate(overview.ActiveUsers, previous.ActiveUsers) overview.PaidUsersDeltaRate = deltaRate(overview.PaidUsers, previous.PaidUsers) + overview.NewPaidUsersDeltaRate = deltaRate(overview.NewPaidUsers, previous.NewPaidUsers) overview.ARPUDeltaRate = deltaRate(overview.ARPUUSDMinor, previous.ARPUUSDMinor) overview.ARPPUDeltaRate = deltaRate(overview.ARPPUUSDMinor, previous.ARPPUUSDMinor) overview.GiftCoinSpentDeltaRate = deltaRate(overview.GiftCoinSpent, previous.GiftCoinSpent) @@ -210,13 +434,17 @@ func (overview *Overview) applyDeltaRates(previous Overview) { overview.GameProfitDeltaRate = deltaRate(overview.GameProfit, previous.GameProfit) } -func (r *Repository) queryRetention(ctx context.Context, app, startDay, endDay string, countryID int64) (Retention, error) { +func (r *Repository) queryRetention(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) (Retention, error) { filter := "" args := []any{app, startDay, endDay} if countryID > 0 { filter = " AND r.country_id = ?" args = append(args, countryID) } + if regionID > 0 { + filter += " AND (r.region_id = ? OR (r.region_id = 0 AND r.country_id = ?))" + args = append(args, regionID, regionID) + } row := r.db.QueryRowContext(ctx, ` SELECT COUNT(*), COALESCE(SUM(EXISTS(SELECT 1 FROM stat_user_day_activity a WHERE a.app_code=r.app_code AND a.user_id=r.user_id AND a.stat_day=DATE_ADD(r.registered_day, INTERVAL 1 DAY))),0), @@ -234,13 +462,17 @@ func (r *Repository) queryRetention(ctx context.Context, app, startDay, endDay s return out, nil } -func (r *Repository) queryGameRanking(ctx context.Context, app, startDay, endDay string, countryID int64) ([]GameRank, error) { +func (r *Repository) queryGameRanking(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) ([]GameRank, error) { args := []any{app, startDay, endDay} filter := "" if countryID > 0 { filter = " AND country_id = ?" args = append(args, countryID) } + if regionID > 0 { + filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" + args = append(args, regionID, regionID) + } rows, err := r.db.QueryContext(ctx, ` SELECT platform_code, game_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0), COALESCE(SUM(refund_coin),0), COALESCE(SUM(player_count),0) @@ -266,13 +498,72 @@ func (r *Repository) queryGameRanking(ctx context.Context, app, startDay, endDay return out, rows.Err() } -func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, endDay string, countryID int64) ([]LuckyGiftPoolStat, error) { +func (r *Repository) queryCountryBreakdown(ctx context.Context, app, startDay, endDay string, regionID int64) ([]CountryBreakdown, error) { + args := []any{app, startDay, endDay} + filter := "" + if regionID > 0 { + filter = " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" + args = append(args, regionID, regionID) + } + rows, err := r.db.QueryContext(ctx, ` + SELECT country_id, COALESCE(MAX(region_id),0), + COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), + COALESCE(SUM(recharge_usd_minor),0), COALESCE(SUM(new_user_recharge_usd_minor),0), + COALESCE(SUM(coin_seller_recharge_usd_minor),0), COALESCE(SUM(mifapay_recharge_usd_minor),0), + COALESCE(SUM(google_recharge_usd_minor),0), COALESCE(SUM(coin_seller_transfer_coin),0), + COALESCE(SUM(gift_coin_spent),0), + COALESCE(SUM(lucky_gift_turnover),0), COALESCE(SUM(lucky_gift_payout),0), COALESCE(SUM(lucky_gift_payers),0), + COALESCE(SUM(game_turnover),0), COALESCE(SUM(game_payout),0), COALESCE(SUM(game_refund),0), + COALESCE(SUM(game_players),0) + FROM stat_app_day_country + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`+filter+` + GROUP BY country_id + ORDER BY COALESCE(SUM(recharge_usd_minor),0) DESC, COALESCE(SUM(active_users),0) DESC, country_id ASC + LIMIT 500`, args...) + if err != nil { + return nil, err + } + defer rows.Close() + out := []CountryBreakdown{} + for rows.Next() { + var item CountryBreakdown + if err := rows.Scan(&item.CountryID, &item.RegionID, &item.NewUsers, &item.ActiveUsers, &item.PaidUsers, &item.RechargeUSDMinor, &item.NewUserRechargeUSDMinor, &item.CoinSellerRechargeUSDMinor, &item.MifaPayRechargeUSDMinor, &item.GoogleRechargeUSDMinor, &item.CoinSellerTransferCoin, &item.GiftCoinSpent, &item.LuckyGiftTurnover, &item.LuckyGiftPayout, &item.LuckyGiftPayers, &item.GameTurnover, &item.GamePayout, &item.GameRefund, &item.GamePlayers); err != nil { + return nil, err + } + applyCountryBreakdownDerivedMetrics(&item) + out = append(out, item) + } + return out, rows.Err() +} + +func applyCountryBreakdownDerivedMetrics(item *CountryBreakdown) { + if item == nil { + return + } + channelRechargeUSDMinor := item.MifaPayRechargeUSDMinor + item.GoogleRechargeUSDMinor + item.CoinSellerRechargeUSDMinor + if channelRechargeUSDMinor > item.RechargeUSDMinor { + item.RechargeUSDMinor = channelRechargeUSDMinor + } + item.GameProfit = item.GameTurnover - item.GamePayout - item.GameRefund + item.GameProfitRate = ratio(item.GameProfit, item.GameTurnover) + item.ARPUUSDMinor = div(item.RechargeUSDMinor, item.ActiveUsers) + item.ARPPUUSDMinor = div(item.RechargeUSDMinor, item.PaidUsers) + item.LuckyGiftProfit = item.LuckyGiftTurnover - item.LuckyGiftPayout + item.LuckyGiftPayoutRate = ratio(item.LuckyGiftPayout, item.LuckyGiftTurnover) + item.LuckyGiftProfitRate = ratio(item.LuckyGiftProfit, item.LuckyGiftTurnover) +} + +func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) ([]LuckyGiftPoolStat, error) { args := []any{app, startDay, endDay} filter := "" if countryID > 0 { filter = " AND country_id = ?" args = append(args, countryID) } + if regionID > 0 { + filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" + args = append(args, regionID, regionID) + } rows, err := r.db.QueryContext(ctx, ` SELECT pool_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0) FROM stat_lucky_gift_pool_day_country @@ -297,13 +588,16 @@ func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, end return out, rows.Err() } -func (r *Repository) queryLuckyGiftPoolsFromActivityStats(ctx context.Context, app, startDay, endDay string, countryID int64) ([]LuckyGiftPoolStat, bool, error) { +func (r *Repository) queryLuckyGiftPoolsFromActivityStats(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) ([]LuckyGiftPoolStat, bool, error) { if r == nil || r.activityDB == nil { return nil, false, nil } args := []any{app, startDay, endDay} filter := "" - if countryID > 0 { + if regionID > 0 { + filter = " AND visible_region_id = ?" + args = append(args, regionID) + } else if countryID > 0 { filter = " AND visible_region_id = ?" args = append(args, countryID) } @@ -337,6 +631,69 @@ func (r *Repository) queryLuckyGiftPoolsFromActivityStats(ctx context.Context, a return out, len(out) > 0, nil } +func (r *Repository) queryLuckyGiftDailyFromActivityStats(ctx context.Context, app, startDay, endDay string, countryID int64, regionID int64) (map[string]LuckyGiftPoolStat, bool, error) { + if r == nil || r.activityDB == nil { + return nil, false, nil + } + args := []any{app, startDay, endDay} + filter := "" + if regionID > 0 { + filter = " AND visible_region_id = ?" + args = append(args, regionID) + } else if countryID > 0 { + filter = " AND visible_region_id = ?" + args = append(args, countryID) + } + rows, err := r.activityDB.QueryContext(ctx, ` + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0) + FROM lucky_draw_pool_day_stats + WHERE app_code = ? AND stat_day BETWEEN ? AND ? AND gift_id = ''`+filter+` + GROUP BY stat_day`, args...) + if err != nil { + if isMissingTableError(err) { + return nil, false, nil + } + return nil, false, err + } + defer rows.Close() + out := map[string]LuckyGiftPoolStat{} + for rows.Next() { + var day string + var item LuckyGiftPoolStat + if err := rows.Scan(&day, &item.TurnoverCoin, &item.PayoutCoin); err != nil { + return nil, false, err + } + item.ProfitCoin = item.TurnoverCoin - item.PayoutCoin + out[day] = item + } + if err := rows.Err(); err != nil { + return nil, false, err + } + return out, len(out) > 0, nil +} + +func mergeActivityLuckyGiftDaily(items []DailySeriesItem, activityDaily map[string]LuckyGiftPoolStat) []DailySeriesItem { + byDay := make(map[string]int, len(items)) + for index := range items { + byDay[items[index].StatDay] = index + } + for day, activity := range activityDaily { + index, exists := byDay[day] + if !exists { + items = append(items, DailySeriesItem{StatDay: day, Label: day}) + index = len(items) - 1 + byDay[day] = index + } + items[index].LuckyGiftTurnover = activity.TurnoverCoin + items[index].LuckyGiftPayout = activity.PayoutCoin + applyDailySeriesDerivedMetrics(&items[index]) + } + sort.SliceStable(items, func(left, right int) bool { + return items[left].StatDay < items[right].StatDay + }) + return items +} + func sumLuckyGiftPools(pools []LuckyGiftPoolStat) (int64, int64) { var turnover, payout int64 for _, pool := range pools { diff --git a/services/statistics-service/internal/storage/mysql/query_test.go b/services/statistics-service/internal/storage/mysql/query_test.go index c84e4e7f..72943502 100644 --- a/services/statistics-service/internal/storage/mysql/query_test.go +++ b/services/statistics-service/internal/storage/mysql/query_test.go @@ -107,3 +107,43 @@ func TestQueryOverviewReturnsPreviousPeriodDeltaRates(t *testing.T) { t.Fatalf("game delta rates mismatch: %+v", overview) } } + +func TestQueryOverviewReturnsCountryBreakdownAndIncludesCoinSellerRecharge(t *testing.T) { + ctx := context.Background() + _, file, _, _ := runtime.Caller(0) + statsSchema := mysqlschema.New(t, mysqlschema.Config{ + InitDBPath: mysqlschema.InitDBPath(t, file, "..", "..", "..", "deploy", "mysql", "initdb", "001_statistics_service.sql"), + DatabasePrefix: "hy_stats_query_country_test", + }) + repository, err := Open(ctx, statsSchema.DSN) + if err != nil { + t.Fatalf("open repository: %v", err) + } + t.Cleanup(func() { _ = repository.Close() }) + + if _, err := repository.db.ExecContext(ctx, ` + INSERT INTO stat_app_day_country ( + app_code, stat_day, country_id, region_id, active_users, paid_users, recharge_usd_minor, + coin_seller_recharge_usd_minor, google_recharge_usd_minor, updated_at_ms + ) VALUES + ('lalu', '2026-06-06', 86, 210, 10, 2, 150, 400, 150, 1), + ('lalu', '2026-06-06', 66, 210, 5, 1, 100, 0, 100, 1), + ('lalu', '2026-06-06', 99, 220, 3, 1, 900, 0, 900, 1)`); err != nil { + t.Fatalf("seed country statistics: %v", err) + } + + start := time.Date(2026, 6, 6, 0, 0, 0, 0, time.UTC).UnixMilli() + overview, err := repository.QueryOverview(ctx, OverviewQuery{AppCode: "lalu", StartMS: start, EndMS: start + int64(24*time.Hour/time.Millisecond), RegionID: 210}) + if err != nil { + t.Fatalf("query overview: %v", err) + } + if overview.RechargeUSDMinor != 650 || overview.CoinSellerRechargeUSDMinor != 400 { + t.Fatalf("overview recharge mismatch: %+v", overview) + } + if len(overview.CountryBreakdown) != 2 { + t.Fatalf("country breakdown should come from aggregate query: %+v", overview.CountryBreakdown) + } + if overview.CountryBreakdown[0].CountryID != 86 || overview.CountryBreakdown[0].RechargeUSDMinor != 550 || overview.CountryBreakdown[0].ARPPUUSDMinor != 275 { + t.Fatalf("first country breakdown mismatch: %+v", overview.CountryBreakdown[0]) + } +} diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index e34f76d5..9b0ca68b 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -104,6 +104,7 @@ func (r *Repository) Migrate(ctx context.Context) error { ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_app_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, new_users BIGINT NOT NULL DEFAULT 0, active_users BIGINT NOT NULL DEFAULT 0, paid_users BIGINT NOT NULL DEFAULT 0, recharge_usd_minor BIGINT NOT NULL DEFAULT 0, new_user_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, coin_seller_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, mifapay_recharge_usd_minor BIGINT NOT NULL DEFAULT 0, @@ -112,49 +113,63 @@ func (r *Repository) Migrate(ctx context.Context) error { lucky_gift_turnover BIGINT NOT NULL DEFAULT 0, lucky_gift_payout BIGINT NOT NULL DEFAULT 0, lucky_gift_payers BIGINT NOT NULL DEFAULT 0, game_turnover BIGINT NOT NULL DEFAULT 0, game_players BIGINT NOT NULL DEFAULT 0, game_payout BIGINT NOT NULL DEFAULT 0, game_refund BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id) + PRIMARY KEY (app_code, stat_day, country_id), + KEY idx_stat_app_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_user_day_activity ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_active_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, user_id), - KEY idx_stat_user_day_country (app_code, stat_day, country_id) + KEY idx_stat_user_day_country (app_code, stat_day, country_id), + KEY idx_stat_user_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_user_registration ( app_code VARCHAR(32) NOT NULL, user_id BIGINT NOT NULL, registered_day DATE NOT NULL, - country_id BIGINT NOT NULL DEFAULT 0, registered_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, user_id), KEY idx_stat_user_registration_day (app_code, registered_day, country_id) + country_id BIGINT NOT NULL DEFAULT 0, region_id BIGINT NOT NULL DEFAULT 0, registered_at_ms BIGINT NOT NULL, + PRIMARY KEY (app_code, user_id), KEY idx_stat_user_registration_day (app_code, registered_day, country_id), + KEY idx_stat_user_registration_region (app_code, registered_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_recharge_day_payers ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_paid_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, user_id), KEY idx_stat_recharge_payer_country (app_code, stat_day, country_id) + PRIMARY KEY (app_code, stat_day, user_id), KEY idx_stat_recharge_payer_country (app_code, stat_day, country_id), + KEY idx_stat_recharge_payer_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_lucky_gift_day_payers ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, user_id BIGINT NOT NULL, first_paid_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, user_id), - KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id) + KEY idx_stat_lucky_payer_country (app_code, stat_day, country_id), + KEY idx_stat_lucky_payer_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, pool_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, payout_coin BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, PRIMARY KEY (app_code, stat_day, country_id, pool_id), - KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id) + KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id), + KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_game_day_country ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, payout_coin BIGINT NOT NULL DEFAULT 0, refund_coin BIGINT NOT NULL DEFAULT 0, player_count BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id) + PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id), + KEY idx_stat_game_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_game_day_players ( app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL DEFAULT 0, + region_id BIGINT NOT NULL DEFAULT 0, platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, user_id BIGINT NOT NULL, first_played_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id, user_id) + PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id, user_id), + KEY idx_stat_game_player_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, } for _, statement := range statements { @@ -168,9 +183,25 @@ func (r *Repository) Migrate(ctx context.Context) error { `ALTER TABLE stat_app_day_country ADD COLUMN lucky_gift_payout BIGINT NOT NULL DEFAULT 0 AFTER lucky_gift_turnover`, `ALTER TABLE stat_app_day_country ADD COLUMN coin_seller_transfer_coin BIGINT NOT NULL DEFAULT 0 AFTER google_recharge_usd_minor`, `ALTER TABLE stat_game_day_country ADD COLUMN refund_coin BIGINT NOT NULL DEFAULT 0 AFTER payout_coin`, + `ALTER TABLE stat_app_day_country ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_user_day_activity ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_user_registration ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_recharge_day_payers ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_lucky_gift_day_payers ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_lucky_gift_pool_day_country ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_game_day_country ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_game_day_players ADD COLUMN region_id BIGINT NOT NULL DEFAULT 0 AFTER country_id`, + `ALTER TABLE stat_app_day_country ADD KEY idx_stat_app_day_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_user_day_activity ADD KEY idx_stat_user_day_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_user_registration ADD KEY idx_stat_user_registration_region (app_code, registered_day, region_id)`, + `ALTER TABLE stat_recharge_day_payers ADD KEY idx_stat_recharge_payer_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_lucky_gift_day_payers ADD KEY idx_stat_lucky_payer_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_lucky_gift_pool_day_country ADD KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_game_day_country ADD KEY idx_stat_game_day_region (app_code, stat_day, region_id)`, + `ALTER TABLE stat_game_day_players ADD KEY idx_stat_game_player_region (app_code, stat_day, region_id)`, } for _, statement := range alterStatements { - if _, err := r.db.ExecContext(ctx, statement); err != nil && !isDuplicateColumnError(err) { + if _, err := r.db.ExecContext(ctx, statement); err != nil && !isDuplicateSchemaError(err) { return err } } @@ -181,6 +212,7 @@ type UserRegisteredEvent struct { AppCode string EventID string UserID int64 + CountryID int64 RegionID int64 OccurredAtMS int64 } @@ -193,15 +225,28 @@ type RechargeEvent struct { USDMinor int64 CoinAmount int64 RechargeSequence int64 + TargetCountryID int64 TargetRegionID int64 RechargeType string OccurredAtMS int64 } +type CoinSellerStockEvent struct { + AppCode string + EventID string + SellerUserID int64 + USDMinor int64 + CoinAmount int64 + CountryID int64 + RegionID int64 + OccurredAtMS int64 +} + type RoomGiftEvent struct { AppCode string EventID string SenderUserID int64 + CountryID int64 VisibleRegionID int64 GiftValue int64 CoinSpent int64 @@ -215,6 +260,7 @@ type LuckyGiftRewardEvent struct { EventType string UserID int64 CountryID int64 + RegionID int64 PoolID string Amount int64 OccurredAtMS int64 @@ -226,6 +272,7 @@ type UserActiveEvent struct { EventType string UserID int64 CountryID int64 + RegionID int64 OccurredAtMS int64 } @@ -234,6 +281,7 @@ type GameOrderEvent struct { EventID string UserID int64 CountryID int64 + RegionID int64 PlatformCode string GameID string OpType string @@ -244,14 +292,14 @@ type GameOrderEvent struct { func (r *Repository) ConsumeUserRegistered(ctx context.Context, event UserRegisteredEvent) error { return r.withEvent(ctx, SourceUser, event.EventID, "UserRegistered", func(tx *sql.Tx, nowMS int64) error { day := statDay(event.OccurredAtMS) - countryID := normalizeID(event.RegionID) - if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { + countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { return err } if _, err := tx.ExecContext(ctx, ` - INSERT IGNORE INTO stat_user_registration (app_code, user_id, registered_day, country_id, registered_at_ms) - VALUES (?, ?, ?, ?, ?) - `, appcode.Normalize(event.AppCode), event.UserID, day, countryID, event.OccurredAtMS); err != nil { + INSERT IGNORE INTO stat_user_registration (app_code, user_id, registered_day, country_id, region_id, registered_at_ms) + VALUES (?, ?, ?, ?, ?, ?) + `, appcode.Normalize(event.AppCode), event.UserID, day, countryID, regionID, event.OccurredAtMS); err != nil { return err } _, err := tx.ExecContext(ctx, ` @@ -266,14 +314,14 @@ func (r *Repository) ConsumeUserRegistered(ctx context.Context, event UserRegist func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) error { return r.withEvent(ctx, SourceWallet, event.EventID, event.EventType, func(tx *sql.Tx, nowMS int64) error { day := statDay(event.OccurredAtMS) - countryID := normalizeID(event.TargetRegionID) - if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { + countryID, regionID := normalizeDimension(event.TargetCountryID, event.TargetRegionID) + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { return err } paidUsers, err := insertUnique(ctx, tx, ` - INSERT IGNORE INTO stat_recharge_day_payers (app_code, stat_day, country_id, user_id, first_paid_at_ms) - VALUES (?, ?, ?, ?, ?) - `, appcode.Normalize(event.AppCode), day, countryID, event.UserID, event.OccurredAtMS) + INSERT IGNORE INTO stat_recharge_day_payers (app_code, stat_day, country_id, region_id, user_id, first_paid_at_ms) + VALUES (?, ?, ?, ?, ?, ?) + `, appcode.Normalize(event.AppCode), day, countryID, regionID, event.UserID, event.OccurredAtMS) if err != nil { return err } @@ -308,11 +356,30 @@ func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) e }) } +func (r *Repository) ConsumeCoinSellerStock(ctx context.Context, event CoinSellerStockEvent) error { + return r.withEvent(ctx, SourceWallet, event.EventID, "WalletCoinSellerStockPurchased", func(tx *sql.Tx, nowMS int64) error { + day := statDay(event.OccurredAtMS) + countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { + return err + } + // 币商进货是后台 USDT 入金事实,只进入总充值和币商充值列;它不是普通用户到账,所以不增加用户 USDT 首充和付费用户。 + _, err := tx.ExecContext(ctx, ` + UPDATE stat_app_day_country + SET recharge_usd_minor = recharge_usd_minor + ?, + coin_seller_recharge_usd_minor = coin_seller_recharge_usd_minor + ?, + updated_at_ms = ? + WHERE app_code = ? AND stat_day = ? AND country_id = ? + `, event.USDMinor, event.USDMinor, nowMS, appcode.Normalize(event.AppCode), day, countryID) + return err + }) +} + func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) error { return r.withEvent(ctx, SourceRoom, event.EventID, "RoomGiftSent", func(tx *sql.Tx, nowMS int64) error { day := statDay(event.OccurredAtMS) - countryID := normalizeID(event.VisibleRegionID) - if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { + countryID, regionID := normalizeDimension(event.CountryID, event.VisibleRegionID) + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { return err } luckyTurnover, luckyPayers := int64(0), int64(0) @@ -320,15 +387,15 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e if poolID != "" { luckyTurnover = event.CoinSpent affected, err := insertUnique(ctx, tx, ` - INSERT IGNORE INTO stat_lucky_gift_day_payers (app_code, stat_day, country_id, user_id, first_paid_at_ms) - VALUES (?, ?, ?, ?, ?) - `, appcode.Normalize(event.AppCode), day, countryID, event.SenderUserID, event.OccurredAtMS) + INSERT IGNORE INTO stat_lucky_gift_day_payers (app_code, stat_day, country_id, region_id, user_id, first_paid_at_ms) + VALUES (?, ?, ?, ?, ?, ?) + `, appcode.Normalize(event.AppCode), day, countryID, regionID, event.SenderUserID, event.OccurredAtMS) if err != nil { return err } luckyPayers = affected // Pool 明细是 Databi 点击下钻的真实口径:每笔带 pool_id 的幸运礼物送礼先按 UTC 日、国家和奖池累加流水,返奖事件稍后用相同维度补齐 payout。 - if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, poolID, nowMS); err != nil { + if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, regionID, poolID, nowMS); err != nil { return err } if _, err := tx.ExecContext(ctx, ` @@ -352,14 +419,14 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e func (r *Repository) ConsumeLuckyGiftReward(ctx context.Context, event LuckyGiftRewardEvent) error { return r.withEvent(ctx, SourceWallet, event.EventID, "WalletLuckyGiftRewardCredited", func(tx *sql.Tx, nowMS int64) error { day := statDay(event.OccurredAtMS) - countryID := normalizeID(event.CountryID) - if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { + countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { return err } poolID := strings.TrimSpace(event.PoolID) if poolID != "" { // 钱包返奖事件带回 pool_id 后,按同一 UTC 日和国家写入奖池返奖;利润不落表,查询时用 turnover-payout 实时计算,避免双写漂移。 - if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, poolID, nowMS); err != nil { + if err := ensureLuckyGiftPoolDay(ctx, tx, event.AppCode, day, countryID, regionID, poolID, nowMS); err != nil { return err } if _, err := tx.ExecContext(ctx, ` @@ -381,18 +448,19 @@ func (r *Repository) ConsumeLuckyGiftReward(ctx context.Context, event LuckyGift func (r *Repository) ConsumeUserActive(ctx context.Context, event UserActiveEvent) error { return r.withEvent(ctx, SourceRoom, event.EventID, event.EventType, func(tx *sql.Tx, nowMS int64) error { - return applyActive(ctx, tx, event.AppCode, statDay(event.OccurredAtMS), normalizeID(event.CountryID), event.UserID, event.OccurredAtMS, nowMS) + countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + return applyActive(ctx, tx, event.AppCode, statDay(event.OccurredAtMS), countryID, regionID, event.UserID, event.OccurredAtMS, nowMS) }) } func (r *Repository) ConsumeGameOrder(ctx context.Context, event GameOrderEvent) error { return r.withEvent(ctx, SourceGame, event.EventID, "GameOrderSettled", func(tx *sql.Tx, nowMS int64) error { day := statDay(event.OccurredAtMS) - countryID := normalizeID(event.CountryID) - if err := applyActive(ctx, tx, event.AppCode, day, countryID, event.UserID, event.OccurredAtMS, nowMS); err != nil { + countryID, regionID := normalizeDimension(event.CountryID, event.RegionID) + if err := applyActive(ctx, tx, event.AppCode, day, countryID, regionID, event.UserID, event.OccurredAtMS, nowMS); err != nil { return err } - if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, nowMS); err != nil { + if err := ensureAppDay(ctx, tx, event.AppCode, day, countryID, regionID, nowMS); err != nil { return err } turnover, payout, refund := int64(0), int64(0), int64(0) @@ -407,15 +475,15 @@ func (r *Repository) ConsumeGameOrder(ctx context.Context, event GameOrderEvent) playerDelta := int64(0) if turnover > 0 { affected, err := insertUnique(ctx, tx, ` - INSERT IGNORE INTO stat_game_day_players (app_code, stat_day, country_id, platform_code, game_id, user_id, first_played_at_ms) - VALUES (?, ?, ?, ?, ?, ?, ?) - `, appcode.Normalize(event.AppCode), day, countryID, event.PlatformCode, event.GameID, event.UserID, event.OccurredAtMS) + INSERT IGNORE INTO stat_game_day_players (app_code, stat_day, country_id, region_id, platform_code, game_id, user_id, first_played_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + `, appcode.Normalize(event.AppCode), day, countryID, regionID, event.PlatformCode, event.GameID, event.UserID, event.OccurredAtMS) if err != nil { return err } playerDelta = affected } - if err := ensureGameDay(ctx, tx, event.AppCode, day, countryID, event.PlatformCode, event.GameID, nowMS); err != nil { + if err := ensureGameDay(ctx, tx, event.AppCode, day, countryID, regionID, event.PlatformCode, event.GameID, nowMS); err != nil { return err } if _, err := tx.ExecContext(ctx, ` @@ -501,9 +569,9 @@ func isRetryableMySQLError(err error) bool { return mysqlErr.Number == 1213 || mysqlErr.Number == 1205 } -func isDuplicateColumnError(err error) bool { +func isDuplicateSchemaError(err error) bool { var mysqlErr *mysqlerr.MySQLError - return errors.As(err, &mysqlErr) && mysqlErr.Number == 1060 + return errors.As(err, &mysqlErr) && (mysqlErr.Number == 1060 || mysqlErr.Number == 1061) } func isMissingTableError(err error) bool { @@ -511,14 +579,14 @@ func isMissingTableError(err error) bool { return errors.As(err, &mysqlErr) && mysqlErr.Number == 1146 } -func applyActive(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, userID int64, occurredAtMS int64, nowMS int64) error { - if err := ensureAppDay(ctx, tx, app, day, countryID, nowMS); err != nil { +func applyActive(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, regionID int64, userID int64, occurredAtMS int64, nowMS int64) error { + if err := ensureAppDay(ctx, tx, app, day, countryID, regionID, nowMS); err != nil { return err } affected, err := insertUnique(ctx, tx, ` - INSERT IGNORE INTO stat_user_day_activity (app_code, stat_day, country_id, user_id, first_active_at_ms) - VALUES (?, ?, ?, ?, ?) - `, appcode.Normalize(app), day, countryID, userID, occurredAtMS) + INSERT IGNORE INTO stat_user_day_activity (app_code, stat_day, country_id, region_id, user_id, first_active_at_ms) + VALUES (?, ?, ?, ?, ?, ?) + `, appcode.Normalize(app), day, countryID, regionID, userID, occurredAtMS) if err != nil { return err } @@ -533,27 +601,36 @@ func applyActive(ctx context.Context, tx *sql.Tx, app string, day string, countr return err } -func ensureAppDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, nowMS int64) error { +func ensureAppDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, regionID int64, nowMS int64) error { _, err := tx.ExecContext(ctx, ` - INSERT IGNORE INTO stat_app_day_country (app_code, stat_day, country_id, updated_at_ms) - VALUES (?, ?, ?, ?) - `, appcode.Normalize(app), day, countryID, nowMS) - return err -} - -func ensureGameDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, platformCode string, gameID string, nowMS int64) error { - _, err := tx.ExecContext(ctx, ` - INSERT IGNORE INTO stat_game_day_country (app_code, stat_day, country_id, platform_code, game_id, updated_at_ms) - VALUES (?, ?, ?, ?, ?, ?) - `, appcode.Normalize(app), day, countryID, platformCode, gameID, nowMS) - return err -} - -func ensureLuckyGiftPoolDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, poolID string, nowMS int64) error { - _, err := tx.ExecContext(ctx, ` - INSERT IGNORE INTO stat_lucky_gift_pool_day_country (app_code, stat_day, country_id, pool_id, updated_at_ms) + INSERT INTO stat_app_day_country (app_code, stat_day, country_id, region_id, updated_at_ms) VALUES (?, ?, ?, ?, ?) - `, appcode.Normalize(app), day, countryID, strings.TrimSpace(poolID), nowMS) + ON DUPLICATE KEY UPDATE + region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), + updated_at_ms = VALUES(updated_at_ms) + `, appcode.Normalize(app), day, countryID, regionID, nowMS) + return err +} + +func ensureGameDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, regionID int64, platformCode string, gameID string, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_game_day_country (app_code, stat_day, country_id, region_id, platform_code, game_id, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), + updated_at_ms = VALUES(updated_at_ms) + `, appcode.Normalize(app), day, countryID, regionID, platformCode, gameID, nowMS) + return err +} + +func ensureLuckyGiftPoolDay(ctx context.Context, tx *sql.Tx, app string, day string, countryID int64, regionID int64, poolID string, nowMS int64) error { + _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_lucky_gift_pool_day_country (app_code, stat_day, country_id, region_id, pool_id, updated_at_ms) + VALUES (?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), + updated_at_ms = VALUES(updated_at_ms) + `, appcode.Normalize(app), day, countryID, regionID, strings.TrimSpace(poolID), nowMS) return err } @@ -580,6 +657,10 @@ func normalizeID(id int64) int64 { return id } +func normalizeDimension(countryID int64, regionID int64) (int64, int64) { + return normalizeID(countryID), normalizeID(regionID) +} + func DecodeJSON(payload string) map[string]any { decoded := map[string]any{} _ = json.Unmarshal([]byte(payload), &decoded) diff --git a/services/user-service/internal/storage/mysql/user/repository.go b/services/user-service/internal/storage/mysql/user/repository.go index 2439549f..a245b88a 100644 --- a/services/user-service/internal/storage/mysql/user/repository.go +++ b/services/user-service/internal/storage/mysql/user/repository.go @@ -158,6 +158,7 @@ func insertUserRegisteredOutbox(ctx context.Context, tx *sql.Tx, user userdomain "user_id": user.UserID, "default_display_user_id": user.DefaultDisplayUserID, "country": user.Country, + "country_id": user.CountryID, "country_by_ip": user.CountryByIP, "region_id": user.RegionID, "invite_code": user.InviteCode, From b49a2109c77ecd11dbdc1105b6b28fc9ffb3b660 Mon Sep 17 00:00:00 2001 From: zhx Date: Mon, 8 Jun 2026 12:01:55 +0800 Subject: [PATCH 27/28] Fix databi statistics dimensions and backfill --- api/proto/events/room/v1/events.pb.go | 914 +- api/proto/events/room/v1/events.proto | 4 + api/proto/room/v1/room.pb.go | 4502 ++++++---- api/proto/room/v1/room.proto | 4 + api/proto/room/v1/room_grpc.pb.go | 106 +- api/proto/wallet/v1/wallet.pb.go | 7487 ++++++++++------- api/proto/wallet/v1/wallet.proto | 5 +- api/proto/wallet/v1/wallet_grpc.pb.go | 148 +- .../admin/internal/modules/hostorg/service.go | 13 + .../transport/http/roomapi/room_handler.go | 30 +- .../http/walletapi/wallet_handler.go | 47 +- .../internal/room/command/command.go | 6 + .../internal/room/service/gift.go | 19 +- .../internal/room/service/helpers.go | 9 + .../internal/room/service/presence.go | 8 +- .../cmd/backfill-last7/main.go | 647 ++ .../mysql/initdb/001_statistics_service.sql | 6 +- .../statistics-service/internal/app/app.go | 8 +- .../internal/storage/mysql/query.go | 34 +- .../internal/storage/mysql/repository.go | 100 +- .../internal/domain/ledger/ledger.go | 21 +- .../internal/service/wallet/service.go | 6 + .../internal/service/wallet/service_test.go | 120 +- .../internal/storage/mysql/repository.go | 55 +- .../internal/transport/grpc/server.go | 19 +- 25 files changed, 9164 insertions(+), 5154 deletions(-) create mode 100644 services/statistics-service/cmd/backfill-last7/main.go diff --git a/api/proto/events/room/v1/events.pb.go b/api/proto/events/room/v1/events.pb.go index 3c87687e..f800268b 100644 --- a/api/proto/events/room/v1/events.pb.go +++ b/api/proto/events/room/v1/events.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 +// protoc-gen-go v1.35.1 // protoc v7.35.0 // source: proto/events/room/v1/events.proto @@ -11,7 +11,6 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" - unsafe "unsafe" ) const ( @@ -24,16 +23,17 @@ const ( // EventEnvelope 是 room-service outbox 的统一事件外壳。 // body 保存具体事件消息序列化后的二进制,event_type 负责告诉消费者如何解码。 type EventEnvelope struct { - state protoimpl.MessageState `protogen:"open.v1"` - EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` - RoomVersion int64 `protobuf:"varint,4,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - OccurredAtMs int64 `protobuf:"varint,5,opt,name=occurred_at_ms,json=occurredAtMs,proto3" json:"occurred_at_ms,omitempty"` - Body []byte `protobuf:"bytes,6,opt,name=body,proto3" json:"body,omitempty"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EventId string `protobuf:"bytes,1,opt,name=event_id,json=eventId,proto3" json:"event_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + RoomVersion int64 `protobuf:"varint,4,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` + OccurredAtMs int64 `protobuf:"varint,5,opt,name=occurred_at_ms,json=occurredAtMs,proto3" json:"occurred_at_ms,omitempty"` + Body []byte `protobuf:"bytes,6,opt,name=body,proto3" json:"body,omitempty"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *EventEnvelope) Reset() { @@ -117,16 +117,17 @@ func (x *EventEnvelope) GetAppCode() string { // RoomCreated 表达房间第一次建立成功。 type RoomCreated struct { - state protoimpl.MessageState `protogen:"open.v1"` - OwnerUserId int64 `protobuf:"varint,1,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - SeatCount int32 `protobuf:"varint,3,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` - Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OwnerUserId int64 `protobuf:"varint,1,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + SeatCount int32 `protobuf:"varint,3,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` // room_name/room_avatar/room_description 是创建时确定的展示资料快照,消费者不需要反查 room-service。 RoomName string `protobuf:"bytes,5,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"` RoomAvatar string `protobuf:"bytes,6,opt,name=room_avatar,json=roomAvatar,proto3" json:"room_avatar,omitempty"` RoomDescription string `protobuf:"bytes,7,opt,name=room_description,json=roomDescription,proto3" json:"room_description,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomCreated) Reset() { @@ -203,15 +204,16 @@ func (x *RoomCreated) GetRoomDescription() string { // RoomProfileUpdated 表达房间展示资料或麦位数量变更。 type RoomProfileUpdated struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - RoomName string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"` - RoomAvatar string `protobuf:"bytes,3,opt,name=room_avatar,json=roomAvatar,proto3" json:"room_avatar,omitempty"` - RoomDescription string `protobuf:"bytes,4,opt,name=room_description,json=roomDescription,proto3" json:"room_description,omitempty"` - SeatCount int32 `protobuf:"varint,5,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` - RoomBackgroundUrl string `protobuf:"bytes,6,opt,name=room_background_url,json=roomBackgroundUrl,proto3" json:"room_background_url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + RoomName string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3" json:"room_name,omitempty"` + RoomAvatar string `protobuf:"bytes,3,opt,name=room_avatar,json=roomAvatar,proto3" json:"room_avatar,omitempty"` + RoomDescription string `protobuf:"bytes,4,opt,name=room_description,json=roomDescription,proto3" json:"room_description,omitempty"` + SeatCount int32 `protobuf:"varint,5,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + RoomBackgroundUrl string `protobuf:"bytes,6,opt,name=room_background_url,json=roomBackgroundUrl,proto3" json:"room_background_url,omitempty"` } func (x *RoomProfileUpdated) Reset() { @@ -288,12 +290,13 @@ func (x *RoomProfileUpdated) GetRoomBackgroundUrl() string { // RoomBackgroundChanged 表达房主切换当前房间背景图。 type RoomBackgroundChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - BackgroundId int64 `protobuf:"varint,2,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` - RoomBackgroundUrl string `protobuf:"bytes,3,opt,name=room_background_url,json=roomBackgroundUrl,proto3" json:"room_background_url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + BackgroundId int64 `protobuf:"varint,2,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` + RoomBackgroundUrl string `protobuf:"bytes,3,opt,name=room_background_url,json=roomBackgroundUrl,proto3" json:"room_background_url,omitempty"` } func (x *RoomBackgroundChanged) Reset() { @@ -349,18 +352,19 @@ func (x *RoomBackgroundChanged) GetRoomBackgroundUrl() string { // RoomUserJoined 表达用户业务态进房成功。 type RoomEntryVehicleSnapshot struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - AssetUrl string `protobuf:"bytes,4,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,5,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,6,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - MetadataJson string `protobuf:"bytes,7,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - EntitlementId string `protobuf:"bytes,8,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + AssetUrl string `protobuf:"bytes,4,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,5,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,6,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + MetadataJson string `protobuf:"bytes,7,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + EntitlementId string `protobuf:"bytes,8,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` } func (x *RoomEntryVehicleSnapshot) Reset() { @@ -457,14 +461,17 @@ func (x *RoomEntryVehicleSnapshot) GetExpiresAtMs() int64 { } type RoomUserJoined struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` // visible_region_id 是用户进房时所在房间的国家/区域桶,统计服务不能反查 room-service。 VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` EntryVehicle *RoomEntryVehicleSnapshot `protobuf:"bytes,4,opt,name=entry_vehicle,json=entryVehicle,proto3" json:"entry_vehicle,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + CountryId int64 `protobuf:"varint,5,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` } func (x *RoomUserJoined) Reset() { @@ -525,12 +532,27 @@ func (x *RoomUserJoined) GetEntryVehicle() *RoomEntryVehicleSnapshot { return nil } +func (x *RoomUserJoined) GetCountryId() int64 { + if x != nil { + return x.CountryId + } + return 0 +} + +func (x *RoomUserJoined) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + // RoomUserLeft 表达用户离房成功。 type RoomUserLeft struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *RoomUserLeft) Reset() { @@ -572,11 +594,12 @@ func (x *RoomUserLeft) GetUserId() int64 { // RoomClosed 表达房间生命周期关闭完成。 type RoomClosed struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *RoomClosed) Reset() { @@ -625,12 +648,15 @@ func (x *RoomClosed) GetReason() string { // RoomMicChanged 表达任意上下麦和换麦位动作。 type RoomMicChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - FromSeat int32 `protobuf:"varint,3,opt,name=from_seat,json=fromSeat,proto3" json:"from_seat,omitempty"` - ToSeat int32 `protobuf:"varint,4,opt,name=to_seat,json=toSeat,proto3" json:"to_seat,omitempty"` - Action string `protobuf:"bytes,5,opt,name=action,proto3" json:"action,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + FromSeat int32 `protobuf:"varint,3,opt,name=from_seat,json=fromSeat,proto3" json:"from_seat,omitempty"` + ToSeat int32 `protobuf:"varint,4,opt,name=to_seat,json=toSeat,proto3" json:"to_seat,omitempty"` + Action string `protobuf:"bytes,5,opt,name=action,proto3" json:"action,omitempty"` // mic_session_id 用于把业务麦位事件和 RTC 发流会话绑定,客户端和 webhook 都必须透传。 MicSessionId string `protobuf:"bytes,6,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` // publish_state 透出 pending_publish/publishing/idle,避免把“占麦”和“已发流”混成一个状态。 @@ -641,8 +667,6 @@ type RoomMicChanged struct { PublishEventTimeMs int64 `protobuf:"varint,10,opt,name=publish_event_time_ms,json=publishEventTimeMs,proto3" json:"publish_event_time_ms,omitempty"` MicMuted bool `protobuf:"varint,11,opt,name=mic_muted,json=micMuted,proto3" json:"mic_muted,omitempty"` SeatStatus string `protobuf:"bytes,12,opt,name=seat_status,json=seatStatus,proto3" json:"seat_status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomMicChanged) Reset() { @@ -761,12 +785,13 @@ func (x *RoomMicChanged) GetSeatStatus() string { // RoomMicSeatLocked 表达单个麦位锁定状态变更。 type RoomMicSeatLocked struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` } func (x *RoomMicSeatLocked) Reset() { @@ -822,11 +847,12 @@ func (x *RoomMicSeatLocked) GetLocked() bool { // RoomChatEnabledChanged 表达公屏开关状态变更。 type RoomChatEnabledChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` } func (x *RoomChatEnabledChanged) Reset() { @@ -875,13 +901,14 @@ func (x *RoomChatEnabledChanged) GetEnabled() bool { // RoomPasswordChanged 表达房间入房密码状态变更,不携带明文或哈希。 type RoomPasswordChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` // visible_region_id 是房间当前可见区域,activity-service 用它把锁房变化投到区域播报群。 VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomPasswordChanged) Reset() { @@ -937,12 +964,13 @@ func (x *RoomPasswordChanged) GetVisibleRegionId() int64 { // RoomAdminChanged 表达房间管理员集合变更。 type RoomAdminChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` } func (x *RoomAdminChanged) Reset() { @@ -998,12 +1026,13 @@ func (x *RoomAdminChanged) GetEnabled() bool { // RoomUserMuted 表达禁言状态变更。 type RoomUserMuted struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` } func (x *RoomUserMuted) Reset() { @@ -1059,11 +1088,12 @@ func (x *RoomUserMuted) GetMuted() bool { // RoomUserKicked 表达踢人动作。 type RoomUserKicked struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` } func (x *RoomUserKicked) Reset() { @@ -1112,11 +1142,12 @@ func (x *RoomUserKicked) GetTargetUserId() int64 { // RoomUserUnbanned 表达解除房间 ban。 type RoomUserUnbanned struct { - state protoimpl.MessageState `protogen:"open.v1"` - ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ActorUserId int64 `protobuf:"varint,1,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` } func (x *RoomUserUnbanned) Reset() { @@ -1165,19 +1196,22 @@ func (x *RoomUserUnbanned) GetTargetUserId() int64 { // RoomGiftSent 表达送礼成功且已落房间状态。 type RoomGiftSent struct { - state protoimpl.MessageState `protogen:"open.v1"` - SenderUserId int64 `protobuf:"varint,1,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,4,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - GiftValue int64 `protobuf:"varint,5,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - BillingReceiptId string `protobuf:"bytes,6,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,7,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - CommandId string `protobuf:"bytes,8,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - PoolId string `protobuf:"bytes,9,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - CoinSpent int64 `protobuf:"varint,10,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SenderUserId int64 `protobuf:"varint,1,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,4,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + GiftValue int64 `protobuf:"varint,5,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + BillingReceiptId string `protobuf:"bytes,6,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,7,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + CommandId string `protobuf:"bytes,8,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + PoolId string `protobuf:"bytes,9,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + CoinSpent int64 `protobuf:"varint,10,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + CountryId int64 `protobuf:"varint,11,opt,name=country_id,json=countryId,proto3" json:"country_id,omitempty"` + RegionId int64 `protobuf:"varint,12,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` } func (x *RoomGiftSent) Reset() { @@ -1280,13 +1314,28 @@ func (x *RoomGiftSent) GetCoinSpent() int64 { return 0 } +func (x *RoomGiftSent) GetCountryId() int64 { + if x != nil { + return x.CountryId + } + return 0 +} + +func (x *RoomGiftSent) GetRegionId() int64 { + if x != nil { + return x.RegionId + } + return 0 +} + // RoomHeatChanged 表达热度变化结果。 type RoomHeatChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - Delta int64 `protobuf:"varint,1,opt,name=delta,proto3" json:"delta,omitempty"` - CurrentHeat int64 `protobuf:"varint,2,opt,name=current_heat,json=currentHeat,proto3" json:"current_heat,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Delta int64 `protobuf:"varint,1,opt,name=delta,proto3" json:"delta,omitempty"` + CurrentHeat int64 `protobuf:"varint,2,opt,name=current_heat,json=currentHeat,proto3" json:"current_heat,omitempty"` } func (x *RoomHeatChanged) Reset() { @@ -1335,12 +1384,13 @@ func (x *RoomHeatChanged) GetCurrentHeat() int64 { // RoomRankChanged 表达本地礼物榜变化结果。 type RoomRankChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Score int64 `protobuf:"varint,2,opt,name=score,proto3" json:"score,omitempty"` - GiftValue int64 `protobuf:"varint,3,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Score int64 `protobuf:"varint,2,opt,name=score,proto3" json:"score,omitempty"` + GiftValue int64 `protobuf:"varint,3,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` } func (x *RoomRankChanged) Reset() { @@ -1395,17 +1445,18 @@ func (x *RoomRankChanged) GetGiftValue() int64 { } type RoomRocketRewardGrant struct { - state protoimpl.MessageState `protogen:"open.v1"` - RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RewardItemId string `protobuf:"bytes,3,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` - ResourceGroupId int64 `protobuf:"varint,4,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` - DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - IconUrl string `protobuf:"bytes,6,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` - GrantId string `protobuf:"bytes,7,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RewardItemId string `protobuf:"bytes,3,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` + ResourceGroupId int64 `protobuf:"varint,4,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + IconUrl string `protobuf:"bytes,6,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` + GrantId string `protobuf:"bytes,7,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` } func (x *RoomRocketRewardGrant) Reset() { @@ -1496,23 +1547,24 @@ func (x *RoomRocketRewardGrant) GetStatus() string { // RoomRocketFuelChanged 表达送礼扣费成功后火箭有效燃料发生变化。 type RoomRocketFuelChanged struct { - state protoimpl.MessageState `protogen:"open.v1"` - RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - AddedFuel int64 `protobuf:"varint,3,opt,name=added_fuel,json=addedFuel,proto3" json:"added_fuel,omitempty"` - EffectiveAddedFuel int64 `protobuf:"varint,4,opt,name=effective_added_fuel,json=effectiveAddedFuel,proto3" json:"effective_added_fuel,omitempty"` - OverflowFuel int64 `protobuf:"varint,5,opt,name=overflow_fuel,json=overflowFuel,proto3" json:"overflow_fuel,omitempty"` - CurrentFuel int64 `protobuf:"varint,6,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` - FuelThreshold int64 `protobuf:"varint,7,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - ResetAtMs int64 `protobuf:"varint,9,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - SenderUserId int64 `protobuf:"varint,10,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - GiftId string `protobuf:"bytes,11,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,14,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + AddedFuel int64 `protobuf:"varint,3,opt,name=added_fuel,json=addedFuel,proto3" json:"added_fuel,omitempty"` + EffectiveAddedFuel int64 `protobuf:"varint,4,opt,name=effective_added_fuel,json=effectiveAddedFuel,proto3" json:"effective_added_fuel,omitempty"` + OverflowFuel int64 `protobuf:"varint,5,opt,name=overflow_fuel,json=overflowFuel,proto3" json:"overflow_fuel,omitempty"` + CurrentFuel int64 `protobuf:"varint,6,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` + FuelThreshold int64 `protobuf:"varint,7,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + ResetAtMs int64 `protobuf:"varint,9,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + SenderUserId int64 `protobuf:"varint,10,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + GiftId string `protobuf:"bytes,11,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,12,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + CommandId string `protobuf:"bytes,13,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,14,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` } func (x *RoomRocketFuelChanged) Reset() { @@ -1645,23 +1697,24 @@ func (x *RoomRocketFuelChanged) GetVisibleRegionId() int64 { // RoomRocketIgnited 表达火箭燃料满后进入倒计时,并作为区域/全局播报的事实源。 type RoomRocketIgnited struct { - state protoimpl.MessageState `protogen:"open.v1"` - RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - CurrentFuel int64 `protobuf:"varint,3,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` - FuelThreshold int64 `protobuf:"varint,4,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` - IgnitedAtMs int64 `protobuf:"varint,5,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` - LaunchAtMs int64 `protobuf:"varint,6,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` - BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` - VisibleRegionId int64 `protobuf:"varint,8,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` - IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` - CommandId string `protobuf:"bytes,11,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - RoomShortId string `protobuf:"bytes,12,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - RocketCoverUrl string `protobuf:"bytes,13,opt,name=rocket_cover_url,json=rocketCoverUrl,proto3" json:"rocket_cover_url,omitempty"` - ResetAtMs int64 `protobuf:"varint,14,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + CurrentFuel int64 `protobuf:"varint,3,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` + FuelThreshold int64 `protobuf:"varint,4,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + IgnitedAtMs int64 `protobuf:"varint,5,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` + LaunchAtMs int64 `protobuf:"varint,6,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` + BroadcastScope string `protobuf:"bytes,7,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` + VisibleRegionId int64 `protobuf:"varint,8,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + Top1UserId int64 `protobuf:"varint,9,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,10,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + CommandId string `protobuf:"bytes,11,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RoomShortId string `protobuf:"bytes,12,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + RocketCoverUrl string `protobuf:"bytes,13,opt,name=rocket_cover_url,json=rocketCoverUrl,proto3" json:"rocket_cover_url,omitempty"` + ResetAtMs int64 `protobuf:"varint,14,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` } func (x *RoomRocketIgnited) Reset() { @@ -1794,7 +1847,10 @@ func (x *RoomRocketIgnited) GetResetAtMs() int64 { // RoomRocketLaunched 表达火箭已经发射,在线用户名单按发射瞬间 Room Cell presence 结算。 type RoomRocketLaunched struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` NextLevel int32 `protobuf:"varint,3,opt,name=next_level,json=nextLevel,proto3" json:"next_level,omitempty"` @@ -1804,8 +1860,6 @@ type RoomRocketLaunched struct { IgniterUserId int64 `protobuf:"varint,7,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` InRoomUserIds []int64 `protobuf:"varint,8,rep,packed,name=in_room_user_ids,json=inRoomUserIds,proto3" json:"in_room_user_ids,omitempty"` Rewards []*RoomRocketRewardGrant `protobuf:"bytes,9,rep,name=rewards,proto3" json:"rewards,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomRocketLaunched) Reset() { @@ -1903,12 +1957,13 @@ func (x *RoomRocketLaunched) GetRewards() []*RoomRocketRewardGrant { // RoomRocketRewardGranted 是客户端展示发奖弹窗和私有通知的最小事实。 type RoomRocketRewardGranted struct { - state protoimpl.MessageState `protogen:"open.v1"` - RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - Rewards []*RoomRocketRewardGrant `protobuf:"bytes,3,rep,name=rewards,proto3" json:"rewards,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + Rewards []*RoomRocketRewardGrant `protobuf:"bytes,3,rep,name=rewards,proto3" json:"rewards,omitempty"` } func (x *RoomRocketRewardGranted) Reset() { @@ -1964,200 +2019,342 @@ func (x *RoomRocketRewardGranted) GetRewards() []*RoomRocketRewardGrant { var File_proto_events_room_v1_events_proto protoreflect.FileDescriptor -const file_proto_events_room_v1_events_proto_rawDesc = "" + - "\n" + - "!proto/events/room/v1/events.proto\x12\x14hyapp.events.room.v1\"\xda\x01\n" + - "\rEventEnvelope\x12\x19\n" + - "\bevent_id\x18\x01 \x01(\tR\aeventId\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x1d\n" + - "\n" + - "event_type\x18\x03 \x01(\tR\teventType\x12!\n" + - "\froom_version\x18\x04 \x01(\x03R\vroomVersion\x12$\n" + - "\x0eoccurred_at_ms\x18\x05 \x01(\x03R\foccurredAtMs\x12\x12\n" + - "\x04body\x18\x06 \x01(\fR\x04body\x12\x19\n" + - "\bapp_code\x18\a \x01(\tR\aappCode\"\xcd\x01\n" + - "\vRoomCreated\x12\"\n" + - "\rowner_user_id\x18\x01 \x01(\x03R\vownerUserId\x12\x1d\n" + - "\n" + - "seat_count\x18\x03 \x01(\x05R\tseatCount\x12\x12\n" + - "\x04mode\x18\x04 \x01(\tR\x04mode\x12\x1b\n" + - "\troom_name\x18\x05 \x01(\tR\broomName\x12\x1f\n" + - "\vroom_avatar\x18\x06 \x01(\tR\n" + - "roomAvatar\x12)\n" + - "\x10room_description\x18\a \x01(\tR\x0froomDescription\"\xf0\x01\n" + - "\x12RoomProfileUpdated\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x1b\n" + - "\troom_name\x18\x02 \x01(\tR\broomName\x12\x1f\n" + - "\vroom_avatar\x18\x03 \x01(\tR\n" + - "roomAvatar\x12)\n" + - "\x10room_description\x18\x04 \x01(\tR\x0froomDescription\x12\x1d\n" + - "\n" + - "seat_count\x18\x05 \x01(\x05R\tseatCount\x12.\n" + - "\x13room_background_url\x18\x06 \x01(\tR\x11roomBackgroundUrl\"\x90\x01\n" + - "\x15RoomBackgroundChanged\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12#\n" + - "\rbackground_id\x18\x02 \x01(\x03R\fbackgroundId\x12.\n" + - "\x13room_background_url\x18\x03 \x01(\tR\x11roomBackgroundUrl\"\xc7\x02\n" + - "\x18RoomEntryVehicleSnapshot\x12\x1f\n" + - "\vresource_id\x18\x01 \x01(\x03R\n" + - "resourceId\x12#\n" + - "\rresource_code\x18\x02 \x01(\tR\fresourceCode\x12\x12\n" + - "\x04name\x18\x03 \x01(\tR\x04name\x12\x1b\n" + - "\tasset_url\x18\x04 \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\x05 \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\x06 \x01(\tR\fanimationUrl\x12#\n" + - "\rmetadata_json\x18\a \x01(\tR\fmetadataJson\x12%\n" + - "\x0eentitlement_id\x18\b \x01(\tR\rentitlementId\x12\"\n" + - "\rexpires_at_ms\x18\t \x01(\x03R\vexpiresAtMs\"\xbe\x01\n" + - "\x0eRoomUserJoined\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" + - "\x04role\x18\x02 \x01(\tR\x04role\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\x12S\n" + - "\rentry_vehicle\x18\x04 \x01(\v2..hyapp.events.room.v1.RoomEntryVehicleSnapshotR\fentryVehicle\"'\n" + - "\fRoomUserLeft\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\"H\n" + - "\n" + - "RoomClosed\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x16\n" + - "\x06reason\x18\x02 \x01(\tR\x06reason\"\xac\x03\n" + - "\x0eRoomMicChanged\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x1b\n" + - "\tfrom_seat\x18\x03 \x01(\x05R\bfromSeat\x12\x17\n" + - "\ato_seat\x18\x04 \x01(\x05R\x06toSeat\x12\x16\n" + - "\x06action\x18\x05 \x01(\tR\x06action\x12$\n" + - "\x0emic_session_id\x18\x06 \x01(\tR\fmicSessionId\x12#\n" + - "\rpublish_state\x18\a \x01(\tR\fpublishState\x12\x16\n" + - "\x06reason\x18\b \x01(\tR\x06reason\x12.\n" + - "\x13publish_deadline_ms\x18\t \x01(\x03R\x11publishDeadlineMs\x121\n" + - "\x15publish_event_time_ms\x18\n" + - " \x01(\x03R\x12publishEventTimeMs\x12\x1b\n" + - "\tmic_muted\x18\v \x01(\bR\bmicMuted\x12\x1f\n" + - "\vseat_status\x18\f \x01(\tR\n" + - "seatStatus\"h\n" + - "\x11RoomMicSeatLocked\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12\x16\n" + - "\x06locked\x18\x03 \x01(\bR\x06locked\"V\n" + - "\x16RoomChatEnabledChanged\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x18\n" + - "\aenabled\x18\x02 \x01(\bR\aenabled\"}\n" + - "\x13RoomPasswordChanged\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12\x16\n" + - "\x06locked\x18\x02 \x01(\bR\x06locked\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\"v\n" + - "\x10RoomAdminChanged\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x18\n" + - "\aenabled\x18\x03 \x01(\bR\aenabled\"o\n" + - "\rRoomUserMuted\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x14\n" + - "\x05muted\x18\x03 \x01(\bR\x05muted\"Z\n" + - "\x0eRoomUserKicked\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"\\\n" + - "\x10RoomUserUnbanned\x12\"\n" + - "\ractor_user_id\x18\x01 \x01(\x03R\vactorUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"\xe2\x02\n" + - "\fRoomGiftSent\x12$\n" + - "\x0esender_user_id\x18\x01 \x01(\x03R\fsenderUserId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x17\n" + - "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x1d\n" + - "\n" + - "gift_count\x18\x04 \x01(\x05R\tgiftCount\x12\x1d\n" + - "\n" + - "gift_value\x18\x05 \x01(\x03R\tgiftValue\x12,\n" + - "\x12billing_receipt_id\x18\x06 \x01(\tR\x10billingReceiptId\x12*\n" + - "\x11visible_region_id\x18\a \x01(\x03R\x0fvisibleRegionId\x12\x1d\n" + - "\n" + - "command_id\x18\b \x01(\tR\tcommandId\x12\x17\n" + - "\apool_id\x18\t \x01(\tR\x06poolId\x12\x1d\n" + - "\n" + - "coin_spent\x18\n" + - " \x01(\x03R\tcoinSpent\"J\n" + - "\x0fRoomHeatChanged\x12\x14\n" + - "\x05delta\x18\x01 \x01(\x03R\x05delta\x12!\n" + - "\fcurrent_heat\x18\x02 \x01(\x03R\vcurrentHeat\"_\n" + - "\x0fRoomRankChanged\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n" + - "\x05score\x18\x02 \x01(\x03R\x05score\x12\x1d\n" + - "\n" + - "gift_value\x18\x03 \x01(\x03R\tgiftValue\"\x94\x02\n" + - "\x15RoomRocketRewardGrant\x12\x1f\n" + - "\vreward_role\x18\x01 \x01(\tR\n" + - "rewardRole\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + - "\x0ereward_item_id\x18\x03 \x01(\tR\frewardItemId\x12*\n" + - "\x11resource_group_id\x18\x04 \x01(\x03R\x0fresourceGroupId\x12!\n" + - "\fdisplay_name\x18\x05 \x01(\tR\vdisplayName\x12\x19\n" + - "\bicon_url\x18\x06 \x01(\tR\aiconUrl\x12\x19\n" + - "\bgrant_id\x18\a \x01(\tR\agrantId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\"\xeb\x03\n" + - "\x15RoomRocketFuelChanged\x12\x1b\n" + - "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12\x1d\n" + - "\n" + - "added_fuel\x18\x03 \x01(\x03R\taddedFuel\x120\n" + - "\x14effective_added_fuel\x18\x04 \x01(\x03R\x12effectiveAddedFuel\x12#\n" + - "\roverflow_fuel\x18\x05 \x01(\x03R\foverflowFuel\x12!\n" + - "\fcurrent_fuel\x18\x06 \x01(\x03R\vcurrentFuel\x12%\n" + - "\x0efuel_threshold\x18\a \x01(\x03R\rfuelThreshold\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\x12\x1e\n" + - "\vreset_at_ms\x18\t \x01(\x03R\tresetAtMs\x12$\n" + - "\x0esender_user_id\x18\n" + - " \x01(\x03R\fsenderUserId\x12\x17\n" + - "\agift_id\x18\v \x01(\tR\x06giftId\x12\x1d\n" + - "\n" + - "gift_count\x18\f \x01(\x05R\tgiftCount\x12\x1d\n" + - "\n" + - "command_id\x18\r \x01(\tR\tcommandId\x12*\n" + - "\x11visible_region_id\x18\x0e \x01(\x03R\x0fvisibleRegionId\"\x82\x04\n" + - "\x11RoomRocketIgnited\x12\x1b\n" + - "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12!\n" + - "\fcurrent_fuel\x18\x03 \x01(\x03R\vcurrentFuel\x12%\n" + - "\x0efuel_threshold\x18\x04 \x01(\x03R\rfuelThreshold\x12\"\n" + - "\rignited_at_ms\x18\x05 \x01(\x03R\vignitedAtMs\x12 \n" + - "\flaunch_at_ms\x18\x06 \x01(\x03R\n" + - "launchAtMs\x12'\n" + - "\x0fbroadcast_scope\x18\a \x01(\tR\x0ebroadcastScope\x12*\n" + - "\x11visible_region_id\x18\b \x01(\x03R\x0fvisibleRegionId\x12 \n" + - "\ftop1_user_id\x18\t \x01(\x03R\n" + - "top1UserId\x12&\n" + - "\x0figniter_user_id\x18\n" + - " \x01(\x03R\rigniterUserId\x12\x1d\n" + - "\n" + - "command_id\x18\v \x01(\tR\tcommandId\x12\"\n" + - "\rroom_short_id\x18\f \x01(\tR\vroomShortId\x12(\n" + - "\x10rocket_cover_url\x18\r \x01(\tR\x0erocketCoverUrl\x12\x1e\n" + - "\vreset_at_ms\x18\x0e \x01(\x03R\tresetAtMs\"\xe6\x02\n" + - "\x12RoomRocketLaunched\x12\x1b\n" + - "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12\x1d\n" + - "\n" + - "next_level\x18\x03 \x01(\x05R\tnextLevel\x12$\n" + - "\x0elaunched_at_ms\x18\x04 \x01(\x03R\flaunchedAtMs\x12\x1e\n" + - "\vreset_at_ms\x18\x05 \x01(\x03R\tresetAtMs\x12 \n" + - "\ftop1_user_id\x18\x06 \x01(\x03R\n" + - "top1UserId\x12&\n" + - "\x0figniter_user_id\x18\a \x01(\x03R\rigniterUserId\x12'\n" + - "\x10in_room_user_ids\x18\b \x03(\x03R\rinRoomUserIds\x12E\n" + - "\arewards\x18\t \x03(\v2+.hyapp.events.room.v1.RoomRocketRewardGrantR\arewards\"\x93\x01\n" + - "\x17RoomRocketRewardGranted\x12\x1b\n" + - "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12E\n" + - "\arewards\x18\x03 \x03(\v2+.hyapp.events.room.v1.RoomRocketRewardGrantR\arewardsB3Z1hyapp.local/api/proto/events/room/v1;roomeventsv1b\x06proto3" +var file_proto_events_room_v1_events_proto_rawDesc = []byte{ + 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x72, + 0x6f, 0x6f, 0x6d, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x22, 0xda, 0x01, 0x0a, 0x0d, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x63, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0xcd, 0x01, 0x0a, 0x0b, 0x52, 0x6f, 0x6f, 0x6d, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, + 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xf0, 0x01, 0x0a, 0x12, 0x52, 0x6f, 0x6f, 0x6d, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x22, 0x0a, + 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, + 0x29, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x6d, 0x44, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, + 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x6f, 0x6f, + 0x6d, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x72, 0x6c, 0x22, 0x90, 0x01, 0x0a, 0x15, 0x52, 0x6f, + 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x13, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x6f, 0x6f, 0x6d, 0x42, + 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x72, 0x6c, 0x22, 0xc7, 0x02, 0x0a, + 0x18, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, + 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, + 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, + 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xfa, 0x01, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, + 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, + 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x53, 0x0a, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x76, 0x65, 0x68, 0x69, + 0x63, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, + 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x0c, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x27, 0x0a, 0x0c, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x65, 0x66, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x48, 0x0a, 0x0a, + 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xac, 0x03, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, + 0x69, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x73, 0x65, 0x61, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x06, 0x74, 0x6f, 0x53, 0x65, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, + 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, + 0x6e, 0x65, 0x4d, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x12, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x63, 0x5f, 0x6d, + 0x75, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x69, 0x63, 0x4d, + 0x75, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x68, 0x0a, 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x4d, 0x69, 0x63, + 0x53, 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x22, + 0x56, 0x0a, 0x16, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x7d, 0x0a, 0x13, 0x52, 0x6f, 0x6f, 0x6d, 0x50, + 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, + 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, + 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x6f, + 0x0a, 0x0d, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4d, 0x75, 0x74, 0x65, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x75, 0x74, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x22, + 0x5a, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x4b, 0x69, 0x63, 0x6b, 0x65, + 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5c, 0x0a, 0x10, 0x52, + 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x9e, 0x03, 0x0a, 0x0c, 0x52, 0x6f, + 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x53, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, + 0x12, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x4a, 0x0a, 0x0f, 0x52, 0x6f, + 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, + 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x68, + 0x65, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x48, 0x65, 0x61, 0x74, 0x22, 0x5f, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x61, + 0x6e, 0x6b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, + 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x94, 0x02, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x6c, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x6f, + 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x49, + 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x21, 0x0a, + 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x69, 0x63, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xeb, + 0x03, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x46, 0x75, 0x65, + 0x6c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x61, + 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x61, 0x64, 0x64, 0x65, 0x64, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x75, + 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x65, 0x64, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, + 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6f, 0x76, 0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x46, 0x75, 0x65, + 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, 0x65, + 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x46, 0x75, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, + 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, + 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, + 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, + 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, + 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x82, 0x04, 0x0a, + 0x11, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x67, 0x6e, 0x69, 0x74, + 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, + 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6c, 0x61, 0x75, 0x6e, 0x63, + 0x68, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, + 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x2a, + 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, + 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, + 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, + 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, + 0x6c, 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, + 0x73, 0x22, 0xe6, 0x02, 0x0a, 0x12, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x6e, 0x65, 0x78, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, + 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x10, 0x69, 0x6e, + 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, + 0x20, 0x03, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x52, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x17, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x07, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, + 0x42, 0x33, 0x5a, 0x31, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x6f, 0x6f, 0x6d, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} var ( file_proto_events_room_v1_events_proto_rawDescOnce sync.Once - file_proto_events_room_v1_events_proto_rawDescData []byte + file_proto_events_room_v1_events_proto_rawDescData = file_proto_events_room_v1_events_proto_rawDesc ) func file_proto_events_room_v1_events_proto_rawDescGZIP() []byte { file_proto_events_room_v1_events_proto_rawDescOnce.Do(func() { - file_proto_events_room_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_events_room_v1_events_proto_rawDesc), len(file_proto_events_room_v1_events_proto_rawDesc))) + file_proto_events_room_v1_events_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_events_room_v1_events_proto_rawDescData) }) return file_proto_events_room_v1_events_proto_rawDescData } @@ -2209,7 +2406,7 @@ func file_proto_events_room_v1_events_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_events_room_v1_events_proto_rawDesc), len(file_proto_events_room_v1_events_proto_rawDesc)), + RawDescriptor: file_proto_events_room_v1_events_proto_rawDesc, NumEnums: 0, NumMessages: 24, NumExtensions: 0, @@ -2220,6 +2417,7 @@ func file_proto_events_room_v1_events_proto_init() { MessageInfos: file_proto_events_room_v1_events_proto_msgTypes, }.Build() File_proto_events_room_v1_events_proto = out.File + file_proto_events_room_v1_events_proto_rawDesc = nil file_proto_events_room_v1_events_proto_goTypes = nil file_proto_events_room_v1_events_proto_depIdxs = nil } diff --git a/api/proto/events/room/v1/events.proto b/api/proto/events/room/v1/events.proto index 63f5b083..9844c61f 100644 --- a/api/proto/events/room/v1/events.proto +++ b/api/proto/events/room/v1/events.proto @@ -63,6 +63,8 @@ message RoomUserJoined { // visible_region_id 是用户进房时所在房间的国家/区域桶,统计服务不能反查 room-service。 int64 visible_region_id = 3; RoomEntryVehicleSnapshot entry_vehicle = 4; + int64 country_id = 5; + int64 region_id = 6; } // RoomUserLeft 表达用户离房成功。 @@ -154,6 +156,8 @@ message RoomGiftSent { string command_id = 8; string pool_id = 9; int64 coin_spent = 10; + int64 country_id = 11; + int64 region_id = 12; } // RoomHeatChanged 表达热度变化结果。 diff --git a/api/proto/room/v1/room.pb.go b/api/proto/room/v1/room.pb.go index 03e7d8b7..4cff54fa 100644 --- a/api/proto/room/v1/room.pb.go +++ b/api/proto/room/v1/room.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 +// protoc-gen-go v1.35.1 // protoc v7.35.0 // source: proto/room/v1/room.proto @@ -11,7 +11,6 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" - unsafe "unsafe" ) const ( @@ -24,10 +23,13 @@ const ( // RequestMeta 固定承载所有命令的调用元信息。 // room-service 用它串起幂等、追踪、路由和业务操作者身份。 type RequestMeta struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - ActorUserId int64 `protobuf:"varint,3,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + ActorUserId int64 `protobuf:"varint,3,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` // room_id 是命令路由、持久化和腾讯 IM/RTC 映射共同依赖的必填字段。 // CreateRoom 时必须满足 ^[A-Za-z0-9_-]{1,48}$。 RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` @@ -35,8 +37,6 @@ type RequestMeta struct { SessionId string `protobuf:"bytes,6,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` SentAtMs int64 `protobuf:"varint,7,opt,name=sent_at_ms,json=sentAtMs,proto3" json:"sent_at_ms,omitempty"` AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RequestMeta) Reset() { @@ -127,12 +127,13 @@ func (x *RequestMeta) GetAppCode() string { // CommandResult 统一返回命令是否真正落地,以及落地后的房间版本。 type CommandResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - Applied bool `protobuf:"varint,1,opt,name=applied,proto3" json:"applied,omitempty"` - RoomVersion int64 `protobuf:"varint,2,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Applied bool `protobuf:"varint,1,opt,name=applied,proto3" json:"applied,omitempty"` + RoomVersion int64 `protobuf:"varint,2,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *CommandResult) Reset() { @@ -188,13 +189,14 @@ func (x *CommandResult) GetServerTimeMs() int64 { // RoomUser 只表达 room-service 需要保存的房间内轻量用户态。 type RoomUser struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - JoinedAtMs int64 `protobuf:"varint,3,opt,name=joined_at_ms,json=joinedAtMs,proto3" json:"joined_at_ms,omitempty"` - LastSeenAtMs int64 `protobuf:"varint,4,opt,name=last_seen_at_ms,json=lastSeenAtMs,proto3" json:"last_seen_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + JoinedAtMs int64 `protobuf:"varint,3,opt,name=joined_at_ms,json=joinedAtMs,proto3" json:"joined_at_ms,omitempty"` + LastSeenAtMs int64 `protobuf:"varint,4,opt,name=last_seen_at_ms,json=lastSeenAtMs,proto3" json:"last_seen_at_ms,omitempty"` } func (x *RoomUser) Reset() { @@ -258,16 +260,17 @@ func (x *RoomUser) GetLastSeenAtMs() int64 { // RoomOnlineUser 是在线用户列表的展示读模型。 // role 保留进房 presence 语义;room_role 只表达房间管理员身份;is_owner 单独表达房主身份。 type RoomOnlineUser struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - RoomRole string `protobuf:"bytes,3,opt,name=room_role,json=roomRole,proto3" json:"room_role,omitempty"` - GiftValue int64 `protobuf:"varint,4,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - JoinedAtMs int64 `protobuf:"varint,5,opt,name=joined_at_ms,json=joinedAtMs,proto3" json:"joined_at_ms,omitempty"` - LastSeenAtMs int64 `protobuf:"varint,6,opt,name=last_seen_at_ms,json=lastSeenAtMs,proto3" json:"last_seen_at_ms,omitempty"` - IsOwner bool `protobuf:"varint,7,opt,name=is_owner,json=isOwner,proto3" json:"is_owner,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + RoomRole string `protobuf:"bytes,3,opt,name=room_role,json=roomRole,proto3" json:"room_role,omitempty"` + GiftValue int64 `protobuf:"varint,4,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + JoinedAtMs int64 `protobuf:"varint,5,opt,name=joined_at_ms,json=joinedAtMs,proto3" json:"joined_at_ms,omitempty"` + LastSeenAtMs int64 `protobuf:"varint,6,opt,name=last_seen_at_ms,json=lastSeenAtMs,proto3" json:"last_seen_at_ms,omitempty"` + IsOwner bool `protobuf:"varint,7,opt,name=is_owner,json=isOwner,proto3" json:"is_owner,omitempty"` } func (x *RoomOnlineUser) Reset() { @@ -351,10 +354,13 @@ func (x *RoomOnlineUser) GetIsOwner() bool { // SeatState 表达单个麦位当前占用和 RTC 发流确认状态。 type SeatState struct { - state protoimpl.MessageState `protogen:"open.v1"` - SeatNo int32 `protobuf:"varint,1,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SeatNo int32 `protobuf:"varint,1,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` // publish_state 为空表示空麦或未进入发流流程;上麦后先进入 pending_publish,确认后进入 publishing。 PublishState string `protobuf:"bytes,4,opt,name=publish_state,json=publishState,proto3" json:"publish_state,omitempty"` // mic_session_id 是单次上麦发流会话 ID;所有客户端确认或 RTC webhook 必须带回它。 @@ -371,8 +377,6 @@ type SeatState struct { SeatStatus string `protobuf:"bytes,10,opt,name=seat_status,json=seatStatus,proto3" json:"seat_status,omitempty"` // mic_heartbeat_at_ms 是当前 mic_session 最近一次服务端接受麦上心跳的 UTC epoch ms。 MicHeartbeatAtMs int64 `protobuf:"varint,11,opt,name=mic_heartbeat_at_ms,json=micHeartbeatAtMs,proto3" json:"mic_heartbeat_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *SeatState) Reset() { @@ -484,13 +488,14 @@ func (x *SeatState) GetMicHeartbeatAtMs() int64 { // RankItem 表达房间内本地礼物榜项目。 type RankItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Score int64 `protobuf:"varint,2,opt,name=score,proto3" json:"score,omitempty"` - GiftValue int64 `protobuf:"varint,3,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Score int64 `protobuf:"varint,2,opt,name=score,proto3" json:"score,omitempty"` + GiftValue int64 `protobuf:"varint,3,opt,name=gift_value,json=giftValue,proto3" json:"gift_value,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *RankItem) Reset() { @@ -553,30 +558,31 @@ func (x *RankItem) GetUpdatedAtMs() int64 { // LuckyGiftDrawResult 是 SendGift 同步返回给当前送礼用户的幸运礼物抽奖表现。 type LuckyGiftDrawResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - PoolId string `protobuf:"bytes,4,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - GiftId string `protobuf:"bytes,5,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - RuleVersion int64 `protobuf:"varint,6,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` - ExperiencePool string `protobuf:"bytes,7,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` - SelectedTierId string `protobuf:"bytes,8,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` - MultiplierPpm int64 `protobuf:"varint,9,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - BaseRewardCoins int64 `protobuf:"varint,10,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` - RoomAtmosphereRewardCoins int64 `protobuf:"varint,11,opt,name=room_atmosphere_reward_coins,json=roomAtmosphereRewardCoins,proto3" json:"room_atmosphere_reward_coins,omitempty"` - ActivitySubsidyCoins int64 `protobuf:"varint,12,opt,name=activity_subsidy_coins,json=activitySubsidyCoins,proto3" json:"activity_subsidy_coins,omitempty"` - EffectiveRewardCoins int64 `protobuf:"varint,13,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` - RewardStatus string `protobuf:"bytes,14,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` - StageFeedback bool `protobuf:"varint,15,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` - HighMultiplier bool `protobuf:"varint,16,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` - CreatedAtMs int64 `protobuf:"varint,17,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - WalletTransactionId string `protobuf:"bytes,18,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,19,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - // target_user_id 是本次幸运礼物抽奖对应的收礼用户;多目标送礼用它关联结果。 - TargetUserId int64 `protobuf:"varint,20,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + DrawId string `protobuf:"bytes,2,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + PoolId string `protobuf:"bytes,4,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + GiftId string `protobuf:"bytes,5,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + RuleVersion int64 `protobuf:"varint,6,opt,name=rule_version,json=ruleVersion,proto3" json:"rule_version,omitempty"` + ExperiencePool string `protobuf:"bytes,7,opt,name=experience_pool,json=experiencePool,proto3" json:"experience_pool,omitempty"` + SelectedTierId string `protobuf:"bytes,8,opt,name=selected_tier_id,json=selectedTierId,proto3" json:"selected_tier_id,omitempty"` + MultiplierPpm int64 `protobuf:"varint,9,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + BaseRewardCoins int64 `protobuf:"varint,10,opt,name=base_reward_coins,json=baseRewardCoins,proto3" json:"base_reward_coins,omitempty"` + RoomAtmosphereRewardCoins int64 `protobuf:"varint,11,opt,name=room_atmosphere_reward_coins,json=roomAtmosphereRewardCoins,proto3" json:"room_atmosphere_reward_coins,omitempty"` + ActivitySubsidyCoins int64 `protobuf:"varint,12,opt,name=activity_subsidy_coins,json=activitySubsidyCoins,proto3" json:"activity_subsidy_coins,omitempty"` + EffectiveRewardCoins int64 `protobuf:"varint,13,opt,name=effective_reward_coins,json=effectiveRewardCoins,proto3" json:"effective_reward_coins,omitempty"` + RewardStatus string `protobuf:"bytes,14,opt,name=reward_status,json=rewardStatus,proto3" json:"reward_status,omitempty"` + StageFeedback bool `protobuf:"varint,15,opt,name=stage_feedback,json=stageFeedback,proto3" json:"stage_feedback,omitempty"` + HighMultiplier bool `protobuf:"varint,16,opt,name=high_multiplier,json=highMultiplier,proto3" json:"high_multiplier,omitempty"` + CreatedAtMs int64 `protobuf:"varint,17,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + WalletTransactionId string `protobuf:"bytes,18,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,19,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + // target_user_id 是本次幸运礼物抽奖对应的收礼用户;多目标送礼用它关联结果。 + TargetUserId int64 `protobuf:"varint,20,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` } func (x *LuckyGiftDrawResult) Reset() { @@ -751,14 +757,15 @@ func (x *LuckyGiftDrawResult) GetTargetUserId() int64 { // RoomRocketRewardItem 是后台配置给客户端展示的火箭奖励候选项。 type RoomRocketRewardItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - RewardItemId string `protobuf:"bytes,1,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` - ResourceGroupId int64 `protobuf:"varint,2,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` - Weight int64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` - DisplayName string `protobuf:"bytes,4,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - IconUrl string `protobuf:"bytes,5,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RewardItemId string `protobuf:"bytes,1,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` + ResourceGroupId int64 `protobuf:"varint,2,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + Weight int64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` + DisplayName string `protobuf:"bytes,4,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + IconUrl string `protobuf:"bytes,5,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` } func (x *RoomRocketRewardItem) Reset() { @@ -828,7 +835,10 @@ func (x *RoomRocketRewardItem) GetIconUrl() string { // RoomRocketLevel 暴露单个等级火箭的物料、阈值和三类奖励池。 type RoomRocketLevel struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` FuelThreshold int64 `protobuf:"varint,2,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` CoverUrl string `protobuf:"bytes,3,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` @@ -838,8 +848,6 @@ type RoomRocketLevel struct { InRoomRewards []*RoomRocketRewardItem `protobuf:"bytes,7,rep,name=in_room_rewards,json=inRoomRewards,proto3" json:"in_room_rewards,omitempty"` Top1Rewards []*RoomRocketRewardItem `protobuf:"bytes,8,rep,name=top1_rewards,json=top1Rewards,proto3" json:"top1_rewards,omitempty"` IgniterRewards []*RoomRocketRewardItem `protobuf:"bytes,9,rep,name=igniter_rewards,json=igniterRewards,proto3" json:"igniter_rewards,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomRocketLevel) Reset() { @@ -937,17 +945,18 @@ func (x *RoomRocketLevel) GetIgniterRewards() []*RoomRocketRewardItem { // RoomRocketRewardGrant 是一次火箭发射后给某个用户结算出的具体奖励。 type RoomRocketRewardGrant struct { - state protoimpl.MessageState `protogen:"open.v1"` - RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RewardItemId string `protobuf:"bytes,3,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` - ResourceGroupId int64 `protobuf:"varint,4,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` - DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` - IconUrl string `protobuf:"bytes,6,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` - GrantId string `protobuf:"bytes,7,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RewardRole string `protobuf:"bytes,1,opt,name=reward_role,json=rewardRole,proto3" json:"reward_role,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RewardItemId string `protobuf:"bytes,3,opt,name=reward_item_id,json=rewardItemId,proto3" json:"reward_item_id,omitempty"` + ResourceGroupId int64 `protobuf:"varint,4,opt,name=resource_group_id,json=resourceGroupId,proto3" json:"resource_group_id,omitempty"` + DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` + IconUrl string `protobuf:"bytes,6,opt,name=icon_url,json=iconUrl,proto3" json:"icon_url,omitempty"` + GrantId string `protobuf:"bytes,7,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` } func (x *RoomRocketRewardGrant) Reset() { @@ -1038,19 +1047,20 @@ func (x *RoomRocketRewardGrant) GetStatus() string { // RoomRocketPendingLaunch 是已经点火、等待延迟发射的单枚火箭。 type RoomRocketPendingLaunch struct { - state protoimpl.MessageState `protogen:"open.v1"` - RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - FuelThreshold int64 `protobuf:"varint,3,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` - IgnitedAtMs int64 `protobuf:"varint,4,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` - LaunchAtMs int64 `protobuf:"varint,5,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` - ResetAtMs int64 `protobuf:"varint,6,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` - Top1UserId int64 `protobuf:"varint,7,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` - IgniterUserId int64 `protobuf:"varint,8,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` - ConfigVersion int64 `protobuf:"varint,9,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` - CoverUrl string `protobuf:"bytes,10,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RocketId string `protobuf:"bytes,1,opt,name=rocket_id,json=rocketId,proto3" json:"rocket_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + FuelThreshold int64 `protobuf:"varint,3,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` + IgnitedAtMs int64 `protobuf:"varint,4,opt,name=ignited_at_ms,json=ignitedAtMs,proto3" json:"ignited_at_ms,omitempty"` + LaunchAtMs int64 `protobuf:"varint,5,opt,name=launch_at_ms,json=launchAtMs,proto3" json:"launch_at_ms,omitempty"` + ResetAtMs int64 `protobuf:"varint,6,opt,name=reset_at_ms,json=resetAtMs,proto3" json:"reset_at_ms,omitempty"` + Top1UserId int64 `protobuf:"varint,7,opt,name=top1_user_id,json=top1UserId,proto3" json:"top1_user_id,omitempty"` + IgniterUserId int64 `protobuf:"varint,8,opt,name=igniter_user_id,json=igniterUserId,proto3" json:"igniter_user_id,omitempty"` + ConfigVersion int64 `protobuf:"varint,9,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` + CoverUrl string `protobuf:"bytes,10,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` } func (x *RoomRocketPendingLaunch) Reset() { @@ -1155,7 +1165,10 @@ func (x *RoomRocketPendingLaunch) GetCoverUrl() string { // RoomRocketState 是 Room Cell 持有并随快照恢复的当前火箭状态。 type RoomRocketState struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + CurrentLevel int32 `protobuf:"varint,1,opt,name=current_level,json=currentLevel,proto3" json:"current_level,omitempty"` CurrentFuel int64 `protobuf:"varint,2,opt,name=current_fuel,json=currentFuel,proto3" json:"current_fuel,omitempty"` FuelThreshold int64 `protobuf:"varint,3,opt,name=fuel_threshold,json=fuelThreshold,proto3" json:"fuel_threshold,omitempty"` @@ -1170,8 +1183,6 @@ type RoomRocketState struct { ConfigVersion int64 `protobuf:"varint,12,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` LastRewards []*RoomRocketRewardGrant `protobuf:"bytes,13,rep,name=last_rewards,json=lastRewards,proto3" json:"last_rewards,omitempty"` PendingLaunches []*RoomRocketPendingLaunch `protobuf:"bytes,14,rep,name=pending_launches,json=pendingLaunches,proto3" json:"pending_launches,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *RoomRocketState) Reset() { @@ -1304,17 +1315,18 @@ func (x *RoomRocketState) GetPendingLaunches() []*RoomRocketPendingLaunch { // RoomRocketInfo 是 App 初始化火箭 UI 的完整读模型。 type RoomRocketInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - Levels []*RoomRocketLevel `protobuf:"bytes,2,rep,name=levels,proto3" json:"levels,omitempty"` - State *RoomRocketState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` - ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - BroadcastScope string `protobuf:"bytes,5,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` - LaunchDelayMs int64 `protobuf:"varint,6,opt,name=launch_delay_ms,json=launchDelayMs,proto3" json:"launch_delay_ms,omitempty"` - BroadcastDelayMs int64 `protobuf:"varint,7,opt,name=broadcast_delay_ms,json=broadcastDelayMs,proto3" json:"broadcast_delay_ms,omitempty"` - RewardStackPolicy string `protobuf:"bytes,8,opt,name=reward_stack_policy,json=rewardStackPolicy,proto3" json:"reward_stack_policy,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Levels []*RoomRocketLevel `protobuf:"bytes,2,rep,name=levels,proto3" json:"levels,omitempty"` + State *RoomRocketState `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + BroadcastScope string `protobuf:"bytes,5,opt,name=broadcast_scope,json=broadcastScope,proto3" json:"broadcast_scope,omitempty"` + LaunchDelayMs int64 `protobuf:"varint,6,opt,name=launch_delay_ms,json=launchDelayMs,proto3" json:"launch_delay_ms,omitempty"` + BroadcastDelayMs int64 `protobuf:"varint,7,opt,name=broadcast_delay_ms,json=broadcastDelayMs,proto3" json:"broadcast_delay_ms,omitempty"` + RewardStackPolicy string `protobuf:"bytes,8,opt,name=reward_stack_policy,json=rewardStackPolicy,proto3" json:"reward_stack_policy,omitempty"` } func (x *RoomRocketInfo) Reset() { @@ -1405,15 +1417,16 @@ func (x *RoomRocketInfo) GetRewardStackPolicy() string { // RoomRocketGiftFuelRule 是后台配置的礼物燃料覆盖规则。 type RoomRocketGiftFuelRule struct { - state protoimpl.MessageState `protogen:"open.v1"` - RuleId string `protobuf:"bytes,1,opt,name=rule_id,json=ruleId,proto3" json:"rule_id,omitempty"` - GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftTypeCode string `protobuf:"bytes,3,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - MultiplierPpm int64 `protobuf:"varint,4,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` - FixedFuel int64 `protobuf:"varint,5,opt,name=fixed_fuel,json=fixedFuel,proto3" json:"fixed_fuel,omitempty"` - Excluded bool `protobuf:"varint,6,opt,name=excluded,proto3" json:"excluded,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RuleId string `protobuf:"bytes,1,opt,name=rule_id,json=ruleId,proto3" json:"rule_id,omitempty"` + GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftTypeCode string `protobuf:"bytes,3,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + MultiplierPpm int64 `protobuf:"varint,4,opt,name=multiplier_ppm,json=multiplierPpm,proto3" json:"multiplier_ppm,omitempty"` + FixedFuel int64 `protobuf:"varint,5,opt,name=fixed_fuel,json=fixedFuel,proto3" json:"fixed_fuel,omitempty"` + Excluded bool `protobuf:"varint,6,opt,name=excluded,proto3" json:"excluded,omitempty"` } func (x *RoomRocketGiftFuelRule) Reset() { @@ -1490,7 +1503,10 @@ func (x *RoomRocketGiftFuelRule) GetExcluded() bool { // AdminRoomRocketConfig 是后台管理读写的完整火箭配置。 type AdminRoomRocketConfig struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + 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"` ConfigVersion int64 `protobuf:"varint,3,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` @@ -1505,8 +1521,6 @@ type AdminRoomRocketConfig struct { UpdatedByAdminId int64 `protobuf:"varint,12,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,omitempty"` CreatedAtMs int64 `protobuf:"varint,13,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` UpdatedAtMs int64 `protobuf:"varint,14,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *AdminRoomRocketConfig) Reset() { @@ -1638,10 +1652,11 @@ func (x *AdminRoomRocketConfig) GetUpdatedAtMs() int64 { } type AdminGetRoomRocketConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` } func (x *AdminGetRoomRocketConfigRequest) Reset() { @@ -1682,11 +1697,12 @@ func (x *AdminGetRoomRocketConfigRequest) GetMeta() *RequestMeta { } type AdminGetRoomRocketConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminGetRoomRocketConfigResponse) Reset() { @@ -1734,12 +1750,13 @@ func (x *AdminGetRoomRocketConfigResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomRocketConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Config *AdminRoomRocketConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - AdminId int64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Config *AdminRoomRocketConfig `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + AdminId int64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` } func (x *AdminUpdateRoomRocketConfigRequest) Reset() { @@ -1794,11 +1811,12 @@ func (x *AdminUpdateRoomRocketConfigRequest) GetAdminId() int64 { } type AdminUpdateRoomRocketConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *AdminRoomRocketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminUpdateRoomRocketConfigResponse) Reset() { @@ -1846,13 +1864,14 @@ func (x *AdminUpdateRoomRocketConfigResponse) GetServerTimeMs() int64 { } type AdminRoomSeatConfig struct { - state protoimpl.MessageState `protogen:"open.v1"` - CandidateSeatCounts []int32 `protobuf:"varint,1,rep,packed,name=candidate_seat_counts,json=candidateSeatCounts,proto3" json:"candidate_seat_counts,omitempty"` - AllowedSeatCounts []int32 `protobuf:"varint,2,rep,packed,name=allowed_seat_counts,json=allowedSeatCounts,proto3" json:"allowed_seat_counts,omitempty"` - DefaultSeatCount int32 `protobuf:"varint,3,opt,name=default_seat_count,json=defaultSeatCount,proto3" json:"default_seat_count,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CandidateSeatCounts []int32 `protobuf:"varint,1,rep,packed,name=candidate_seat_counts,json=candidateSeatCounts,proto3" json:"candidate_seat_counts,omitempty"` + AllowedSeatCounts []int32 `protobuf:"varint,2,rep,packed,name=allowed_seat_counts,json=allowedSeatCounts,proto3" json:"allowed_seat_counts,omitempty"` + DefaultSeatCount int32 `protobuf:"varint,3,opt,name=default_seat_count,json=defaultSeatCount,proto3" json:"default_seat_count,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,4,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *AdminRoomSeatConfig) Reset() { @@ -1914,10 +1933,11 @@ func (x *AdminRoomSeatConfig) GetUpdatedAtMs() int64 { } type AdminGetRoomSeatConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` } func (x *AdminGetRoomSeatConfigRequest) Reset() { @@ -1958,11 +1978,12 @@ func (x *AdminGetRoomSeatConfigRequest) GetMeta() *RequestMeta { } type AdminGetRoomSeatConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomSeatConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *AdminRoomSeatConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminGetRoomSeatConfigResponse) Reset() { @@ -2010,12 +2031,13 @@ func (x *AdminGetRoomSeatConfigResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomSeatConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - AllowedSeatCounts []int32 `protobuf:"varint,2,rep,packed,name=allowed_seat_counts,json=allowedSeatCounts,proto3" json:"allowed_seat_counts,omitempty"` - DefaultSeatCount int32 `protobuf:"varint,3,opt,name=default_seat_count,json=defaultSeatCount,proto3" json:"default_seat_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + AllowedSeatCounts []int32 `protobuf:"varint,2,rep,packed,name=allowed_seat_counts,json=allowedSeatCounts,proto3" json:"allowed_seat_counts,omitempty"` + DefaultSeatCount int32 `protobuf:"varint,3,opt,name=default_seat_count,json=defaultSeatCount,proto3" json:"default_seat_count,omitempty"` } func (x *AdminUpdateRoomSeatConfigRequest) Reset() { @@ -2070,11 +2092,12 @@ func (x *AdminUpdateRoomSeatConfigRequest) GetDefaultSeatCount() int32 { } type AdminUpdateRoomSeatConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *AdminRoomSeatConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *AdminRoomSeatConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminUpdateRoomSeatConfigResponse) Reset() { @@ -2122,16 +2145,17 @@ func (x *AdminUpdateRoomSeatConfigResponse) GetServerTimeMs() int64 { } type AdminRoomPinRoom struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RoomShortId string `protobuf:"bytes,2,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` - CoverUrl string `protobuf:"bytes,6,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RoomShortId string `protobuf:"bytes,2,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` + CoverUrl string `protobuf:"bytes,6,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` } func (x *AdminRoomPinRoom) Reset() { @@ -2214,23 +2238,24 @@ func (x *AdminRoomPinRoom) GetStatus() string { } type AdminRoomPin struct { - state protoimpl.MessageState `protogen:"open.v1"` - Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,2,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Weight int64 `protobuf:"varint,4,opt,name=weight,proto3" json:"weight,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - PinnedAtMs int64 `protobuf:"varint,6,opt,name=pinned_at_ms,json=pinnedAtMs,proto3" json:"pinned_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,7,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - CancelledAtMs int64 `protobuf:"varint,8,opt,name=cancelled_at_ms,json=cancelledAtMs,proto3" json:"cancelled_at_ms,omitempty"` - CreatedByAdminId uint64 `protobuf:"varint,9,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"` - CancelledByAdminId uint64 `protobuf:"varint,10,opt,name=cancelled_by_admin_id,json=cancelledByAdminId,proto3" json:"cancelled_by_admin_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,12,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - Room *AdminRoomPinRoom `protobuf:"bytes,13,opt,name=room,proto3" json:"room,omitempty"` - PinType string `protobuf:"bytes,14,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,2,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Weight int64 `protobuf:"varint,4,opt,name=weight,proto3" json:"weight,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + PinnedAtMs int64 `protobuf:"varint,6,opt,name=pinned_at_ms,json=pinnedAtMs,proto3" json:"pinned_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,7,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + CancelledAtMs int64 `protobuf:"varint,8,opt,name=cancelled_at_ms,json=cancelledAtMs,proto3" json:"cancelled_at_ms,omitempty"` + CreatedByAdminId uint64 `protobuf:"varint,9,opt,name=created_by_admin_id,json=createdByAdminId,proto3" json:"created_by_admin_id,omitempty"` + CancelledByAdminId uint64 `protobuf:"varint,10,opt,name=cancelled_by_admin_id,json=cancelledByAdminId,proto3" json:"cancelled_by_admin_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,12,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + Room *AdminRoomPinRoom `protobuf:"bytes,13,opt,name=room,proto3" json:"room,omitempty"` + PinType string `protobuf:"bytes,14,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` } func (x *AdminRoomPin) Reset() { @@ -2362,16 +2387,17 @@ func (x *AdminRoomPin) GetPinType() string { } type AdminListRoomPinsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - PinType string `protobuf:"bytes,7,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + PinType string `protobuf:"bytes,7,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` } func (x *AdminListRoomPinsRequest) Reset() { @@ -2454,12 +2480,13 @@ func (x *AdminListRoomPinsRequest) GetPinType() string { } type AdminListRoomPinsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Pins []*AdminRoomPin `protobuf:"bytes,1,rep,name=pins,proto3" json:"pins,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pins []*AdminRoomPin `protobuf:"bytes,1,rep,name=pins,proto3" json:"pins,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminListRoomPinsResponse) Reset() { @@ -2514,17 +2541,18 @@ func (x *AdminListRoomPinsResponse) GetServerTimeMs() int64 { } type AdminCreateRoomPinRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Weight int64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` - DurationDays int64 `protobuf:"varint,4,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` - AdminId uint64 `protobuf:"varint,5,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` - PinnedAtMs int64 `protobuf:"varint,6,opt,name=pinned_at_ms,json=pinnedAtMs,proto3" json:"pinned_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,7,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - PinType string `protobuf:"bytes,8,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Weight int64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` + DurationDays int64 `protobuf:"varint,4,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` + AdminId uint64 `protobuf:"varint,5,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + PinnedAtMs int64 `protobuf:"varint,6,opt,name=pinned_at_ms,json=pinnedAtMs,proto3" json:"pinned_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,7,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + PinType string `protobuf:"bytes,8,opt,name=pin_type,json=pinType,proto3" json:"pin_type,omitempty"` } func (x *AdminCreateRoomPinRequest) Reset() { @@ -2614,11 +2642,12 @@ func (x *AdminCreateRoomPinRequest) GetPinType() string { } type AdminCreateRoomPinResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Pin *AdminRoomPin `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pin *AdminRoomPin `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminCreateRoomPinResponse) Reset() { @@ -2666,12 +2695,13 @@ func (x *AdminCreateRoomPinResponse) GetServerTimeMs() int64 { } type AdminCancelRoomPinRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - PinId int64 `protobuf:"varint,2,opt,name=pin_id,json=pinId,proto3" json:"pin_id,omitempty"` - AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + PinId int64 `protobuf:"varint,2,opt,name=pin_id,json=pinId,proto3" json:"pin_id,omitempty"` + AdminId uint64 `protobuf:"varint,3,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` } func (x *AdminCancelRoomPinRequest) Reset() { @@ -2726,11 +2756,12 @@ func (x *AdminCancelRoomPinRequest) GetAdminId() uint64 { } type AdminCancelRoomPinResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Pin *AdminRoomPin `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Pin *AdminRoomPin `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminCancelRoomPinResponse) Reset() { @@ -2779,14 +2810,15 @@ func (x *AdminCancelRoomPinResponse) GetServerTimeMs() int64 { // RoomBanState 表达单个房间 ban 的治理状态。 type RoomBanState struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - // expires_at_ms 为 0 表示永久 ban;非 0 表示该 UTC 毫秒后可重新进房。 - ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + // expires_at_ms 为 0 表示永久 ban;非 0 表示该 UTC 毫秒后可重新进房。 + ExpiresAtMs int64 `protobuf:"varint,4,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` } func (x *RoomBanState) Reset() { @@ -2849,32 +2881,33 @@ func (x *RoomBanState) GetExpiresAtMs() int64 { // RoomSnapshot 把 room-service 对外需要暴露的房间投影集中返回。 type RoomSnapshot struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - ChatEnabled bool `protobuf:"varint,6,opt,name=chat_enabled,json=chatEnabled,proto3" json:"chat_enabled,omitempty"` - MicSeats []*SeatState `protobuf:"bytes,7,rep,name=mic_seats,json=micSeats,proto3" json:"mic_seats,omitempty"` - OnlineUsers []*RoomUser `protobuf:"bytes,8,rep,name=online_users,json=onlineUsers,proto3" json:"online_users,omitempty"` - AdminUserIds []int64 `protobuf:"varint,9,rep,packed,name=admin_user_ids,json=adminUserIds,proto3" json:"admin_user_ids,omitempty"` - BanUserIds []int64 `protobuf:"varint,10,rep,packed,name=ban_user_ids,json=banUserIds,proto3" json:"ban_user_ids,omitempty"` - MuteUserIds []int64 `protobuf:"varint,11,rep,packed,name=mute_user_ids,json=muteUserIds,proto3" json:"mute_user_ids,omitempty"` - GiftRank []*RankItem `protobuf:"bytes,12,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` - RoomExt map[string]string `protobuf:"bytes,13,rep,name=room_ext,json=roomExt,proto3" json:"room_ext,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - Heat int64 `protobuf:"varint,14,opt,name=heat,proto3" json:"heat,omitempty"` - Version int64 `protobuf:"varint,15,opt,name=version,proto3" json:"version,omitempty"` - AppCode string `protobuf:"bytes,16,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RoomShortId string `protobuf:"bytes,17,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,18,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + Mode string `protobuf:"bytes,4,opt,name=mode,proto3" json:"mode,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + ChatEnabled bool `protobuf:"varint,6,opt,name=chat_enabled,json=chatEnabled,proto3" json:"chat_enabled,omitempty"` + MicSeats []*SeatState `protobuf:"bytes,7,rep,name=mic_seats,json=micSeats,proto3" json:"mic_seats,omitempty"` + OnlineUsers []*RoomUser `protobuf:"bytes,8,rep,name=online_users,json=onlineUsers,proto3" json:"online_users,omitempty"` + AdminUserIds []int64 `protobuf:"varint,9,rep,packed,name=admin_user_ids,json=adminUserIds,proto3" json:"admin_user_ids,omitempty"` + BanUserIds []int64 `protobuf:"varint,10,rep,packed,name=ban_user_ids,json=banUserIds,proto3" json:"ban_user_ids,omitempty"` + MuteUserIds []int64 `protobuf:"varint,11,rep,packed,name=mute_user_ids,json=muteUserIds,proto3" json:"mute_user_ids,omitempty"` + GiftRank []*RankItem `protobuf:"bytes,12,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` + RoomExt map[string]string `protobuf:"bytes,13,rep,name=room_ext,json=roomExt,proto3" json:"room_ext,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Heat int64 `protobuf:"varint,14,opt,name=heat,proto3" json:"heat,omitempty"` + Version int64 `protobuf:"varint,15,opt,name=version,proto3" json:"version,omitempty"` + AppCode string `protobuf:"bytes,16,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RoomShortId string `protobuf:"bytes,17,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,18,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` // locked 只表达房间是否需要入房密码;具体密码哈希不对外映射到 HTTP JSON。 Locked bool `protobuf:"varint,19,opt,name=locked,proto3" json:"locked,omitempty"` // rocket 是语音房火箭当前状态;配置物料通过 GetRoomRocket 单独读取,避免快照过大。 Rocket *RoomRocketState `protobuf:"bytes,20,opt,name=rocket,proto3" json:"rocket,omitempty"` // ban_states 保存 ban 的过期边界;ban_user_ids 仍只服务简单集合判断。 - BanStates []*RoomBanState `protobuf:"bytes,21,rep,name=ban_states,json=banStates,proto3" json:"ban_states,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + BanStates []*RoomBanState `protobuf:"bytes,21,rep,name=ban_states,json=banStates,proto3" json:"ban_states,omitempty"` } func (x *RoomSnapshot) Reset() { @@ -3050,15 +3083,16 @@ func (x *RoomSnapshot) GetBanStates() []*RoomBanState { // RoomBackgroundImage 是房间维度保存过的背景图素材。 // 保存列表归属于 room-service,当前生效背景仍写入 RoomSnapshot.room_ext["background_url"]。 type RoomBackgroundImage struct { - state protoimpl.MessageState `protogen:"open.v1"` - BackgroundId int64 `protobuf:"varint,1,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ImageUrl string `protobuf:"bytes,3,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - CreatedByUserId int64 `protobuf:"varint,4,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_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 + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BackgroundId int64 `protobuf:"varint,1,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ImageUrl string `protobuf:"bytes,3,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` + CreatedByUserId int64 `protobuf:"varint,4,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_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"` } func (x *RoomBackgroundImage) Reset() { @@ -3134,12 +3168,13 @@ func (x *RoomBackgroundImage) GetUpdatedAtMs() int64 { } type SaveRoomBackgroundRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ImageUrl string `protobuf:"bytes,3,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ImageUrl string `protobuf:"bytes,3,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` } func (x *SaveRoomBackgroundRequest) Reset() { @@ -3194,11 +3229,12 @@ func (x *SaveRoomBackgroundRequest) GetImageUrl() string { } type SaveRoomBackgroundResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Background *RoomBackgroundImage `protobuf:"bytes,1,opt,name=background,proto3" json:"background,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Background *RoomBackgroundImage `protobuf:"bytes,1,opt,name=background,proto3" json:"background,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *SaveRoomBackgroundResponse) Reset() { @@ -3246,12 +3282,13 @@ func (x *SaveRoomBackgroundResponse) GetServerTimeMs() int64 { } type ListRoomBackgroundsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` } func (x *ListRoomBackgroundsRequest) Reset() { @@ -3306,12 +3343,13 @@ func (x *ListRoomBackgroundsRequest) GetViewerUserId() int64 { } type ListRoomBackgroundsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + Backgrounds []*RoomBackgroundImage `protobuf:"bytes,1,rep,name=backgrounds,proto3" json:"backgrounds,omitempty"` SelectedBackgroundUrl string `protobuf:"bytes,2,opt,name=selected_background_url,json=selectedBackgroundUrl,proto3" json:"selected_background_url,omitempty"` ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *ListRoomBackgroundsResponse) Reset() { @@ -3366,11 +3404,12 @@ func (x *ListRoomBackgroundsResponse) GetServerTimeMs() int64 { } type SetRoomBackgroundRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - BackgroundId int64 `protobuf:"varint,2,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + BackgroundId int64 `protobuf:"varint,2,opt,name=background_id,json=backgroundId,proto3" json:"background_id,omitempty"` } func (x *SetRoomBackgroundRequest) Reset() { @@ -3418,12 +3457,13 @@ func (x *SetRoomBackgroundRequest) GetBackgroundId() int64 { } type SetRoomBackgroundResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - Background *RoomBackgroundImage `protobuf:"bytes,3,opt,name=background,proto3" json:"background,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + Background *RoomBackgroundImage `protobuf:"bytes,3,opt,name=background,proto3" json:"background,omitempty"` } func (x *SetRoomBackgroundResponse) Reset() { @@ -3481,8 +3521,11 @@ func (x *SetRoomBackgroundResponse) GetBackground() *RoomBackgroundImage { // 必填语义:meta.room_id、meta.command_id、meta.actor_user_id、mode、room_name 和 room_avatar。 // 同一个 meta.actor_user_id 只能作为 owner 创建一个房间;重复创建返回 Conflict。 type CreateRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` // seat_count 为空或 0 时使用后台房间配置默认值;正数必须命中后台启用座位数。 SeatCount int32 `protobuf:"varint,2,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` // mode 必须非空;当前只作为房间状态字段保存和透出。 @@ -3496,9 +3539,7 @@ type CreateRoomRequest struct { // room_description 是房间简介,只作为房间扩展资料保存,不参与 Room Cell 高频状态决策。 RoomDescription string `protobuf:"bytes,7,opt,name=room_description,json=roomDescription,proto3" json:"room_description,omitempty"` // room_short_id 是房间短 ID,首版直接等于创建者当前 default/current display_user_id。 - RoomShortId string `protobuf:"bytes,8,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + RoomShortId string `protobuf:"bytes,8,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` } func (x *CreateRoomRequest) Reset() { @@ -3589,11 +3630,12 @@ func (x *CreateRoomRequest) GetRoomShortId() string { // CreateRoomResponse 返回新建后的房间快照。 type CreateRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *CreateRoomResponse) Reset() { @@ -3643,14 +3685,15 @@ func (x *CreateRoomResponse) GetRoom() *RoomSnapshot { // UpdateRoomProfileRequest 修改房间展示资料和麦位数量。 // 该命令只允许当前在房间 presence 内的 owner 执行,座位数必须命中后台启用配置。 type UpdateRoomProfileRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomName *string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3,oneof" json:"room_name,omitempty"` - RoomAvatar *string `protobuf:"bytes,3,opt,name=room_avatar,json=roomAvatar,proto3,oneof" json:"room_avatar,omitempty"` - RoomDescription *string `protobuf:"bytes,4,opt,name=room_description,json=roomDescription,proto3,oneof" json:"room_description,omitempty"` - SeatCount *int32 `protobuf:"varint,5,opt,name=seat_count,json=seatCount,proto3,oneof" json:"seat_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomName *string `protobuf:"bytes,2,opt,name=room_name,json=roomName,proto3,oneof" json:"room_name,omitempty"` + RoomAvatar *string `protobuf:"bytes,3,opt,name=room_avatar,json=roomAvatar,proto3,oneof" json:"room_avatar,omitempty"` + RoomDescription *string `protobuf:"bytes,4,opt,name=room_description,json=roomDescription,proto3,oneof" json:"room_description,omitempty"` + SeatCount *int32 `protobuf:"varint,5,opt,name=seat_count,json=seatCount,proto3,oneof" json:"seat_count,omitempty"` } func (x *UpdateRoomProfileRequest) Reset() { @@ -3720,11 +3763,12 @@ func (x *UpdateRoomProfileRequest) GetSeatCount() int32 { // UpdateRoomProfileResponse 返回修改后的最新房间快照。 type UpdateRoomProfileResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *UpdateRoomProfileResponse) Reset() { @@ -3773,18 +3817,19 @@ func (x *UpdateRoomProfileResponse) GetRoom() *RoomSnapshot { // JoinRoomRequest 把用户 presence 接入房间业务态。 type RoomEntryVehicleSnapshot struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - AssetUrl string `protobuf:"bytes,4,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,5,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,6,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - MetadataJson string `protobuf:"bytes,7,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - EntitlementId string `protobuf:"bytes,8,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + AssetUrl string `protobuf:"bytes,4,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,5,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,6,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + MetadataJson string `protobuf:"bytes,7,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + EntitlementId string `protobuf:"bytes,8,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,9,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` } func (x *RoomEntryVehicleSnapshot) Reset() { @@ -3881,14 +3926,17 @@ func (x *RoomEntryVehicleSnapshot) GetExpiresAtMs() int64 { } type JoinRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - // password 只用于本次入房校验;room-service 不把明文写入 command log 或快照。 - Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` - EntryVehicle *RoomEntryVehicleSnapshot `protobuf:"bytes,4,opt,name=entry_vehicle,json=entryVehicle,proto3" json:"entry_vehicle,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + // password 只用于本次入房校验;room-service 不把明文写入 command log 或快照。 + Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` + EntryVehicle *RoomEntryVehicleSnapshot `protobuf:"bytes,4,opt,name=entry_vehicle,json=entryVehicle,proto3" json:"entry_vehicle,omitempty"` + ActorCountryId int64 `protobuf:"varint,5,opt,name=actor_country_id,json=actorCountryId,proto3" json:"actor_country_id,omitempty"` + ActorRegionId int64 `protobuf:"varint,6,opt,name=actor_region_id,json=actorRegionId,proto3" json:"actor_region_id,omitempty"` } func (x *JoinRoomRequest) Reset() { @@ -3949,14 +3997,29 @@ func (x *JoinRoomRequest) GetEntryVehicle() *RoomEntryVehicleSnapshot { return nil } +func (x *JoinRoomRequest) GetActorCountryId() int64 { + if x != nil { + return x.ActorCountryId + } + return 0 +} + +func (x *JoinRoomRequest) GetActorRegionId() int64 { + if x != nil { + return x.ActorRegionId + } + return 0 +} + // JoinRoomResponse 返回加入后的房间快照。 type JoinRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - User *RoomUser `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + User *RoomUser `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *JoinRoomResponse) Reset() { @@ -4013,10 +4076,11 @@ func (x *JoinRoomResponse) GetRoom() *RoomSnapshot { // RoomHeartbeatRequest 显式刷新已经存在的房间业务 presence。 // 它不能替代 JoinRoom;用户不在房间时必须拒绝,避免心跳把已离开的用户重新加入房间。 type RoomHeartbeatRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` } func (x *RoomHeartbeatRequest) Reset() { @@ -4058,12 +4122,13 @@ func (x *RoomHeartbeatRequest) GetMeta() *RequestMeta { // RoomHeartbeatResponse 返回刷新后的用户 presence 和房间快照。 type RoomHeartbeatResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - User *RoomUser `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + User *RoomUser `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *RoomHeartbeatResponse) Reset() { @@ -4119,10 +4184,11 @@ func (x *RoomHeartbeatResponse) GetRoom() *RoomSnapshot { // LeaveRoomRequest 把用户从房间 presence 移出。 type LeaveRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` } func (x *LeaveRoomRequest) Reset() { @@ -4164,11 +4230,12 @@ func (x *LeaveRoomRequest) GetMeta() *RequestMeta { // LeaveRoomResponse 返回离房后的房间快照。 type LeaveRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *LeaveRoomResponse) Reset() { @@ -4217,11 +4284,12 @@ func (x *LeaveRoomResponse) GetRoom() *RoomSnapshot { // CloseRoomRequest 关闭房间并清理业务 presence 和麦位。 type CloseRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *CloseRoomRequest) Reset() { @@ -4270,11 +4338,12 @@ func (x *CloseRoomRequest) GetReason() string { // CloseRoomResponse 返回关闭后的房间快照。 type CloseRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *CloseRoomResponse) Reset() { @@ -4323,28 +4392,29 @@ func (x *CloseRoomResponse) GetRoom() *RoomSnapshot { // AdminRoomListItem 是后台房间管理卡片;它来自 room-service owner 读模型,不允许后台直连房间库。 type AdminRoomListItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RoomShortId string `protobuf:"bytes,2,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` - CoverUrl string `protobuf:"bytes,6,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Mode string `protobuf:"bytes,7,opt,name=mode,proto3" json:"mode,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - CloseReason string `protobuf:"bytes,9,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` - ClosedByAdminId uint64 `protobuf:"varint,10,opt,name=closed_by_admin_id,json=closedByAdminId,proto3" json:"closed_by_admin_id,omitempty"` - ClosedByAdminName string `protobuf:"bytes,11,opt,name=closed_by_admin_name,json=closedByAdminName,proto3" json:"closed_by_admin_name,omitempty"` - ClosedAtMs int64 `protobuf:"varint,12,opt,name=closed_at_ms,json=closedAtMs,proto3" json:"closed_at_ms,omitempty"` - Heat int64 `protobuf:"varint,13,opt,name=heat,proto3" json:"heat,omitempty"` - OnlineCount int32 `protobuf:"varint,14,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` - SeatCount int32 `protobuf:"varint,15,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` - OccupiedSeatCount int32 `protobuf:"varint,16,opt,name=occupied_seat_count,json=occupiedSeatCount,proto3" json:"occupied_seat_count,omitempty"` - SortScore int64 `protobuf:"varint,17,opt,name=sort_score,json=sortScore,proto3" json:"sort_score,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 + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RoomShortId string `protobuf:"bytes,2,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,4,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` + CoverUrl string `protobuf:"bytes,6,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` + Mode string `protobuf:"bytes,7,opt,name=mode,proto3" json:"mode,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + CloseReason string `protobuf:"bytes,9,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` + ClosedByAdminId uint64 `protobuf:"varint,10,opt,name=closed_by_admin_id,json=closedByAdminId,proto3" json:"closed_by_admin_id,omitempty"` + ClosedByAdminName string `protobuf:"bytes,11,opt,name=closed_by_admin_name,json=closedByAdminName,proto3" json:"closed_by_admin_name,omitempty"` + ClosedAtMs int64 `protobuf:"varint,12,opt,name=closed_at_ms,json=closedAtMs,proto3" json:"closed_at_ms,omitempty"` + Heat int64 `protobuf:"varint,13,opt,name=heat,proto3" json:"heat,omitempty"` + OnlineCount int32 `protobuf:"varint,14,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` + SeatCount int32 `protobuf:"varint,15,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + OccupiedSeatCount int32 `protobuf:"varint,16,opt,name=occupied_seat_count,json=occupiedSeatCount,proto3" json:"occupied_seat_count,omitempty"` + SortScore int64 `protobuf:"varint,17,opt,name=sort_score,json=sortScore,proto3" json:"sort_score,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"` } func (x *AdminRoomListItem) Reset() { @@ -4511,18 +4581,19 @@ func (x *AdminRoomListItem) GetUpdatedAtMs() int64 { } type AdminListRoomsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - SortBy string `protobuf:"bytes,7,opt,name=sort_by,json=sortBy,proto3" json:"sort_by,omitempty"` - SortDirection string `protobuf:"bytes,8,opt,name=sort_direction,json=sortDirection,proto3" json:"sort_direction,omitempty"` - OwnerUserId int64 `protobuf:"varint,9,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Page int32 `protobuf:"varint,2,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,3,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + VisibleRegionId int64 `protobuf:"varint,6,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + SortBy string `protobuf:"bytes,7,opt,name=sort_by,json=sortBy,proto3" json:"sort_by,omitempty"` + SortDirection string `protobuf:"bytes,8,opt,name=sort_direction,json=sortDirection,proto3" json:"sort_direction,omitempty"` + OwnerUserId int64 `protobuf:"varint,9,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` } func (x *AdminListRoomsRequest) Reset() { @@ -4619,12 +4690,13 @@ func (x *AdminListRoomsRequest) GetOwnerUserId() int64 { } type AdminListRoomsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Rooms []*AdminRoomListItem `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rooms []*AdminRoomListItem `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminListRoomsResponse) Reset() { @@ -4679,11 +4751,12 @@ func (x *AdminListRoomsResponse) GetServerTimeMs() int64 { } type AdminGetRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` } func (x *AdminGetRoomRequest) Reset() { @@ -4731,11 +4804,12 @@ func (x *AdminGetRoomRequest) GetRoomId() string { } type AdminGetRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Room *AdminRoomListItem `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Room *AdminRoomListItem `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *AdminGetRoomResponse) Reset() { @@ -4783,19 +4857,20 @@ func (x *AdminGetRoomResponse) GetServerTimeMs() int64 { } type AdminUpdateRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` - CoverUrl *string `protobuf:"bytes,3,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` - Description *string `protobuf:"bytes,4,opt,name=description,proto3,oneof" json:"description,omitempty"` - Mode *string `protobuf:"bytes,5,opt,name=mode,proto3,oneof" json:"mode,omitempty"` - Status *string `protobuf:"bytes,6,opt,name=status,proto3,oneof" json:"status,omitempty"` - VisibleRegionId *int64 `protobuf:"varint,7,opt,name=visible_region_id,json=visibleRegionId,proto3,oneof" json:"visible_region_id,omitempty"` - CloseReason string `protobuf:"bytes,8,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` - AdminId uint64 `protobuf:"varint,9,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` - AdminName string `protobuf:"bytes,10,opt,name=admin_name,json=adminName,proto3" json:"admin_name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Title *string `protobuf:"bytes,2,opt,name=title,proto3,oneof" json:"title,omitempty"` + CoverUrl *string `protobuf:"bytes,3,opt,name=cover_url,json=coverUrl,proto3,oneof" json:"cover_url,omitempty"` + Description *string `protobuf:"bytes,4,opt,name=description,proto3,oneof" json:"description,omitempty"` + Mode *string `protobuf:"bytes,5,opt,name=mode,proto3,oneof" json:"mode,omitempty"` + Status *string `protobuf:"bytes,6,opt,name=status,proto3,oneof" json:"status,omitempty"` + VisibleRegionId *int64 `protobuf:"varint,7,opt,name=visible_region_id,json=visibleRegionId,proto3,oneof" json:"visible_region_id,omitempty"` + CloseReason string `protobuf:"bytes,8,opt,name=close_reason,json=closeReason,proto3" json:"close_reason,omitempty"` + AdminId uint64 `protobuf:"varint,9,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + AdminName string `protobuf:"bytes,10,opt,name=admin_name,json=adminName,proto3" json:"admin_name,omitempty"` } func (x *AdminUpdateRoomRequest) Reset() { @@ -4899,11 +4974,12 @@ func (x *AdminUpdateRoomRequest) GetAdminName() string { } type AdminUpdateRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *AdminUpdateRoomResponse) Reset() { @@ -4951,12 +5027,13 @@ func (x *AdminUpdateRoomResponse) GetRoom() *RoomSnapshot { } type AdminDeleteRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - AdminId uint64 `protobuf:"varint,2,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` - AdminName string `protobuf:"bytes,3,opt,name=admin_name,json=adminName,proto3" json:"admin_name,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + AdminId uint64 `protobuf:"varint,2,opt,name=admin_id,json=adminId,proto3" json:"admin_id,omitempty"` + AdminName string `protobuf:"bytes,3,opt,name=admin_name,json=adminName,proto3" json:"admin_name,omitempty"` } func (x *AdminDeleteRoomRequest) Reset() { @@ -5011,11 +5088,12 @@ func (x *AdminDeleteRoomRequest) GetAdminName() string { } type AdminDeleteRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *AdminDeleteRoomResponse) Reset() { @@ -5064,11 +5142,12 @@ func (x *AdminDeleteRoomResponse) GetRoom() *RoomSnapshot { // MicUpRequest 申请把用户放到指定麦位。 type MicUpRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` } func (x *MicUpRequest) Reset() { @@ -5117,14 +5196,15 @@ func (x *MicUpRequest) GetSeatNo() int32 { // MicUpResponse 返回最新房间快照与目标麦位。 type MicUpResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - MicSessionId string `protobuf:"bytes,4,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` - PublishDeadlineMs int64 `protobuf:"varint,5,opt,name=publish_deadline_ms,json=publishDeadlineMs,proto3" json:"publish_deadline_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` + MicSessionId string `protobuf:"bytes,4,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` + PublishDeadlineMs int64 `protobuf:"varint,5,opt,name=publish_deadline_ms,json=publishDeadlineMs,proto3" json:"publish_deadline_ms,omitempty"` } func (x *MicUpResponse) Reset() { @@ -5194,13 +5274,14 @@ func (x *MicUpResponse) GetPublishDeadlineMs() int64 { // MicDownRequest 把用户从当前麦位移下。 type MicDownRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - // reason 为空表示主动下麦;系统自动释放麦位时会写入稳定原因,例如 publish_timeout。 - Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + // reason 为空表示主动下麦;系统自动释放麦位时会写入稳定原因,例如 publish_timeout。 + Reason string `protobuf:"bytes,3,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *MicDownRequest) Reset() { @@ -5256,12 +5337,13 @@ func (x *MicDownRequest) GetReason() string { // MicDownResponse 返回最新房间快照与目标麦位。 type MicDownResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *MicDownResponse) Reset() { @@ -5317,12 +5399,13 @@ func (x *MicDownResponse) GetRoom() *RoomSnapshot { // ChangeMicSeatRequest 直接调整指定用户所在麦位。 type ChangeMicSeatRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - SeatNo int32 `protobuf:"varint,3,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + SeatNo int32 `protobuf:"varint,3,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` } func (x *ChangeMicSeatRequest) Reset() { @@ -5378,11 +5461,12 @@ func (x *ChangeMicSeatRequest) GetSeatNo() int32 { // ChangeMicSeatResponse 返回变更后的房间快照。 type ChangeMicSeatResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *ChangeMicSeatResponse) Reset() { @@ -5432,16 +5516,17 @@ func (x *ChangeMicSeatResponse) GetRoom() *RoomSnapshot { // ConfirmMicPublishingRequest 确认当前 mic_session 已经在 RTC 侧成功发布音频。 // 客户端 SDK 回调和后续 RTC webhook 都必须带 mic_session_id、room_version 和 event_time_ms。 type ConfirmMicPublishingRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - // target_user_id 为空时默认确认 actor_user_id;RTC webhook 入口可显式指定目标用户。 - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - MicSessionId string `protobuf:"bytes,3,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` - RoomVersion int64 `protobuf:"varint,4,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - EventTimeMs int64 `protobuf:"varint,5,opt,name=event_time_ms,json=eventTimeMs,proto3" json:"event_time_ms,omitempty"` - Source string `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + // target_user_id 为空时默认确认 actor_user_id;RTC webhook 入口可显式指定目标用户。 + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + MicSessionId string `protobuf:"bytes,3,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` + RoomVersion int64 `protobuf:"varint,4,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` + EventTimeMs int64 `protobuf:"varint,5,opt,name=event_time_ms,json=eventTimeMs,proto3" json:"event_time_ms,omitempty"` + Source string `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` } func (x *ConfirmMicPublishingRequest) Reset() { @@ -5518,12 +5603,13 @@ func (x *ConfirmMicPublishingRequest) GetSource() string { // ConfirmMicPublishingResponse 返回确认后的最新房间快照。 type ConfirmMicPublishingResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *ConfirmMicPublishingResponse) Reset() { @@ -5579,14 +5665,15 @@ func (x *ConfirmMicPublishingResponse) GetRoom() *RoomSnapshot { // MicHeartbeatRequest 刷新当前 publishing 麦位会话的服务端麦上心跳。 type MicHeartbeatRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` // target_user_id 为空时默认刷新 actor_user_id 自己的麦上会话。 TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` // mic_session_id 必须匹配当前麦位上的会话,避免旧心跳续住新会话。 - MicSessionId string `protobuf:"bytes,3,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + MicSessionId string `protobuf:"bytes,3,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` } func (x *MicHeartbeatRequest) Reset() { @@ -5642,13 +5729,14 @@ func (x *MicHeartbeatRequest) GetMicSessionId() string { // MicHeartbeatResponse 返回刷新后的麦位和房间快照。 type MicHeartbeatResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - MicHeartbeatAtMs int64 `protobuf:"varint,4,opt,name=mic_heartbeat_at_ms,json=micHeartbeatAtMs,proto3" json:"mic_heartbeat_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` + MicHeartbeatAtMs int64 `protobuf:"varint,4,opt,name=mic_heartbeat_at_ms,json=micHeartbeatAtMs,proto3" json:"mic_heartbeat_at_ms,omitempty"` } func (x *MicHeartbeatResponse) Reset() { @@ -5711,13 +5799,14 @@ func (x *MicHeartbeatResponse) GetMicHeartbeatAtMs() int64 { // SetMicMuteRequest 修改麦位上的服务端可见静音态。 type SetMicMuteRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - // target_user_id 为空时默认修改 actor_user_id 自己的麦克风静音态。 - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + // target_user_id 为空时默认修改 actor_user_id 自己的麦克风静音态。 + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` } func (x *SetMicMuteRequest) Reset() { @@ -5773,12 +5862,13 @@ func (x *SetMicMuteRequest) GetMuted() bool { // SetMicMuteResponse 返回静音态变更后的最新房间快照。 type SetMicMuteResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *SetMicMuteResponse) Reset() { @@ -5835,16 +5925,17 @@ func (x *SetMicMuteResponse) GetRoom() *RoomSnapshot { // ApplyRTCEventRequest 把可信 RTC 服务端回调转换成 Room Cell 命令。 // event_type 当前只接受 audio_started、audio_stopped、room_exited。 type ApplyRTCEventRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` - EventTimeMs int64 `protobuf:"varint,4,opt,name=event_time_ms,json=eventTimeMs,proto3" json:"event_time_ms,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - Source string `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` - ExternalEventId string `protobuf:"bytes,7,opt,name=external_event_id,json=externalEventId,proto3" json:"external_event_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + EventType string `protobuf:"bytes,3,opt,name=event_type,json=eventType,proto3" json:"event_type,omitempty"` + EventTimeMs int64 `protobuf:"varint,4,opt,name=event_time_ms,json=eventTimeMs,proto3" json:"event_time_ms,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + Source string `protobuf:"bytes,6,opt,name=source,proto3" json:"source,omitempty"` + ExternalEventId string `protobuf:"bytes,7,opt,name=external_event_id,json=externalEventId,proto3" json:"external_event_id,omitempty"` } func (x *ApplyRTCEventRequest) Reset() { @@ -5928,12 +6019,13 @@ func (x *ApplyRTCEventRequest) GetExternalEventId() string { // ApplyRTCEventResponse 返回 RTC 事件落房间状态后的快照。 type ApplyRTCEventResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` } func (x *ApplyRTCEventResponse) Reset() { @@ -5989,12 +6081,13 @@ func (x *ApplyRTCEventResponse) GetRoom() *RoomSnapshot { // SetMicSeatLockRequest 锁定或解锁指定麦位。 type SetMicSeatLockRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` - Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + SeatNo int32 `protobuf:"varint,2,opt,name=seat_no,json=seatNo,proto3" json:"seat_no,omitempty"` + Locked bool `protobuf:"varint,3,opt,name=locked,proto3" json:"locked,omitempty"` } func (x *SetMicSeatLockRequest) Reset() { @@ -6050,11 +6143,12 @@ func (x *SetMicSeatLockRequest) GetLocked() bool { // SetMicSeatLockResponse 返回锁麦后的最新房间快照。 type SetMicSeatLockResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *SetMicSeatLockResponse) Reset() { @@ -6103,11 +6197,12 @@ func (x *SetMicSeatLockResponse) GetRoom() *RoomSnapshot { // SetChatEnabledRequest 开启或关闭房间公屏。 type SetChatEnabledRequest 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"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"` } func (x *SetChatEnabledRequest) Reset() { @@ -6156,11 +6251,12 @@ func (x *SetChatEnabledRequest) GetEnabled() bool { // SetChatEnabledResponse 返回聊天开关变更后的最新房间快照。 type SetChatEnabledResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *SetChatEnabledResponse) Reset() { @@ -6210,12 +6306,13 @@ func (x *SetChatEnabledResponse) GetRoom() *RoomSnapshot { // SetRoomPasswordRequest 设置或清空房间入房密码。 // locked=true 时 password 必须非空;locked=false 表示清空密码并解除锁房。 type SetRoomPasswordRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` - Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Locked bool `protobuf:"varint,2,opt,name=locked,proto3" json:"locked,omitempty"` + Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` } func (x *SetRoomPasswordRequest) Reset() { @@ -6271,11 +6368,12 @@ func (x *SetRoomPasswordRequest) GetPassword() string { // SetRoomPasswordResponse 返回锁房状态变更后的最新房间快照。 type SetRoomPasswordResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *SetRoomPasswordResponse) Reset() { @@ -6324,12 +6422,13 @@ func (x *SetRoomPasswordResponse) GetRoom() *RoomSnapshot { // SetRoomAdminRequest 添加或移除房间管理员。 type SetRoomAdminRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` } func (x *SetRoomAdminRequest) Reset() { @@ -6385,11 +6484,12 @@ func (x *SetRoomAdminRequest) GetEnabled() bool { // SetRoomAdminResponse 返回管理员集合变更后的最新房间快照。 type SetRoomAdminResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *SetRoomAdminResponse) Reset() { @@ -6438,12 +6538,13 @@ func (x *SetRoomAdminResponse) GetRoom() *RoomSnapshot { // MuteUserRequest 修改房间内禁言态。 type MuteUserRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Muted bool `protobuf:"varint,3,opt,name=muted,proto3" json:"muted,omitempty"` } func (x *MuteUserRequest) Reset() { @@ -6499,11 +6600,12 @@ func (x *MuteUserRequest) GetMuted() bool { // MuteUserResponse 返回最新房间快照。 type MuteUserResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *MuteUserResponse) Reset() { @@ -6552,13 +6654,14 @@ func (x *MuteUserResponse) GetRoom() *RoomSnapshot { // KickUserRequest 把指定用户踢出房间。 type KickUserRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - // duration_ms 为 0 表示永久 ban;大于 0 表示从服务端当前 UTC 时间起禁止进房的时长。 - DurationMs int64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + // duration_ms 为 0 表示永久 ban;大于 0 表示从服务端当前 UTC 时间起禁止进房的时长。 + DurationMs int64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` } func (x *KickUserRequest) Reset() { @@ -6614,15 +6717,16 @@ func (x *KickUserRequest) GetDurationMs() int64 { // KickUserResponse 返回最新房间快照。 type KickUserResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` // rtc_kicked 表示 room-service 已通过 TRTC 服务端接口移除目标用户;失败不回滚房间踢人事实。 RtcKicked bool `protobuf:"varint,3,opt,name=rtc_kicked,json=rtcKicked,proto3" json:"rtc_kicked,omitempty"` // rtc_kick_error 仅用于调用方排障和告警,客户端展示仍以统一错误码和房间状态为准。 - RtcKickError string `protobuf:"bytes,4,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + RtcKickError string `protobuf:"bytes,4,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` } func (x *KickUserResponse) Reset() { @@ -6685,11 +6789,12 @@ func (x *KickUserResponse) GetRtcKickError() string { // UnbanUserRequest 解除房间内 ban,用户仍需重新 JoinRoom。 type UnbanUserRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` } func (x *UnbanUserRequest) Reset() { @@ -6738,11 +6843,12 @@ func (x *UnbanUserRequest) GetTargetUserId() int64 { // UnbanUserResponse 返回解封后的最新房间快照。 type UnbanUserResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` } func (x *UnbanUserResponse) Reset() { @@ -6792,15 +6898,16 @@ func (x *UnbanUserResponse) GetRoom() *RoomSnapshot { // SystemEvictUserRequest 是平台级封禁、风控或后台治理触发的系统驱逐入口。 // 该命令仍由 Room Cell 修改房间状态;调用方不能直接写房间 presence 或麦位。 type SystemEvictUserRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - OperatorUserId int64 `protobuf:"varint,3,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` - // ban_from_room 为 true 时把用户加入当前房间 ban 集合,防止同一房间恢复入口重新进入。 - BanFromRoom bool `protobuf:"varint,5,opt,name=ban_from_room,json=banFromRoom,proto3" json:"ban_from_room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + OperatorUserId int64 `protobuf:"varint,3,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` + // ban_from_room 为 true 时把用户加入当前房间 ban 集合,防止同一房间恢复入口重新进入。 + BanFromRoom bool `protobuf:"varint,5,opt,name=ban_from_room,json=banFromRoom,proto3" json:"ban_from_room,omitempty"` } func (x *SystemEvictUserRequest) Reset() { @@ -6870,15 +6977,16 @@ func (x *SystemEvictUserRequest) GetBanFromRoom() bool { // SystemEvictUserResponse 返回系统驱逐的房间状态和外部 RTC 副作用结果。 type SystemEvictUserResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - HadCurrentRoom bool `protobuf:"varint,1,opt,name=had_current_room,json=hadCurrentRoom,proto3" json:"had_current_room,omitempty"` - Result *CommandResult `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` - RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RtcKicked bool `protobuf:"varint,5,opt,name=rtc_kicked,json=rtcKicked,proto3" json:"rtc_kicked,omitempty"` - RtcKickError string `protobuf:"bytes,6,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HadCurrentRoom bool `protobuf:"varint,1,opt,name=had_current_room,json=hadCurrentRoom,proto3" json:"had_current_room,omitempty"` + Result *CommandResult `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,3,opt,name=room,proto3" json:"room,omitempty"` + RoomId string `protobuf:"bytes,4,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RtcKicked bool `protobuf:"varint,5,opt,name=rtc_kicked,json=rtcKicked,proto3" json:"rtc_kicked,omitempty"` + RtcKickError string `protobuf:"bytes,6,opt,name=rtc_kick_error,json=rtcKickError,proto3" json:"rtc_kick_error,omitempty"` } func (x *SystemEvictUserResponse) Reset() { @@ -6955,8 +7063,11 @@ func (x *SystemEvictUserResponse) GetRtcKickError() string { // SendGiftRequest 是首版房间内最重要的变现命令。 type SendGiftRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` // target_user_id 是兼容旧客户端的单目标字段;新客户端优先使用 target_user_ids。 TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` @@ -6973,8 +7084,8 @@ type SendGiftRequest struct { TargetAgencyOwnerUserId int64 `protobuf:"varint,10,opt,name=target_agency_owner_user_id,json=targetAgencyOwnerUserId,proto3" json:"target_agency_owner_user_id,omitempty"` // sender_region_id 是 gateway 从 user-service 当前送礼用户资料注入的区域,用于 wallet 匹配礼物钻石比例。 SenderRegionId int64 `protobuf:"varint,11,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // sender_country_id 是 gateway 从 user-service 当前送礼用户资料注入的真实国家,用于统计国家维度。 + SenderCountryId int64 `protobuf:"varint,12,opt,name=sender_country_id,json=senderCountryId,proto3" json:"sender_country_id,omitempty"` } func (x *SendGiftRequest) Reset() { @@ -7084,21 +7195,29 @@ func (x *SendGiftRequest) GetSenderRegionId() int64 { return 0 } +func (x *SendGiftRequest) GetSenderCountryId() int64 { + if x != nil { + return x.SenderCountryId + } + return 0 +} + // SendGiftResponse 返回扣费成功并落到房间后的状态结果。 type SendGiftResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` - BillingReceiptId string `protobuf:"bytes,2,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - RoomHeat int64 `protobuf:"varint,3,opt,name=room_heat,json=roomHeat,proto3" json:"room_heat,omitempty"` - GiftRank []*RankItem `protobuf:"bytes,4,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` - Room *RoomSnapshot `protobuf:"bytes,5,opt,name=room,proto3" json:"room,omitempty"` - Rocket *RoomRocketState `protobuf:"bytes,6,opt,name=rocket,proto3" json:"rocket,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Result *CommandResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` + BillingReceiptId string `protobuf:"bytes,2,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + RoomHeat int64 `protobuf:"varint,3,opt,name=room_heat,json=roomHeat,proto3" json:"room_heat,omitempty"` + GiftRank []*RankItem `protobuf:"bytes,4,rep,name=gift_rank,json=giftRank,proto3" json:"gift_rank,omitempty"` + Room *RoomSnapshot `protobuf:"bytes,5,opt,name=room,proto3" json:"room,omitempty"` + Rocket *RoomRocketState `protobuf:"bytes,6,opt,name=rocket,proto3" json:"rocket,omitempty"` // lucky_gift 是本次送礼的聚合幸运礼物结果;多目标时倍率和返奖金额按所有目标累加。 LuckyGift *LuckyGiftDrawResult `protobuf:"bytes,7,opt,name=lucky_gift,json=luckyGift,proto3" json:"lucky_gift,omitempty"` // lucky_gifts 是每个收礼目标的独立抽奖结果;多目标客户端用 target_user_id 对齐明细表现。 - LuckyGifts []*LuckyGiftDrawResult `protobuf:"bytes,8,rep,name=lucky_gifts,json=luckyGifts,proto3" json:"lucky_gifts,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + LuckyGifts []*LuckyGiftDrawResult `protobuf:"bytes,8,rep,name=lucky_gifts,json=luckyGifts,proto3" json:"lucky_gifts,omitempty"` } func (x *SendGiftResponse) Reset() { @@ -7189,12 +7308,13 @@ func (x *SendGiftResponse) GetLuckyGifts() []*LuckyGiftDrawResult { // CheckSpeakPermissionRequest 让腾讯云 IM 发言回调或 gateway 在公屏前同步问房间业务态。 type CheckSpeakPermissionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - AppCode string `protobuf:"bytes,3,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + AppCode string `protobuf:"bytes,3,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *CheckSpeakPermissionRequest) Reset() { @@ -7250,12 +7370,13 @@ func (x *CheckSpeakPermissionRequest) GetAppCode() string { // CheckSpeakPermissionResponse 返回当前用户是否允许发言。 type CheckSpeakPermissionResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` - RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Allowed bool `protobuf:"varint,1,opt,name=allowed,proto3" json:"allowed,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` } func (x *CheckSpeakPermissionResponse) Reset() { @@ -7311,14 +7432,15 @@ func (x *CheckSpeakPermissionResponse) GetRoomVersion() int64 { // VerifyRoomPresenceRequest 让外部 IM 入口在进群前确认用户业务上仍在房间内。 type VerifyRoomPresenceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` - RequestId string `protobuf:"bytes,4,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SessionId string `protobuf:"bytes,3,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + RequestId string `protobuf:"bytes,4,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *VerifyRoomPresenceRequest) Reset() { @@ -7388,12 +7510,13 @@ func (x *VerifyRoomPresenceRequest) GetAppCode() string { // VerifyRoomPresenceResponse 返回用户是否仍然属于该房间。 type VerifyRoomPresenceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Present bool `protobuf:"varint,1,opt,name=present,proto3" json:"present,omitempty"` - Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` - RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Present bool `protobuf:"varint,1,opt,name=present,proto3" json:"present,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` + RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` } func (x *VerifyRoomPresenceResponse) Reset() { @@ -7450,16 +7573,17 @@ func (x *VerifyRoomPresenceResponse) GetRoomVersion() int64 { // ListRoomsRequest 查询当前用户所在区域可见的房间列表。 // visible_region_id 必须来自 gateway 对 user-service 的 GetUser 结果,客户端不能直接提交。 type ListRoomsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ViewerUserId int64 `protobuf:"varint,2,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - Tab string `protobuf:"bytes,4,opt,name=tab,proto3" json:"tab,omitempty"` - Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"` - Limit int32 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"` - Query string `protobuf:"bytes,7,opt,name=query,proto3" json:"query,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ViewerUserId int64 `protobuf:"varint,2,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + Tab string `protobuf:"bytes,4,opt,name=tab,proto3" json:"tab,omitempty"` + Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"` + Limit int32 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"` + Query string `protobuf:"bytes,7,opt,name=query,proto3" json:"query,omitempty"` } func (x *ListRoomsRequest) Reset() { @@ -7544,18 +7668,19 @@ func (x *ListRoomsRequest) GetQuery() string { // ListRoomFeedsRequest 查询 Mine 页 visited/friend/following/followed 房间流。 // 它和公共房间发现列表分离,避免把用户关系流误建模成房间全集过滤。 type ListRoomFeedsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - ViewerUserId int64 `protobuf:"varint,2,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - Tab string `protobuf:"bytes,4,opt,name=tab,proto3" json:"tab,omitempty"` - Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"` - Limit int32 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"` - Query string `protobuf:"bytes,7,opt,name=query,proto3" json:"query,omitempty"` - // related_users 只用于 friend/following;关系事实由 gateway 从 user-service 读取后传入。 - RelatedUsers []*RoomFeedRelatedUser `protobuf:"bytes,8,rep,name=related_users,json=relatedUsers,proto3" json:"related_users,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + ViewerUserId int64 `protobuf:"varint,2,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` + VisibleRegionId int64 `protobuf:"varint,3,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + Tab string `protobuf:"bytes,4,opt,name=tab,proto3" json:"tab,omitempty"` + Cursor string `protobuf:"bytes,5,opt,name=cursor,proto3" json:"cursor,omitempty"` + Limit int32 `protobuf:"varint,6,opt,name=limit,proto3" json:"limit,omitempty"` + Query string `protobuf:"bytes,7,opt,name=query,proto3" json:"query,omitempty"` + // related_users 只用于 friend/following;关系事实由 gateway 从 user-service 读取后传入。 + RelatedUsers []*RoomFeedRelatedUser `protobuf:"bytes,8,rep,name=related_users,json=relatedUsers,proto3" json:"related_users,omitempty"` } func (x *ListRoomFeedsRequest) Reset() { @@ -7646,13 +7771,14 @@ func (x *ListRoomFeedsRequest) GetRelatedUsers() []*RoomFeedRelatedUser { // ListRoomGiftLeaderboardRequest 查询当前 UTC 周期内的房间金币消耗榜。 type ListRoomGiftLeaderboardRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - Period string `protobuf:"bytes,2,opt,name=period,proto3" json:"period,omitempty"` - Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + Period string `protobuf:"bytes,2,opt,name=period,proto3" json:"period,omitempty"` + Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListRoomGiftLeaderboardRequest) Reset() { @@ -7715,11 +7841,12 @@ func (x *ListRoomGiftLeaderboardRequest) GetPageSize() int32 { // RoomFeedRelatedUser 是 Mine 关系房间流的排序输入,不让 room-service 持有好友/关注事实。 type RoomFeedRelatedUser struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RelationUpdatedAtMs int64 `protobuf:"varint,2,opt,name=relation_updated_at_ms,json=relationUpdatedAtMs,proto3" json:"relation_updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RelationUpdatedAtMs int64 `protobuf:"varint,2,opt,name=relation_updated_at_ms,json=relationUpdatedAtMs,proto3" json:"relation_updated_at_ms,omitempty"` } func (x *RoomFeedRelatedUser) Reset() { @@ -7768,23 +7895,24 @@ func (x *RoomFeedRelatedUser) GetRelationUpdatedAtMs() int64 { // RoomListItem 是房间发现页卡片读模型,不承载完整 Room Cell 状态。 type RoomListItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - Title string `protobuf:"bytes,4,opt,name=title,proto3" json:"title,omitempty"` - CoverUrl string `protobuf:"bytes,5,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` - Mode string `protobuf:"bytes,6,opt,name=mode,proto3" json:"mode,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - Heat int64 `protobuf:"varint,8,opt,name=heat,proto3" json:"heat,omitempty"` - OnlineCount int32 `protobuf:"varint,9,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` - SeatCount int32 `protobuf:"varint,10,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` - OccupiedSeatCount int32 `protobuf:"varint,11,opt,name=occupied_seat_count,json=occupiedSeatCount,proto3" json:"occupied_seat_count,omitempty"` - VisibleRegionId int64 `protobuf:"varint,12,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - AppCode string `protobuf:"bytes,13,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RoomShortId string `protobuf:"bytes,14,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` - Locked bool `protobuf:"varint,15,opt,name=locked,proto3" json:"locked,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` + Title string `protobuf:"bytes,4,opt,name=title,proto3" json:"title,omitempty"` + CoverUrl string `protobuf:"bytes,5,opt,name=cover_url,json=coverUrl,proto3" json:"cover_url,omitempty"` + Mode string `protobuf:"bytes,6,opt,name=mode,proto3" json:"mode,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + Heat int64 `protobuf:"varint,8,opt,name=heat,proto3" json:"heat,omitempty"` + OnlineCount int32 `protobuf:"varint,9,opt,name=online_count,json=onlineCount,proto3" json:"online_count,omitempty"` + SeatCount int32 `protobuf:"varint,10,opt,name=seat_count,json=seatCount,proto3" json:"seat_count,omitempty"` + OccupiedSeatCount int32 `protobuf:"varint,11,opt,name=occupied_seat_count,json=occupiedSeatCount,proto3" json:"occupied_seat_count,omitempty"` + VisibleRegionId int64 `protobuf:"varint,12,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` + AppCode string `protobuf:"bytes,13,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RoomShortId string `protobuf:"bytes,14,opt,name=room_short_id,json=roomShortId,proto3" json:"room_short_id,omitempty"` + Locked bool `protobuf:"varint,15,opt,name=locked,proto3" json:"locked,omitempty"` } func (x *RoomListItem) Reset() { @@ -7917,11 +8045,12 @@ func (x *RoomListItem) GetLocked() bool { // ListRoomsResponse 返回一页房间卡片和下一页不透明 cursor。 type ListRoomsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Rooms []*RoomListItem `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` - NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rooms []*RoomListItem `protobuf:"bytes,1,rep,name=rooms,proto3" json:"rooms,omitempty"` + NextCursor string `protobuf:"bytes,2,opt,name=next_cursor,json=nextCursor,proto3" json:"next_cursor,omitempty"` } func (x *ListRoomsResponse) Reset() { @@ -7970,13 +8099,14 @@ func (x *ListRoomsResponse) GetNextCursor() string { // RoomGiftLeaderboardItem 是跨房间金币消耗榜卡片;score 只表达该周期房间礼物金币消耗。 type RoomGiftLeaderboardItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - CoinSpent int64 `protobuf:"varint,3,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - Room *RoomListItem `protobuf:"bytes,4,opt,name=room,proto3" json:"room,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rank int64 `protobuf:"varint,1,opt,name=rank,proto3" json:"rank,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + CoinSpent int64 `protobuf:"varint,3,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + Room *RoomListItem `protobuf:"bytes,4,opt,name=room,proto3" json:"room,omitempty"` } func (x *RoomGiftLeaderboardItem) Reset() { @@ -8039,15 +8169,16 @@ func (x *RoomGiftLeaderboardItem) GetRoom() *RoomListItem { // ListRoomGiftLeaderboardResponse 返回当前 UTC 周期房间金币榜。 type ListRoomGiftLeaderboardResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*RoomGiftLeaderboardItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - Period string `protobuf:"bytes,3,opt,name=period,proto3" json:"period,omitempty"` - StartAtMs int64 `protobuf:"varint,4,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` - EndAtMs int64 `protobuf:"varint,5,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` - ServerTimeMs int64 `protobuf:"varint,6,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*RoomGiftLeaderboardItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + Period string `protobuf:"bytes,3,opt,name=period,proto3" json:"period,omitempty"` + StartAtMs int64 `protobuf:"varint,4,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` + EndAtMs int64 `protobuf:"varint,5,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` + ServerTimeMs int64 `protobuf:"varint,6,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *ListRoomGiftLeaderboardResponse) Reset() { @@ -8125,11 +8256,12 @@ func (x *ListRoomGiftLeaderboardResponse) GetServerTimeMs() int64 { // GetMyRoomRequest 查询当前用户自己创建的房间。 // 该查询必须由 gateway 写入鉴权后的 owner_user_id,不能从客户端接收用户 ID。 type GetMyRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + OwnerUserId int64 `protobuf:"varint,2,opt,name=owner_user_id,json=ownerUserId,proto3" json:"owner_user_id,omitempty"` } func (x *GetMyRoomRequest) Reset() { @@ -8179,12 +8311,13 @@ func (x *GetMyRoomRequest) GetOwnerUserId() int64 { // GetMyRoomResponse 返回 Mine 顶部“我的房间”权威卡片。 // 它直接读取 rooms 元数据并用 Room Cell 快照补充实时卡片字段,不依赖发现页投影是否已经写入。 type GetMyRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - HasRoom bool `protobuf:"varint,1,opt,name=has_room,json=hasRoom,proto3" json:"has_room,omitempty"` - Room *RoomListItem `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HasRoom bool `protobuf:"varint,1,opt,name=has_room,json=hasRoom,proto3" json:"has_room,omitempty"` + Room *RoomListItem `protobuf:"bytes,2,opt,name=room,proto3" json:"room,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GetMyRoomResponse) Reset() { @@ -8241,11 +8374,12 @@ func (x *GetMyRoomResponse) GetServerTimeMs() int64 { // GetCurrentRoomRequest 查询当前用户是否仍有可恢复的房间 presence。 // 该查询必须由 gateway 写入鉴权后的 user_id,客户端不能提交 user_id。 type GetCurrentRoomRequest 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 + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + 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"` } func (x *GetCurrentRoomRequest) Reset() { @@ -8295,18 +8429,19 @@ func (x *GetCurrentRoomRequest) GetUserId() int64 { // GetCurrentRoomResponse 是 App 启动、回前台和网络恢复时的房间恢复探测结果。 // 它只表达是否需要恢复,不会隐式 JoinRoom 或刷新 presence。 type GetCurrentRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - HasCurrentRoom bool `protobuf:"varint,1,opt,name=has_current_room,json=hasCurrentRoom,proto3" json:"has_current_room,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` - Role string `protobuf:"bytes,4,opt,name=role,proto3" json:"role,omitempty"` - MicSessionId string `protobuf:"bytes,5,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` - PublishState string `protobuf:"bytes,6,opt,name=publish_state,json=publishState,proto3" json:"publish_state,omitempty"` - NeedJoinImGroup bool `protobuf:"varint,7,opt,name=need_join_im_group,json=needJoinImGroup,proto3" json:"need_join_im_group,omitempty"` - NeedRtcToken bool `protobuf:"varint,8,opt,name=need_rtc_token,json=needRtcToken,proto3" json:"need_rtc_token,omitempty"` - ServerTimeMs int64 `protobuf:"varint,9,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HasCurrentRoom bool `protobuf:"varint,1,opt,name=has_current_room,json=hasCurrentRoom,proto3" json:"has_current_room,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RoomVersion int64 `protobuf:"varint,3,opt,name=room_version,json=roomVersion,proto3" json:"room_version,omitempty"` + Role string `protobuf:"bytes,4,opt,name=role,proto3" json:"role,omitempty"` + MicSessionId string `protobuf:"bytes,5,opt,name=mic_session_id,json=micSessionId,proto3" json:"mic_session_id,omitempty"` + PublishState string `protobuf:"bytes,6,opt,name=publish_state,json=publishState,proto3" json:"publish_state,omitempty"` + NeedJoinImGroup bool `protobuf:"varint,7,opt,name=need_join_im_group,json=needJoinImGroup,proto3" json:"need_join_im_group,omitempty"` + NeedRtcToken bool `protobuf:"varint,8,opt,name=need_rtc_token,json=needRtcToken,proto3" json:"need_rtc_token,omitempty"` + ServerTimeMs int64 `protobuf:"varint,9,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GetCurrentRoomResponse) Reset() { @@ -8405,12 +8540,13 @@ func (x *GetCurrentRoomResponse) GetServerTimeMs() int64 { // GetRoomSnapshotRequest 主动读取当前房间完整快照。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 type GetRoomSnapshotRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` } func (x *GetRoomSnapshotRequest) Reset() { @@ -8466,13 +8602,14 @@ func (x *GetRoomSnapshotRequest) GetViewerUserId() int64 { // GetRoomSnapshotResponse 返回 Room Cell 当前快照;只读,不刷新 presence。 type GetRoomSnapshotResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Room *RoomSnapshot `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - // is_followed 表达 viewer 是否已经关注该房间;它来自 room_follows 关系表,不属于 Room Cell 核心快照。 - IsFollowed bool `protobuf:"varint,3,opt,name=is_followed,json=isFollowed,proto3" json:"is_followed,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Room *RoomSnapshot `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + // is_followed 表达 viewer 是否已经关注该房间;它来自 room_follows 关系表,不属于 Room Cell 核心快照。 + IsFollowed bool `protobuf:"varint,3,opt,name=is_followed,json=isFollowed,proto3" json:"is_followed,omitempty"` } func (x *GetRoomSnapshotResponse) Reset() { @@ -8529,12 +8666,13 @@ func (x *GetRoomSnapshotResponse) GetIsFollowed() bool { // GetRoomRocketRequest 主动读取当前房间火箭配置物料和进度状态。 // 该查询必须由 gateway 写入鉴权后的 viewer_user_id,客户端不能提交 viewer_user_id。 type GetRoomRocketRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` } func (x *GetRoomRocketRequest) Reset() { @@ -8589,11 +8727,12 @@ func (x *GetRoomRocketRequest) GetViewerUserId() int64 { } type GetRoomRocketResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Rocket *RoomRocketInfo `protobuf:"bytes,1,opt,name=rocket,proto3" json:"rocket,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rocket *RoomRocketInfo `protobuf:"bytes,1,opt,name=rocket,proto3" json:"rocket,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GetRoomRocketResponse) Reset() { @@ -8642,15 +8781,16 @@ func (x *GetRoomRocketResponse) GetServerTimeMs() int64 { // ListRoomOnlineUsersRequest 分页查询房间在线用户,不让客户端拉完整 RoomSnapshot 做列表分页。 type ListRoomOnlineUsersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_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"` - Sort string `protobuf:"bytes,6,opt,name=sort,proto3" json:"sort,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_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"` + Sort string `protobuf:"bytes,6,opt,name=sort,proto3" json:"sort,omitempty"` } func (x *ListRoomOnlineUsersRequest) Reset() { @@ -8726,15 +8866,16 @@ func (x *ListRoomOnlineUsersRequest) GetSort() string { } type ListRoomOnlineUsersResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Users []*RoomUser `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - Items []*RoomOnlineUser `protobuf:"bytes,6,rep,name=items,proto3" json:"items,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Users []*RoomUser `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + Items []*RoomOnlineUser `protobuf:"bytes,6,rep,name=items,proto3" json:"items,omitempty"` } func (x *ListRoomOnlineUsersResponse) Reset() { @@ -8811,16 +8952,17 @@ func (x *ListRoomOnlineUsersResponse) GetItems() []*RoomOnlineUser { // RoomBannedUser 是房间黑名单列表的轻量治理读模型;用户展示资料由 gateway 批量补齐。 type RoomBannedUser struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - // unban_at_ms 为 0 表示永久 ban;非 0 表示该 UTC 毫秒后自动允许重新进房。 - UnbanAtMs int64 `protobuf:"varint,4,opt,name=unban_at_ms,json=unbanAtMs,proto3" json:"unban_at_ms,omitempty"` - RemainingMs int64 `protobuf:"varint,5,opt,name=remaining_ms,json=remainingMs,proto3" json:"remaining_ms,omitempty"` - Permanent bool `protobuf:"varint,6,opt,name=permanent,proto3" json:"permanent,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ActorUserId int64 `protobuf:"varint,2,opt,name=actor_user_id,json=actorUserId,proto3" json:"actor_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,3,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + // unban_at_ms 为 0 表示永久 ban;非 0 表示该 UTC 毫秒后自动允许重新进房。 + UnbanAtMs int64 `protobuf:"varint,4,opt,name=unban_at_ms,json=unbanAtMs,proto3" json:"unban_at_ms,omitempty"` + RemainingMs int64 `protobuf:"varint,5,opt,name=remaining_ms,json=remainingMs,proto3" json:"remaining_ms,omitempty"` + Permanent bool `protobuf:"varint,6,opt,name=permanent,proto3" json:"permanent,omitempty"` } func (x *RoomBannedUser) Reset() { @@ -8897,14 +9039,15 @@ func (x *RoomBannedUser) GetPermanent() bool { // ListRoomBannedUsersRequest 分页查询房间当前仍有效的黑名单。 type ListRoomBannedUsersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_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 + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,3,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_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"` } func (x *ListRoomBannedUsersRequest) Reset() { @@ -8973,14 +9116,15 @@ func (x *ListRoomBannedUsersRequest) GetPageSize() int32 { } type ListRoomBannedUsersResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*RoomBannedUser `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*RoomBannedUser `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ServerTimeMs int64 `protobuf:"varint,5,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *ListRoomBannedUsersResponse) Reset() { @@ -9051,12 +9195,13 @@ func (x *ListRoomBannedUsersResponse) GetServerTimeMs() int64 { // FollowRoomRequest 建立当前用户对房间的关注关系。 // 该关系是 room-service 的用户-房间低频关系事实,不进入 Room Cell command log。 type FollowRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *FollowRoomRequest) Reset() { @@ -9111,13 +9256,14 @@ func (x *FollowRoomRequest) GetUserId() int64 { } type FollowRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Followed bool `protobuf:"varint,2,opt,name=followed,proto3" json:"followed,omitempty"` - FollowedAtMs int64 `protobuf:"varint,3,opt,name=followed_at_ms,json=followedAtMs,proto3" json:"followed_at_ms,omitempty"` - ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Followed bool `protobuf:"varint,2,opt,name=followed,proto3" json:"followed,omitempty"` + FollowedAtMs int64 `protobuf:"varint,3,opt,name=followed_at_ms,json=followedAtMs,proto3" json:"followed_at_ms,omitempty"` + ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *FollowRoomResponse) Reset() { @@ -9180,12 +9326,13 @@ func (x *FollowRoomResponse) GetServerTimeMs() int64 { // UnfollowRoomRequest 取消当前用户对房间的关注关系;未关注时按幂等成功处理。 type UnfollowRoomRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta *RequestMeta `protobuf:"bytes,1,opt,name=meta,proto3" json:"meta,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *UnfollowRoomRequest) Reset() { @@ -9240,12 +9387,13 @@ func (x *UnfollowRoomRequest) GetUserId() int64 { } type UnfollowRoomResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - Followed bool `protobuf:"varint,2,opt,name=followed,proto3" json:"followed,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + Followed bool `protobuf:"varint,2,opt,name=followed,proto3" json:"followed,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *UnfollowRoomResponse) Reset() { @@ -9301,856 +9449,1915 @@ func (x *UnfollowRoomResponse) GetServerTimeMs() int64 { var File_proto_room_v1_room_proto protoreflect.FileDescriptor -const file_proto_room_v1_room_proto_rawDesc = "" + - "\n" + - "\x18proto/room/v1/room.proto\x12\rhyapp.room.v1\"\x88\x02\n" + - "\vRequestMeta\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x1d\n" + - "\n" + - "command_id\x18\x02 \x01(\tR\tcommandId\x12\"\n" + - "\ractor_user_id\x18\x03 \x01(\x03R\vactorUserId\x12\x17\n" + - "\aroom_id\x18\x04 \x01(\tR\x06roomId\x12&\n" + - "\x0fgateway_node_id\x18\x05 \x01(\tR\rgatewayNodeId\x12\x1d\n" + - "\n" + - "session_id\x18\x06 \x01(\tR\tsessionId\x12\x1c\n" + - "\n" + - "sent_at_ms\x18\a \x01(\x03R\bsentAtMs\x12\x19\n" + - "\bapp_code\x18\b \x01(\tR\aappCode\"r\n" + - "\rCommandResult\x12\x18\n" + - "\aapplied\x18\x01 \x01(\bR\aapplied\x12!\n" + - "\froom_version\x18\x02 \x01(\x03R\vroomVersion\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x80\x01\n" + - "\bRoomUser\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" + - "\x04role\x18\x02 \x01(\tR\x04role\x12 \n" + - "\fjoined_at_ms\x18\x03 \x01(\x03R\n" + - "joinedAtMs\x12%\n" + - "\x0flast_seen_at_ms\x18\x04 \x01(\x03R\flastSeenAtMs\"\xdd\x01\n" + - "\x0eRoomOnlineUser\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x12\n" + - "\x04role\x18\x02 \x01(\tR\x04role\x12\x1b\n" + - "\troom_role\x18\x03 \x01(\tR\broomRole\x12\x1d\n" + - "\n" + - "gift_value\x18\x04 \x01(\x03R\tgiftValue\x12 \n" + - "\fjoined_at_ms\x18\x05 \x01(\x03R\n" + - "joinedAtMs\x12%\n" + - "\x0flast_seen_at_ms\x18\x06 \x01(\x03R\flastSeenAtMs\x12\x19\n" + - "\bis_owner\x18\a \x01(\bR\aisOwner\"\xb2\x03\n" + - "\tSeatState\x12\x17\n" + - "\aseat_no\x18\x01 \x01(\x05R\x06seatNo\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x16\n" + - "\x06locked\x18\x03 \x01(\bR\x06locked\x12#\n" + - "\rpublish_state\x18\x04 \x01(\tR\fpublishState\x12$\n" + - "\x0emic_session_id\x18\x05 \x01(\tR\fmicSessionId\x12.\n" + - "\x13publish_deadline_ms\x18\x06 \x01(\x03R\x11publishDeadlineMs\x127\n" + - "\x18mic_session_room_version\x18\a \x01(\x03R\x15micSessionRoomVersion\x12:\n" + - "\x1alast_publish_event_time_ms\x18\b \x01(\x03R\x16lastPublishEventTimeMs\x12\x1b\n" + - "\tmic_muted\x18\t \x01(\bR\bmicMuted\x12\x1f\n" + - "\vseat_status\x18\n" + - " \x01(\tR\n" + - "seatStatus\x12-\n" + - "\x13mic_heartbeat_at_ms\x18\v \x01(\x03R\x10micHeartbeatAtMs\"|\n" + - "\bRankItem\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n" + - "\x05score\x18\x02 \x01(\x03R\x05score\x12\x1d\n" + - "\n" + - "gift_value\x18\x03 \x01(\x03R\tgiftValue\x12\"\n" + - "\rupdated_at_ms\x18\x04 \x01(\x03R\vupdatedAtMs\"\xb0\x06\n" + - "\x13LuckyGiftDrawResult\x12\x18\n" + - "\aenabled\x18\x01 \x01(\bR\aenabled\x12\x17\n" + - "\adraw_id\x18\x02 \x01(\tR\x06drawId\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12\x17\n" + - "\apool_id\x18\x04 \x01(\tR\x06poolId\x12\x17\n" + - "\agift_id\x18\x05 \x01(\tR\x06giftId\x12!\n" + - "\frule_version\x18\x06 \x01(\x03R\vruleVersion\x12'\n" + - "\x0fexperience_pool\x18\a \x01(\tR\x0eexperiencePool\x12(\n" + - "\x10selected_tier_id\x18\b \x01(\tR\x0eselectedTierId\x12%\n" + - "\x0emultiplier_ppm\x18\t \x01(\x03R\rmultiplierPpm\x12*\n" + - "\x11base_reward_coins\x18\n" + - " \x01(\x03R\x0fbaseRewardCoins\x12?\n" + - "\x1croom_atmosphere_reward_coins\x18\v \x01(\x03R\x19roomAtmosphereRewardCoins\x124\n" + - "\x16activity_subsidy_coins\x18\f \x01(\x03R\x14activitySubsidyCoins\x124\n" + - "\x16effective_reward_coins\x18\r \x01(\x03R\x14effectiveRewardCoins\x12#\n" + - "\rreward_status\x18\x0e \x01(\tR\frewardStatus\x12%\n" + - "\x0estage_feedback\x18\x0f \x01(\bR\rstageFeedback\x12'\n" + - "\x0fhigh_multiplier\x18\x10 \x01(\bR\x0ehighMultiplier\x12\"\n" + - "\rcreated_at_ms\x18\x11 \x01(\x03R\vcreatedAtMs\x122\n" + - "\x15wallet_transaction_id\x18\x12 \x01(\tR\x13walletTransactionId\x12,\n" + - "\x12coin_balance_after\x18\x13 \x01(\x03R\x10coinBalanceAfter\x12$\n" + - "\x0etarget_user_id\x18\x14 \x01(\x03R\ftargetUserId\"\xbe\x01\n" + - "\x14RoomRocketRewardItem\x12$\n" + - "\x0ereward_item_id\x18\x01 \x01(\tR\frewardItemId\x12*\n" + - "\x11resource_group_id\x18\x02 \x01(\x03R\x0fresourceGroupId\x12\x16\n" + - "\x06weight\x18\x03 \x01(\x03R\x06weight\x12!\n" + - "\fdisplay_name\x18\x04 \x01(\tR\vdisplayName\x12\x19\n" + - "\bicon_url\x18\x05 \x01(\tR\aiconUrl\"\xd3\x03\n" + - "\x0fRoomRocketLevel\x12\x14\n" + - "\x05level\x18\x01 \x01(\x05R\x05level\x12%\n" + - "\x0efuel_threshold\x18\x02 \x01(\x03R\rfuelThreshold\x12\x1b\n" + - "\tcover_url\x18\x03 \x01(\tR\bcoverUrl\x12#\n" + - "\ranimation_url\x18\x04 \x01(\tR\fanimationUrl\x120\n" + - "\x14launch_animation_url\x18\x05 \x01(\tR\x12launchAnimationUrl\x12,\n" + - "\x12launched_image_url\x18\x06 \x01(\tR\x10launchedImageUrl\x12K\n" + - "\x0fin_room_rewards\x18\a \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\rinRoomRewards\x12F\n" + - "\ftop1_rewards\x18\b \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\vtop1Rewards\x12L\n" + - "\x0figniter_rewards\x18\t \x03(\v2#.hyapp.room.v1.RoomRocketRewardItemR\x0eigniterRewards\"\x94\x02\n" + - "\x15RoomRocketRewardGrant\x12\x1f\n" + - "\vreward_role\x18\x01 \x01(\tR\n" + - "rewardRole\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12$\n" + - "\x0ereward_item_id\x18\x03 \x01(\tR\frewardItemId\x12*\n" + - "\x11resource_group_id\x18\x04 \x01(\x03R\x0fresourceGroupId\x12!\n" + - "\fdisplay_name\x18\x05 \x01(\tR\vdisplayName\x12\x19\n" + - "\bicon_url\x18\x06 \x01(\tR\aiconUrl\x12\x19\n" + - "\bgrant_id\x18\a \x01(\tR\agrantId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\"\xe7\x02\n" + - "\x17RoomRocketPendingLaunch\x12\x1b\n" + - "\trocket_id\x18\x01 \x01(\tR\brocketId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12%\n" + - "\x0efuel_threshold\x18\x03 \x01(\x03R\rfuelThreshold\x12\"\n" + - "\rignited_at_ms\x18\x04 \x01(\x03R\vignitedAtMs\x12 \n" + - "\flaunch_at_ms\x18\x05 \x01(\x03R\n" + - "launchAtMs\x12\x1e\n" + - "\vreset_at_ms\x18\x06 \x01(\x03R\tresetAtMs\x12 \n" + - "\ftop1_user_id\x18\a \x01(\x03R\n" + - "top1UserId\x12&\n" + - "\x0figniter_user_id\x18\b \x01(\x03R\rigniterUserId\x12%\n" + - "\x0econfig_version\x18\t \x01(\x03R\rconfigVersion\x12\x1b\n" + - "\tcover_url\x18\n" + - " \x01(\tR\bcoverUrl\"\xce\x04\n" + - "\x0fRoomRocketState\x12#\n" + - "\rcurrent_level\x18\x01 \x01(\x05R\fcurrentLevel\x12!\n" + - "\fcurrent_fuel\x18\x02 \x01(\x03R\vcurrentFuel\x12%\n" + - "\x0efuel_threshold\x18\x03 \x01(\x03R\rfuelThreshold\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12\"\n" + - "\rignited_at_ms\x18\x05 \x01(\x03R\vignitedAtMs\x12 \n" + - "\flaunch_at_ms\x18\x06 \x01(\x03R\n" + - "launchAtMs\x12$\n" + - "\x0elaunched_at_ms\x18\a \x01(\x03R\flaunchedAtMs\x12\x1e\n" + - "\vreset_at_ms\x18\b \x01(\x03R\tresetAtMs\x12 \n" + - "\ftop1_user_id\x18\t \x01(\x03R\n" + - "top1UserId\x12&\n" + - "\x0figniter_user_id\x18\n" + - " \x01(\x03R\rigniterUserId\x12\x1b\n" + - "\trocket_id\x18\v \x01(\tR\brocketId\x12%\n" + - "\x0econfig_version\x18\f \x01(\x03R\rconfigVersion\x12G\n" + - "\flast_rewards\x18\r \x03(\v2$.hyapp.room.v1.RoomRocketRewardGrantR\vlastRewards\x12Q\n" + - "\x10pending_launches\x18\x0e \x03(\v2&.hyapp.room.v1.RoomRocketPendingLaunchR\x0fpendingLaunches\"\xed\x02\n" + - "\x0eRoomRocketInfo\x12\x18\n" + - "\aenabled\x18\x01 \x01(\bR\aenabled\x126\n" + - "\x06levels\x18\x02 \x03(\v2\x1e.hyapp.room.v1.RoomRocketLevelR\x06levels\x124\n" + - "\x05state\x18\x03 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x05state\x12$\n" + - "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\x12'\n" + - "\x0fbroadcast_scope\x18\x05 \x01(\tR\x0ebroadcastScope\x12&\n" + - "\x0flaunch_delay_ms\x18\x06 \x01(\x03R\rlaunchDelayMs\x12,\n" + - "\x12broadcast_delay_ms\x18\a \x01(\x03R\x10broadcastDelayMs\x12.\n" + - "\x13reward_stack_policy\x18\b \x01(\tR\x11rewardStackPolicy\"\xd2\x01\n" + - "\x16RoomRocketGiftFuelRule\x12\x17\n" + - "\arule_id\x18\x01 \x01(\tR\x06ruleId\x12\x17\n" + - "\agift_id\x18\x02 \x01(\tR\x06giftId\x12$\n" + - "\x0egift_type_code\x18\x03 \x01(\tR\fgiftTypeCode\x12%\n" + - "\x0emultiplier_ppm\x18\x04 \x01(\x03R\rmultiplierPpm\x12\x1d\n" + - "\n" + - "fixed_fuel\x18\x05 \x01(\x03R\tfixedFuel\x12\x1a\n" + - "\bexcluded\x18\x06 \x01(\bR\bexcluded\"\xee\x04\n" + - "\x15AdminRoomRocketConfig\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + - "\aenabled\x18\x02 \x01(\bR\aenabled\x12%\n" + - "\x0econfig_version\x18\x03 \x01(\x03R\rconfigVersion\x12\x1f\n" + - "\vfuel_source\x18\x04 \x01(\tR\n" + - "fuelSource\x12&\n" + - "\x0flaunch_delay_ms\x18\x05 \x01(\x03R\rlaunchDelayMs\x12+\n" + - "\x11broadcast_enabled\x18\x06 \x01(\bR\x10broadcastEnabled\x12'\n" + - "\x0fbroadcast_scope\x18\a \x01(\tR\x0ebroadcastScope\x12,\n" + - "\x12broadcast_delay_ms\x18\b \x01(\x03R\x10broadcastDelayMs\x12.\n" + - "\x13reward_stack_policy\x18\t \x01(\tR\x11rewardStackPolicy\x126\n" + - "\x06levels\x18\n" + - " \x03(\v2\x1e.hyapp.room.v1.RoomRocketLevelR\x06levels\x12M\n" + - "\x0fgift_fuel_rules\x18\v \x03(\v2%.hyapp.room.v1.RoomRocketGiftFuelRuleR\rgiftFuelRules\x12-\n" + - "\x13updated_by_admin_id\x18\f \x01(\x03R\x10updatedByAdminId\x12\"\n" + - "\rcreated_at_ms\x18\r \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x0e \x01(\x03R\vupdatedAtMs\"Q\n" + - "\x1fAdminGetRoomRocketConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\x86\x01\n" + - " AdminGetRoomRocketConfigResponse\x12<\n" + - "\x06config\x18\x01 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xad\x01\n" + - "\"AdminUpdateRoomRocketConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12<\n" + - "\x06config\x18\x02 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12\x19\n" + - "\badmin_id\x18\x03 \x01(\x03R\aadminId\"\x89\x01\n" + - "#AdminUpdateRoomRocketConfigResponse\x12<\n" + - "\x06config\x18\x01 \x01(\v2$.hyapp.room.v1.AdminRoomRocketConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xcb\x01\n" + - "\x13AdminRoomSeatConfig\x122\n" + - "\x15candidate_seat_counts\x18\x01 \x03(\x05R\x13candidateSeatCounts\x12.\n" + - "\x13allowed_seat_counts\x18\x02 \x03(\x05R\x11allowedSeatCounts\x12,\n" + - "\x12default_seat_count\x18\x03 \x01(\x05R\x10defaultSeatCount\x12\"\n" + - "\rupdated_at_ms\x18\x04 \x01(\x03R\vupdatedAtMs\"O\n" + - "\x1dAdminGetRoomSeatConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\x82\x01\n" + - "\x1eAdminGetRoomSeatConfigResponse\x12:\n" + - "\x06config\x18\x01 \x01(\v2\".hyapp.room.v1.AdminRoomSeatConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xb0\x01\n" + - " AdminUpdateRoomSeatConfigRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12.\n" + - "\x13allowed_seat_counts\x18\x02 \x03(\x05R\x11allowedSeatCounts\x12,\n" + - "\x12default_seat_count\x18\x03 \x01(\x05R\x10defaultSeatCount\"\x85\x01\n" + - "!AdminUpdateRoomSeatConfigResponse\x12:\n" + - "\x06config\x18\x01 \x01(\v2\".hyapp.room.v1.AdminRoomSeatConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xea\x01\n" + - "\x10AdminRoomPinRoom\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\"\n" + - "\rroom_short_id\x18\x02 \x01(\tR\vroomShortId\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\x12\"\n" + - "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\x12\x14\n" + - "\x05title\x18\x05 \x01(\tR\x05title\x12\x1b\n" + - "\tcover_url\x18\x06 \x01(\tR\bcoverUrl\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\"\xfb\x03\n" + - "\fAdminRoomPin\x12\x0e\n" + - "\x02id\x18\x01 \x01(\x03R\x02id\x12*\n" + - "\x11visible_region_id\x18\x02 \x01(\x03R\x0fvisibleRegionId\x12\x17\n" + - "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12\x16\n" + - "\x06weight\x18\x04 \x01(\x03R\x06weight\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12 \n" + - "\fpinned_at_ms\x18\x06 \x01(\x03R\n" + - "pinnedAtMs\x12\"\n" + - "\rexpires_at_ms\x18\a \x01(\x03R\vexpiresAtMs\x12&\n" + - "\x0fcancelled_at_ms\x18\b \x01(\x03R\rcancelledAtMs\x12-\n" + - "\x13created_by_admin_id\x18\t \x01(\x04R\x10createdByAdminId\x121\n" + - "\x15cancelled_by_admin_id\x18\n" + - " \x01(\x04R\x12cancelledByAdminId\x12\"\n" + - "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\f \x01(\x03R\vupdatedAtMs\x123\n" + - "\x04room\x18\r \x01(\v2\x1f.hyapp.room.v1.AdminRoomPinRoomR\x04room\x12\x19\n" + - "\bpin_type\x18\x0e \x01(\tR\apinType\"\xf4\x01\n" + - "\x18AdminListRoomPinsRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x12\n" + - "\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x18\n" + - "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12*\n" + - "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\x12\x19\n" + - "\bpin_type\x18\a \x01(\tR\apinType\"\x88\x01\n" + - "\x19AdminListRoomPinsResponse\x12/\n" + - "\x04pins\x18\x01 \x03(\v2\x1b.hyapp.room.v1.AdminRoomPinR\x04pins\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x9d\x02\n" + - "\x19AdminCreateRoomPinRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x16\n" + - "\x06weight\x18\x03 \x01(\x03R\x06weight\x12#\n" + - "\rduration_days\x18\x04 \x01(\x03R\fdurationDays\x12\x19\n" + - "\badmin_id\x18\x05 \x01(\x04R\aadminId\x12 \n" + - "\fpinned_at_ms\x18\x06 \x01(\x03R\n" + - "pinnedAtMs\x12\"\n" + - "\rexpires_at_ms\x18\a \x01(\x03R\vexpiresAtMs\x12\x19\n" + - "\bpin_type\x18\b \x01(\tR\apinType\"q\n" + - "\x1aAdminCreateRoomPinResponse\x12-\n" + - "\x03pin\x18\x01 \x01(\v2\x1b.hyapp.room.v1.AdminRoomPinR\x03pin\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"}\n" + - "\x19AdminCancelRoomPinRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x15\n" + - "\x06pin_id\x18\x02 \x01(\x03R\x05pinId\x12\x19\n" + - "\badmin_id\x18\x03 \x01(\x04R\aadminId\"q\n" + - "\x1aAdminCancelRoomPinResponse\x12-\n" + - "\x03pin\x18\x01 \x01(\v2\x1b.hyapp.room.v1.AdminRoomPinR\x03pin\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\x93\x01\n" + - "\fRoomBanState\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\"\n" + - "\ractor_user_id\x18\x02 \x01(\x03R\vactorUserId\x12\"\n" + - "\rcreated_at_ms\x18\x03 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rexpires_at_ms\x18\x04 \x01(\x03R\vexpiresAtMs\"\xd5\x06\n" + - "\fRoomSnapshot\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\"\n" + - "\rowner_user_id\x18\x02 \x01(\x03R\vownerUserId\x12\x12\n" + - "\x04mode\x18\x04 \x01(\tR\x04mode\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12!\n" + - "\fchat_enabled\x18\x06 \x01(\bR\vchatEnabled\x125\n" + - "\tmic_seats\x18\a \x03(\v2\x18.hyapp.room.v1.SeatStateR\bmicSeats\x12:\n" + - "\fonline_users\x18\b \x03(\v2\x17.hyapp.room.v1.RoomUserR\vonlineUsers\x12$\n" + - "\x0eadmin_user_ids\x18\t \x03(\x03R\fadminUserIds\x12 \n" + - "\fban_user_ids\x18\n" + - " \x03(\x03R\n" + - "banUserIds\x12\"\n" + - "\rmute_user_ids\x18\v \x03(\x03R\vmuteUserIds\x124\n" + - "\tgift_rank\x18\f \x03(\v2\x17.hyapp.room.v1.RankItemR\bgiftRank\x12C\n" + - "\broom_ext\x18\r \x03(\v2(.hyapp.room.v1.RoomSnapshot.RoomExtEntryR\aroomExt\x12\x12\n" + - "\x04heat\x18\x0e \x01(\x03R\x04heat\x12\x18\n" + - "\aversion\x18\x0f \x01(\x03R\aversion\x12\x19\n" + - "\bapp_code\x18\x10 \x01(\tR\aappCode\x12\"\n" + - "\rroom_short_id\x18\x11 \x01(\tR\vroomShortId\x12*\n" + - "\x11visible_region_id\x18\x12 \x01(\x03R\x0fvisibleRegionId\x12\x16\n" + - "\x06locked\x18\x13 \x01(\bR\x06locked\x126\n" + - "\x06rocket\x18\x14 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x06rocket\x12:\n" + - "\n" + - "ban_states\x18\x15 \x03(\v2\x1b.hyapp.room.v1.RoomBanStateR\tbanStates\x1a:\n" + - "\fRoomExtEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe5\x01\n" + - "\x13RoomBackgroundImage\x12#\n" + - "\rbackground_id\x18\x01 \x01(\x03R\fbackgroundId\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x1b\n" + - "\timage_url\x18\x03 \x01(\tR\bimageUrl\x12+\n" + - "\x12created_by_user_id\x18\x04 \x01(\x03R\x0fcreatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\x05 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x06 \x01(\x03R\vupdatedAtMs\"\x81\x01\n" + - "\x19SaveRoomBackgroundRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x1b\n" + - "\timage_url\x18\x03 \x01(\tR\bimageUrl\"\x86\x01\n" + - "\x1aSaveRoomBackgroundResponse\x12B\n" + - "\n" + - "background\x18\x01 \x01(\v2\".hyapp.room.v1.RoomBackgroundImageR\n" + - "background\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\x8b\x01\n" + - "\x1aListRoomBackgroundsRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\"\xc1\x01\n" + - "\x1bListRoomBackgroundsResponse\x12D\n" + - "\vbackgrounds\x18\x01 \x03(\v2\".hyapp.room.v1.RoomBackgroundImageR\vbackgrounds\x126\n" + - "\x17selected_background_url\x18\x02 \x01(\tR\x15selectedBackgroundUrl\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"o\n" + - "\x18SetRoomBackgroundRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12#\n" + - "\rbackground_id\x18\x02 \x01(\x03R\fbackgroundId\"\xc6\x01\n" + - "\x19SetRoomBackgroundResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12B\n" + - "\n" + - "background\x18\x03 \x01(\v2\".hyapp.room.v1.RoomBackgroundImageR\n" + - "background\"\xaf\x02\n" + - "\x11CreateRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x1d\n" + - "\n" + - "seat_count\x18\x02 \x01(\x05R\tseatCount\x12\x12\n" + - "\x04mode\x18\x03 \x01(\tR\x04mode\x12*\n" + - "\x11visible_region_id\x18\x04 \x01(\x03R\x0fvisibleRegionId\x12\x1b\n" + - "\troom_name\x18\x05 \x01(\tR\broomName\x12\x1f\n" + - "\vroom_avatar\x18\x06 \x01(\tR\n" + - "roomAvatar\x12)\n" + - "\x10room_description\x18\a \x01(\tR\x0froomDescription\x12\"\n" + - "\rroom_short_id\x18\b \x01(\tR\vroomShortId\"{\n" + - "\x12CreateRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\xa8\x02\n" + - "\x18UpdateRoomProfileRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12 \n" + - "\troom_name\x18\x02 \x01(\tH\x00R\broomName\x88\x01\x01\x12$\n" + - "\vroom_avatar\x18\x03 \x01(\tH\x01R\n" + - "roomAvatar\x88\x01\x01\x12.\n" + - "\x10room_description\x18\x04 \x01(\tH\x02R\x0froomDescription\x88\x01\x01\x12\"\n" + - "\n" + - "seat_count\x18\x05 \x01(\x05H\x03R\tseatCount\x88\x01\x01B\f\n" + - "\n" + - "_room_nameB\x0e\n" + - "\f_room_avatarB\x13\n" + - "\x11_room_descriptionB\r\n" + - "\v_seat_count\"\x82\x01\n" + - "\x19UpdateRoomProfileResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\xc7\x02\n" + - "\x18RoomEntryVehicleSnapshot\x12\x1f\n" + - "\vresource_id\x18\x01 \x01(\x03R\n" + - "resourceId\x12#\n" + - "\rresource_code\x18\x02 \x01(\tR\fresourceCode\x12\x12\n" + - "\x04name\x18\x03 \x01(\tR\x04name\x12\x1b\n" + - "\tasset_url\x18\x04 \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\x05 \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\x06 \x01(\tR\fanimationUrl\x12#\n" + - "\rmetadata_json\x18\a \x01(\tR\fmetadataJson\x12%\n" + - "\x0eentitlement_id\x18\b \x01(\tR\rentitlementId\x12\"\n" + - "\rexpires_at_ms\x18\t \x01(\x03R\vexpiresAtMs\"\xbf\x01\n" + - "\x0fJoinRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x12\n" + - "\x04role\x18\x02 \x01(\tR\x04role\x12\x1a\n" + - "\bpassword\x18\x03 \x01(\tR\bpassword\x12L\n" + - "\rentry_vehicle\x18\x04 \x01(\v2'.hyapp.room.v1.RoomEntryVehicleSnapshotR\fentryVehicle\"\xa6\x01\n" + - "\x10JoinRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12+\n" + - "\x04user\x18\x02 \x01(\v2\x17.hyapp.room.v1.RoomUserR\x04user\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"F\n" + - "\x14RoomHeartbeatRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"\xab\x01\n" + - "\x15RoomHeartbeatResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12+\n" + - "\x04user\x18\x02 \x01(\v2\x17.hyapp.room.v1.RoomUserR\x04user\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"B\n" + - "\x10LeaveRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\"z\n" + - "\x11LeaveRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"Z\n" + - "\x10CloseRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x16\n" + - "\x06reason\x18\x02 \x01(\tR\x06reason\"z\n" + - "\x11CloseRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x8f\x05\n" + - "\x11AdminRoomListItem\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\"\n" + - "\rroom_short_id\x18\x02 \x01(\tR\vroomShortId\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\x12\"\n" + - "\rowner_user_id\x18\x04 \x01(\x03R\vownerUserId\x12\x14\n" + - "\x05title\x18\x05 \x01(\tR\x05title\x12\x1b\n" + - "\tcover_url\x18\x06 \x01(\tR\bcoverUrl\x12\x12\n" + - "\x04mode\x18\a \x01(\tR\x04mode\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\x12!\n" + - "\fclose_reason\x18\t \x01(\tR\vcloseReason\x12+\n" + - "\x12closed_by_admin_id\x18\n" + - " \x01(\x04R\x0fclosedByAdminId\x12/\n" + - "\x14closed_by_admin_name\x18\v \x01(\tR\x11closedByAdminName\x12 \n" + - "\fclosed_at_ms\x18\f \x01(\x03R\n" + - "closedAtMs\x12\x12\n" + - "\x04heat\x18\r \x01(\x03R\x04heat\x12!\n" + - "\fonline_count\x18\x0e \x01(\x05R\vonlineCount\x12\x1d\n" + - "\n" + - "seat_count\x18\x0f \x01(\x05R\tseatCount\x12.\n" + - "\x13occupied_seat_count\x18\x10 \x01(\x05R\x11occupiedSeatCount\x12\x1d\n" + - "\n" + - "sort_score\x18\x11 \x01(\x03R\tsortScore\x12\"\n" + - "\rcreated_at_ms\x18\x12 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x13 \x01(\x03R\vupdatedAtMs\"\xba\x02\n" + - "\x15AdminListRoomsRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x12\n" + - "\x04page\x18\x02 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x03 \x01(\x05R\bpageSize\x12\x18\n" + - "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12*\n" + - "\x11visible_region_id\x18\x06 \x01(\x03R\x0fvisibleRegionId\x12\x17\n" + - "\asort_by\x18\a \x01(\tR\x06sortBy\x12%\n" + - "\x0esort_direction\x18\b \x01(\tR\rsortDirection\x12\"\n" + - "\rowner_user_id\x18\t \x01(\x03R\vownerUserId\"\x8c\x01\n" + - "\x16AdminListRoomsResponse\x126\n" + - "\x05rooms\x18\x01 \x03(\v2 .hyapp.room.v1.AdminRoomListItemR\x05rooms\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"^\n" + - "\x13AdminGetRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\"r\n" + - "\x14AdminGetRoomResponse\x124\n" + - "\x04room\x18\x01 \x01(\v2 .hyapp.room.v1.AdminRoomListItemR\x04room\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xc2\x03\n" + - "\x16AdminUpdateRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x19\n" + - "\x05title\x18\x02 \x01(\tH\x00R\x05title\x88\x01\x01\x12 \n" + - "\tcover_url\x18\x03 \x01(\tH\x01R\bcoverUrl\x88\x01\x01\x12%\n" + - "\vdescription\x18\x04 \x01(\tH\x02R\vdescription\x88\x01\x01\x12\x17\n" + - "\x04mode\x18\x05 \x01(\tH\x03R\x04mode\x88\x01\x01\x12\x1b\n" + - "\x06status\x18\x06 \x01(\tH\x04R\x06status\x88\x01\x01\x12/\n" + - "\x11visible_region_id\x18\a \x01(\x03H\x05R\x0fvisibleRegionId\x88\x01\x01\x12!\n" + - "\fclose_reason\x18\b \x01(\tR\vcloseReason\x12\x19\n" + - "\badmin_id\x18\t \x01(\x04R\aadminId\x12\x1d\n" + - "\n" + - "admin_name\x18\n" + - " \x01(\tR\tadminNameB\b\n" + - "\x06_titleB\f\n" + - "\n" + - "_cover_urlB\x0e\n" + - "\f_descriptionB\a\n" + - "\x05_modeB\t\n" + - "\a_statusB\x14\n" + - "\x12_visible_region_id\"\x80\x01\n" + - "\x17AdminUpdateRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x82\x01\n" + - "\x16AdminDeleteRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x19\n" + - "\badmin_id\x18\x02 \x01(\x04R\aadminId\x12\x1d\n" + - "\n" + - "admin_name\x18\x03 \x01(\tR\tadminName\"\x80\x01\n" + - "\x17AdminDeleteRoomResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"W\n" + - "\fMicUpRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\"\xe5\x01\n" + - "\rMicUpResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12$\n" + - "\x0emic_session_id\x18\x04 \x01(\tR\fmicSessionId\x12.\n" + - "\x13publish_deadline_ms\x18\x05 \x01(\x03R\x11publishDeadlineMs\"~\n" + - "\x0eMicDownRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06reason\x18\x03 \x01(\tR\x06reason\"\x91\x01\n" + - "\x0fMicDownResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x85\x01\n" + - "\x14ChangeMicSeatRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x17\n" + - "\aseat_no\x18\x03 \x01(\x05R\x06seatNo\"~\n" + - "\x15ChangeMicSeatResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\xf8\x01\n" + - "\x1bConfirmMicPublishingRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12$\n" + - "\x0emic_session_id\x18\x03 \x01(\tR\fmicSessionId\x12!\n" + - "\froom_version\x18\x04 \x01(\x03R\vroomVersion\x12\"\n" + - "\revent_time_ms\x18\x05 \x01(\x03R\veventTimeMs\x12\x16\n" + - "\x06source\x18\x06 \x01(\tR\x06source\"\x9e\x01\n" + - "\x1cConfirmMicPublishingResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x91\x01\n" + - "\x13MicHeartbeatRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12$\n" + - "\x0emic_session_id\x18\x03 \x01(\tR\fmicSessionId\"\xc5\x01\n" + - "\x14MicHeartbeatResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12-\n" + - "\x13mic_heartbeat_at_ms\x18\x04 \x01(\x03R\x10micHeartbeatAtMs\"\x7f\n" + - "\x11SetMicMuteRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x14\n" + - "\x05muted\x18\x03 \x01(\bR\x05muted\"\x94\x01\n" + - "\x12SetMicMuteResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x8b\x02\n" + - "\x14ApplyRTCEventRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x1d\n" + - "\n" + - "event_type\x18\x03 \x01(\tR\teventType\x12\"\n" + - "\revent_time_ms\x18\x04 \x01(\x03R\veventTimeMs\x12\x16\n" + - "\x06reason\x18\x05 \x01(\tR\x06reason\x12\x16\n" + - "\x06source\x18\x06 \x01(\tR\x06source\x12*\n" + - "\x11external_event_id\x18\a \x01(\tR\x0fexternalEventId\"\x97\x01\n" + - "\x15ApplyRTCEventResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"x\n" + - "\x15SetMicSeatLockRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aseat_no\x18\x02 \x01(\x05R\x06seatNo\x12\x16\n" + - "\x06locked\x18\x03 \x01(\bR\x06locked\"\x7f\n" + - "\x16SetMicSeatLockResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"a\n" + - "\x15SetChatEnabledRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x18\n" + - "\aenabled\x18\x02 \x01(\bR\aenabled\"\x7f\n" + - "\x16SetChatEnabledResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"|\n" + - "\x16SetRoomPasswordRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x16\n" + - "\x06locked\x18\x02 \x01(\bR\x06locked\x12\x1a\n" + - "\bpassword\x18\x03 \x01(\tR\bpassword\"\x80\x01\n" + - "\x17SetRoomPasswordResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x85\x01\n" + - "\x13SetRoomAdminRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x18\n" + - "\aenabled\x18\x03 \x01(\bR\aenabled\"}\n" + - "\x14SetRoomAdminResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"}\n" + - "\x0fMuteUserRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x14\n" + - "\x05muted\x18\x03 \x01(\bR\x05muted\"y\n" + - "\x10MuteUserResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\x88\x01\n" + - "\x0fKickUserRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x1f\n" + - "\vduration_ms\x18\x03 \x01(\x03R\n" + - "durationMs\"\xbe\x01\n" + - "\x10KickUserResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12\x1d\n" + - "\n" + - "rtc_kicked\x18\x03 \x01(\bR\trtcKicked\x12$\n" + - "\x0ertc_kick_error\x18\x04 \x01(\tR\frtcKickError\"h\n" + - "\x10UnbanUserRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\"z\n" + - "\x11UnbanUserResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\"\xd4\x01\n" + - "\x16SystemEvictUserRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12(\n" + - "\x10operator_user_id\x18\x03 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + - "\x06reason\x18\x04 \x01(\tR\x06reason\x12\"\n" + - "\rban_from_room\x18\x05 \x01(\bR\vbanFromRoom\"\x88\x02\n" + - "\x17SystemEvictUserResponse\x12(\n" + - "\x10had_current_room\x18\x01 \x01(\bR\x0ehadCurrentRoom\x124\n" + - "\x06result\x18\x02 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12/\n" + - "\x04room\x18\x03 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12\x17\n" + - "\aroom_id\x18\x04 \x01(\tR\x06roomId\x12\x1d\n" + - "\n" + - "rtc_kicked\x18\x05 \x01(\bR\trtcKicked\x12$\n" + - "\x0ertc_kick_error\x18\x06 \x01(\tR\frtcKickError\"\xc2\x03\n" + - "\x0fSendGiftRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x17\n" + - "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x1d\n" + - "\n" + - "gift_count\x18\x04 \x01(\x05R\tgiftCount\x12\x1f\n" + - "\vtarget_type\x18\x05 \x01(\tR\n" + - "targetType\x12&\n" + - "\x0ftarget_user_ids\x18\x06 \x03(\x03R\rtargetUserIds\x12\x17\n" + - "\apool_id\x18\a \x01(\tR\x06poolId\x12$\n" + - "\x0etarget_is_host\x18\b \x01(\bR\ftargetIsHost\x121\n" + - "\x15target_host_region_id\x18\t \x01(\x03R\x12targetHostRegionId\x12<\n" + - "\x1btarget_agency_owner_user_id\x18\n" + - " \x01(\x03R\x17targetAgencyOwnerUserId\x12(\n" + - "\x10sender_region_id\x18\v \x01(\x03R\x0esenderRegionId\"\xba\x03\n" + - "\x10SendGiftResponse\x124\n" + - "\x06result\x18\x01 \x01(\v2\x1c.hyapp.room.v1.CommandResultR\x06result\x12,\n" + - "\x12billing_receipt_id\x18\x02 \x01(\tR\x10billingReceiptId\x12\x1b\n" + - "\troom_heat\x18\x03 \x01(\x03R\broomHeat\x124\n" + - "\tgift_rank\x18\x04 \x03(\v2\x17.hyapp.room.v1.RankItemR\bgiftRank\x12/\n" + - "\x04room\x18\x05 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x126\n" + - "\x06rocket\x18\x06 \x01(\v2\x1e.hyapp.room.v1.RoomRocketStateR\x06rocket\x12A\n" + - "\n" + - "lucky_gift\x18\a \x01(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\tluckyGift\x12C\n" + - "\vlucky_gifts\x18\b \x03(\v2\".hyapp.room.v1.LuckyGiftDrawResultR\n" + - "luckyGifts\"j\n" + - "\x1bCheckSpeakPermissionRequest\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x19\n" + - "\bapp_code\x18\x03 \x01(\tR\aappCode\"s\n" + - "\x1cCheckSpeakPermissionResponse\x12\x18\n" + - "\aallowed\x18\x01 \x01(\bR\aallowed\x12\x16\n" + - "\x06reason\x18\x02 \x01(\tR\x06reason\x12!\n" + - "\froom_version\x18\x03 \x01(\x03R\vroomVersion\"\xa6\x01\n" + - "\x19VerifyRoomPresenceRequest\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1d\n" + - "\n" + - "session_id\x18\x03 \x01(\tR\tsessionId\x12\x1d\n" + - "\n" + - "request_id\x18\x04 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x05 \x01(\tR\aappCode\"q\n" + - "\x1aVerifyRoomPresenceResponse\x12\x18\n" + - "\apresent\x18\x01 \x01(\bR\apresent\x12\x16\n" + - "\x06reason\x18\x02 \x01(\tR\x06reason\x12!\n" + - "\froom_version\x18\x03 \x01(\x03R\vroomVersion\"\xea\x01\n" + - "\x10ListRoomsRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0eviewer_user_id\x18\x02 \x01(\x03R\fviewerUserId\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\x12\x10\n" + - "\x03tab\x18\x04 \x01(\tR\x03tab\x12\x16\n" + - "\x06cursor\x18\x05 \x01(\tR\x06cursor\x12\x14\n" + - "\x05limit\x18\x06 \x01(\x05R\x05limit\x12\x14\n" + - "\x05query\x18\a \x01(\tR\x05query\"\xb7\x02\n" + - "\x14ListRoomFeedsRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12$\n" + - "\x0eviewer_user_id\x18\x02 \x01(\x03R\fviewerUserId\x12*\n" + - "\x11visible_region_id\x18\x03 \x01(\x03R\x0fvisibleRegionId\x12\x10\n" + - "\x03tab\x18\x04 \x01(\tR\x03tab\x12\x16\n" + - "\x06cursor\x18\x05 \x01(\tR\x06cursor\x12\x14\n" + - "\x05limit\x18\x06 \x01(\x05R\x05limit\x12\x14\n" + - "\x05query\x18\a \x01(\tR\x05query\x12G\n" + - "\rrelated_users\x18\b \x03(\v2\".hyapp.room.v1.RoomFeedRelatedUserR\frelatedUsers\"\x99\x01\n" + - "\x1eListRoomGiftLeaderboardRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x16\n" + - "\x06period\x18\x02 \x01(\tR\x06period\x12\x12\n" + - "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x04 \x01(\x05R\bpageSize\"c\n" + - "\x13RoomFeedRelatedUser\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x123\n" + - "\x16relation_updated_at_ms\x18\x02 \x01(\x03R\x13relationUpdatedAtMs\"\xb3\x03\n" + - "\fRoomListItem\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\"\n" + - "\rowner_user_id\x18\x02 \x01(\x03R\vownerUserId\x12\x14\n" + - "\x05title\x18\x04 \x01(\tR\x05title\x12\x1b\n" + - "\tcover_url\x18\x05 \x01(\tR\bcoverUrl\x12\x12\n" + - "\x04mode\x18\x06 \x01(\tR\x04mode\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\x12\x12\n" + - "\x04heat\x18\b \x01(\x03R\x04heat\x12!\n" + - "\fonline_count\x18\t \x01(\x05R\vonlineCount\x12\x1d\n" + - "\n" + - "seat_count\x18\n" + - " \x01(\x05R\tseatCount\x12.\n" + - "\x13occupied_seat_count\x18\v \x01(\x05R\x11occupiedSeatCount\x12*\n" + - "\x11visible_region_id\x18\f \x01(\x03R\x0fvisibleRegionId\x12\x19\n" + - "\bapp_code\x18\r \x01(\tR\aappCode\x12\"\n" + - "\rroom_short_id\x18\x0e \x01(\tR\vroomShortId\x12\x16\n" + - "\x06locked\x18\x0f \x01(\bR\x06locked\"g\n" + - "\x11ListRoomsResponse\x121\n" + - "\x05rooms\x18\x01 \x03(\v2\x1b.hyapp.room.v1.RoomListItemR\x05rooms\x12\x1f\n" + - "\vnext_cursor\x18\x02 \x01(\tR\n" + - "nextCursor\"\x96\x01\n" + - "\x17RoomGiftLeaderboardItem\x12\x12\n" + - "\x04rank\x18\x01 \x01(\x03R\x04rank\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x1d\n" + - "\n" + - "coin_spent\x18\x03 \x01(\x03R\tcoinSpent\x12/\n" + - "\x04room\x18\x04 \x01(\v2\x1b.hyapp.room.v1.RoomListItemR\x04room\"\xef\x01\n" + - "\x1fListRoomGiftLeaderboardResponse\x12<\n" + - "\x05items\x18\x01 \x03(\v2&.hyapp.room.v1.RoomGiftLeaderboardItemR\x05items\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12\x16\n" + - "\x06period\x18\x03 \x01(\tR\x06period\x12\x1e\n" + - "\vstart_at_ms\x18\x04 \x01(\x03R\tstartAtMs\x12\x1a\n" + - "\tend_at_ms\x18\x05 \x01(\x03R\aendAtMs\x12$\n" + - "\x0eserver_time_ms\x18\x06 \x01(\x03R\fserverTimeMs\"f\n" + - "\x10GetMyRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\"\n" + - "\rowner_user_id\x18\x02 \x01(\x03R\vownerUserId\"\x85\x01\n" + - "\x11GetMyRoomResponse\x12\x19\n" + - "\bhas_room\x18\x01 \x01(\bR\ahasRoom\x12/\n" + - "\x04room\x18\x02 \x01(\v2\x1b.hyapp.room.v1.RoomListItemR\x04room\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"`\n" + - "\x15GetCurrentRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\"\xd6\x02\n" + - "\x16GetCurrentRoomResponse\x12(\n" + - "\x10has_current_room\x18\x01 \x01(\bR\x0ehasCurrentRoom\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12!\n" + - "\froom_version\x18\x03 \x01(\x03R\vroomVersion\x12\x12\n" + - "\x04role\x18\x04 \x01(\tR\x04role\x12$\n" + - "\x0emic_session_id\x18\x05 \x01(\tR\fmicSessionId\x12#\n" + - "\rpublish_state\x18\x06 \x01(\tR\fpublishState\x12+\n" + - "\x12need_join_im_group\x18\a \x01(\bR\x0fneedJoinImGroup\x12$\n" + - "\x0eneed_rtc_token\x18\b \x01(\bR\fneedRtcToken\x12$\n" + - "\x0eserver_time_ms\x18\t \x01(\x03R\fserverTimeMs\"\x87\x01\n" + - "\x16GetRoomSnapshotRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\"\x91\x01\n" + - "\x17GetRoomSnapshotResponse\x12/\n" + - "\x04room\x18\x01 \x01(\v2\x1b.hyapp.room.v1.RoomSnapshotR\x04room\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\x12\x1f\n" + - "\vis_followed\x18\x03 \x01(\bR\n" + - "isFollowed\"\x85\x01\n" + - "\x14GetRoomRocketRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\"t\n" + - "\x15GetRoomRocketResponse\x125\n" + - "\x06rocket\x18\x01 \x01(\v2\x1d.hyapp.room.v1.RoomRocketInfoR\x06rocket\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xd0\x01\n" + - "\x1aListRoomOnlineUsersRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\x12\x12\n" + - "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x05 \x01(\x05R\bpageSize\x12\x12\n" + - "\x04sort\x18\x06 \x01(\tR\x04sort\"\xee\x01\n" + - "\x1bListRoomOnlineUsersResponse\x12-\n" + - "\x05users\x18\x01 \x03(\v2\x17.hyapp.room.v1.RoomUserR\x05users\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12\x12\n" + - "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12$\n" + - "\x0eserver_time_ms\x18\x05 \x01(\x03R\fserverTimeMs\x123\n" + - "\x05items\x18\x06 \x03(\v2\x1d.hyapp.room.v1.RoomOnlineUserR\x05items\"\xd2\x01\n" + - "\x0eRoomBannedUser\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\"\n" + - "\ractor_user_id\x18\x02 \x01(\x03R\vactorUserId\x12\"\n" + - "\rcreated_at_ms\x18\x03 \x01(\x03R\vcreatedAtMs\x12\x1e\n" + - "\vunban_at_ms\x18\x04 \x01(\x03R\tunbanAtMs\x12!\n" + - "\fremaining_ms\x18\x05 \x01(\x03R\vremainingMs\x12\x1c\n" + - "\tpermanent\x18\x06 \x01(\bR\tpermanent\"\xbc\x01\n" + - "\x1aListRoomBannedUsersRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0eviewer_user_id\x18\x03 \x01(\x03R\fviewerUserId\x12\x12\n" + - "\x04page\x18\x04 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x05 \x01(\x05R\bpageSize\"\xbf\x01\n" + - "\x1bListRoomBannedUsersResponse\x123\n" + - "\x05items\x18\x01 \x03(\v2\x1d.hyapp.room.v1.RoomBannedUserR\x05items\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12\x12\n" + - "\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12$\n" + - "\x0eserver_time_ms\x18\x05 \x01(\x03R\fserverTimeMs\"u\n" + - "\x11FollowRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"\x95\x01\n" + - "\x12FollowRoomResponse\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x1a\n" + - "\bfollowed\x18\x02 \x01(\bR\bfollowed\x12$\n" + - "\x0efollowed_at_ms\x18\x03 \x01(\x03R\ffollowedAtMs\x12$\n" + - "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\"w\n" + - "\x13UnfollowRoomRequest\x12.\n" + - "\x04meta\x18\x01 \x01(\v2\x1a.hyapp.room.v1.RequestMetaR\x04meta\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"q\n" + - "\x14UnfollowRoomResponse\x12\x17\n" + - "\aroom_id\x18\x01 \x01(\tR\x06roomId\x12\x1a\n" + - "\bfollowed\x18\x02 \x01(\bR\bfollowed\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs2\xad\x17\n" + - "\x12RoomCommandService\x12Q\n" + - "\n" + - "CreateRoom\x12 .hyapp.room.v1.CreateRoomRequest\x1a!.hyapp.room.v1.CreateRoomResponse\x12f\n" + - "\x11UpdateRoomProfile\x12'.hyapp.room.v1.UpdateRoomProfileRequest\x1a(.hyapp.room.v1.UpdateRoomProfileResponse\x12i\n" + - "\x12SaveRoomBackground\x12(.hyapp.room.v1.SaveRoomBackgroundRequest\x1a).hyapp.room.v1.SaveRoomBackgroundResponse\x12f\n" + - "\x11SetRoomBackground\x12'.hyapp.room.v1.SetRoomBackgroundRequest\x1a(.hyapp.room.v1.SetRoomBackgroundResponse\x12K\n" + - "\bJoinRoom\x12\x1e.hyapp.room.v1.JoinRoomRequest\x1a\x1f.hyapp.room.v1.JoinRoomResponse\x12Z\n" + - "\rRoomHeartbeat\x12#.hyapp.room.v1.RoomHeartbeatRequest\x1a$.hyapp.room.v1.RoomHeartbeatResponse\x12N\n" + - "\tLeaveRoom\x12\x1f.hyapp.room.v1.LeaveRoomRequest\x1a .hyapp.room.v1.LeaveRoomResponse\x12N\n" + - "\tCloseRoom\x12\x1f.hyapp.room.v1.CloseRoomRequest\x1a .hyapp.room.v1.CloseRoomResponse\x12`\n" + - "\x0fAdminUpdateRoom\x12%.hyapp.room.v1.AdminUpdateRoomRequest\x1a&.hyapp.room.v1.AdminUpdateRoomResponse\x12`\n" + - "\x0fAdminDeleteRoom\x12%.hyapp.room.v1.AdminDeleteRoomRequest\x1a&.hyapp.room.v1.AdminDeleteRoomResponse\x12\x84\x01\n" + - "\x1bAdminUpdateRoomRocketConfig\x121.hyapp.room.v1.AdminUpdateRoomRocketConfigRequest\x1a2.hyapp.room.v1.AdminUpdateRoomRocketConfigResponse\x12~\n" + - "\x19AdminUpdateRoomSeatConfig\x12/.hyapp.room.v1.AdminUpdateRoomSeatConfigRequest\x1a0.hyapp.room.v1.AdminUpdateRoomSeatConfigResponse\x12i\n" + - "\x12AdminCreateRoomPin\x12(.hyapp.room.v1.AdminCreateRoomPinRequest\x1a).hyapp.room.v1.AdminCreateRoomPinResponse\x12i\n" + - "\x12AdminCancelRoomPin\x12(.hyapp.room.v1.AdminCancelRoomPinRequest\x1a).hyapp.room.v1.AdminCancelRoomPinResponse\x12B\n" + - "\x05MicUp\x12\x1b.hyapp.room.v1.MicUpRequest\x1a\x1c.hyapp.room.v1.MicUpResponse\x12H\n" + - "\aMicDown\x12\x1d.hyapp.room.v1.MicDownRequest\x1a\x1e.hyapp.room.v1.MicDownResponse\x12Z\n" + - "\rChangeMicSeat\x12#.hyapp.room.v1.ChangeMicSeatRequest\x1a$.hyapp.room.v1.ChangeMicSeatResponse\x12o\n" + - "\x14ConfirmMicPublishing\x12*.hyapp.room.v1.ConfirmMicPublishingRequest\x1a+.hyapp.room.v1.ConfirmMicPublishingResponse\x12W\n" + - "\fMicHeartbeat\x12\".hyapp.room.v1.MicHeartbeatRequest\x1a#.hyapp.room.v1.MicHeartbeatResponse\x12Q\n" + - "\n" + - "SetMicMute\x12 .hyapp.room.v1.SetMicMuteRequest\x1a!.hyapp.room.v1.SetMicMuteResponse\x12Z\n" + - "\rApplyRTCEvent\x12#.hyapp.room.v1.ApplyRTCEventRequest\x1a$.hyapp.room.v1.ApplyRTCEventResponse\x12]\n" + - "\x0eSetMicSeatLock\x12$.hyapp.room.v1.SetMicSeatLockRequest\x1a%.hyapp.room.v1.SetMicSeatLockResponse\x12]\n" + - "\x0eSetChatEnabled\x12$.hyapp.room.v1.SetChatEnabledRequest\x1a%.hyapp.room.v1.SetChatEnabledResponse\x12`\n" + - "\x0fSetRoomPassword\x12%.hyapp.room.v1.SetRoomPasswordRequest\x1a&.hyapp.room.v1.SetRoomPasswordResponse\x12W\n" + - "\fSetRoomAdmin\x12\".hyapp.room.v1.SetRoomAdminRequest\x1a#.hyapp.room.v1.SetRoomAdminResponse\x12K\n" + - "\bMuteUser\x12\x1e.hyapp.room.v1.MuteUserRequest\x1a\x1f.hyapp.room.v1.MuteUserResponse\x12K\n" + - "\bKickUser\x12\x1e.hyapp.room.v1.KickUserRequest\x1a\x1f.hyapp.room.v1.KickUserResponse\x12N\n" + - "\tUnbanUser\x12\x1f.hyapp.room.v1.UnbanUserRequest\x1a .hyapp.room.v1.UnbanUserResponse\x12`\n" + - "\x0fSystemEvictUser\x12%.hyapp.room.v1.SystemEvictUserRequest\x1a&.hyapp.room.v1.SystemEvictUserResponse\x12K\n" + - "\bSendGift\x12\x1e.hyapp.room.v1.SendGiftRequest\x1a\x1f.hyapp.room.v1.SendGiftResponse\x12Q\n" + - "\n" + - "FollowRoom\x12 .hyapp.room.v1.FollowRoomRequest\x1a!.hyapp.room.v1.FollowRoomResponse\x12W\n" + - "\fUnfollowRoom\x12\".hyapp.room.v1.UnfollowRoomRequest\x1a#.hyapp.room.v1.UnfollowRoomResponse2\xee\x01\n" + - "\x10RoomGuardService\x12o\n" + - "\x14CheckSpeakPermission\x12*.hyapp.room.v1.CheckSpeakPermissionRequest\x1a+.hyapp.room.v1.CheckSpeakPermissionResponse\x12i\n" + - "\x12VerifyRoomPresence\x12(.hyapp.room.v1.VerifyRoomPresenceRequest\x1a).hyapp.room.v1.VerifyRoomPresenceResponse2\xff\v\n" + - "\x10RoomQueryService\x12]\n" + - "\x0eAdminListRooms\x12$.hyapp.room.v1.AdminListRoomsRequest\x1a%.hyapp.room.v1.AdminListRoomsResponse\x12W\n" + - "\fAdminGetRoom\x12\".hyapp.room.v1.AdminGetRoomRequest\x1a#.hyapp.room.v1.AdminGetRoomResponse\x12{\n" + - "\x18AdminGetRoomRocketConfig\x12..hyapp.room.v1.AdminGetRoomRocketConfigRequest\x1a/.hyapp.room.v1.AdminGetRoomRocketConfigResponse\x12u\n" + - "\x16AdminGetRoomSeatConfig\x12,.hyapp.room.v1.AdminGetRoomSeatConfigRequest\x1a-.hyapp.room.v1.AdminGetRoomSeatConfigResponse\x12f\n" + - "\x11AdminListRoomPins\x12'.hyapp.room.v1.AdminListRoomPinsRequest\x1a(.hyapp.room.v1.AdminListRoomPinsResponse\x12N\n" + - "\tListRooms\x12\x1f.hyapp.room.v1.ListRoomsRequest\x1a .hyapp.room.v1.ListRoomsResponse\x12V\n" + - "\rListRoomFeeds\x12#.hyapp.room.v1.ListRoomFeedsRequest\x1a .hyapp.room.v1.ListRoomsResponse\x12x\n" + - "\x17ListRoomGiftLeaderboard\x12-.hyapp.room.v1.ListRoomGiftLeaderboardRequest\x1a..hyapp.room.v1.ListRoomGiftLeaderboardResponse\x12N\n" + - "\tGetMyRoom\x12\x1f.hyapp.room.v1.GetMyRoomRequest\x1a .hyapp.room.v1.GetMyRoomResponse\x12]\n" + - "\x0eGetCurrentRoom\x12$.hyapp.room.v1.GetCurrentRoomRequest\x1a%.hyapp.room.v1.GetCurrentRoomResponse\x12`\n" + - "\x0fGetRoomSnapshot\x12%.hyapp.room.v1.GetRoomSnapshotRequest\x1a&.hyapp.room.v1.GetRoomSnapshotResponse\x12l\n" + - "\x13ListRoomBackgrounds\x12).hyapp.room.v1.ListRoomBackgroundsRequest\x1a*.hyapp.room.v1.ListRoomBackgroundsResponse\x12Z\n" + - "\rGetRoomRocket\x12#.hyapp.room.v1.GetRoomRocketRequest\x1a$.hyapp.room.v1.GetRoomRocketResponse\x12l\n" + - "\x13ListRoomOnlineUsers\x12).hyapp.room.v1.ListRoomOnlineUsersRequest\x1a*.hyapp.room.v1.ListRoomOnlineUsersResponse\x12l\n" + - "\x13ListRoomBannedUsers\x12).hyapp.room.v1.ListRoomBannedUsersRequest\x1a*.hyapp.room.v1.ListRoomBannedUsersResponseB&Z$hyapp.local/api/proto/room/v1;roomv1b\x06proto3" +var file_proto_room_v1_room_proto_rawDesc = []byte{ + 0x0a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, 0x76, 0x31, 0x2f, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x22, 0x88, 0x02, 0x0a, 0x0b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x0a, 0x73, + 0x65, 0x6e, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x73, 0x65, 0x6e, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x22, 0x72, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x80, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x6f, + 0x6d, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, + 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, + 0x6e, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, + 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xdd, 0x01, 0x0a, 0x0e, + 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, + 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x6a, 0x6f, 0x69, 0x6e, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6a, + 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x25, 0x0a, 0x0f, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65, 0x6e, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0xb2, 0x03, 0x0a, 0x09, + 0x53, 0x65, 0x61, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, + 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, + 0x4e, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, + 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, + 0x6b, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, 0x5f, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2e, + 0x0a, 0x13, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x69, + 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x73, 0x12, 0x37, + 0x0a, 0x18, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x15, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x0a, 0x1a, 0x6c, 0x61, 0x73, 0x74, 0x5f, + 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x6c, 0x61, 0x73, + 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x63, 0x5f, 0x6d, 0x75, 0x74, 0x65, 0x64, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x69, 0x63, 0x4d, 0x75, 0x74, 0x65, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x69, 0x63, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, + 0x6d, 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x41, 0x74, 0x4d, 0x73, + 0x22, 0x7c, 0x0a, 0x08, 0x52, 0x61, 0x6e, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, + 0x69, 0x66, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x67, 0x69, 0x66, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb0, + 0x06, 0x0a, 0x13, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x64, 0x72, 0x61, 0x77, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, + 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, + 0x6c, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x72, 0x75, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, + 0x0f, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x65, 0x6e, + 0x63, 0x65, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x65, 0x64, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x69, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, + 0x70, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, + 0x6c, 0x69, 0x65, 0x72, 0x50, 0x70, 0x6d, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x73, 0x65, 0x5f, + 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0f, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, + 0x69, 0x6e, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x61, 0x74, 0x6d, 0x6f, + 0x73, 0x70, 0x68, 0x65, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, + 0x69, 0x6e, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x19, 0x72, 0x6f, 0x6f, 0x6d, 0x41, + 0x74, 0x6d, 0x6f, 0x73, 0x70, 0x68, 0x65, 0x72, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, + 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, + 0x5f, 0x73, 0x75, 0x62, 0x73, 0x69, 0x64, 0x79, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x53, 0x75, + 0x62, 0x73, 0x69, 0x64, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x16, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x63, + 0x6f, 0x69, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x14, 0x65, 0x66, 0x66, 0x65, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x69, 0x6e, 0x73, + 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x66, + 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x27, 0x0a, 0x0f, + 0x68, 0x69, 0x67, 0x68, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x69, 0x67, 0x68, 0x4d, 0x75, 0x6c, 0x74, 0x69, + 0x70, 0x6c, 0x69, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2c, 0x0a, + 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, + 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x22, 0xbe, 0x01, 0x0a, 0x14, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, + 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, + 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, 0x6f, 0x6e, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x63, 0x6f, 0x6e, 0x55, + 0x72, 0x6c, 0x22, 0xd3, 0x03, 0x0a, 0x0f, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, + 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, + 0x6f, 0x6c, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, + 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x5f, + 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x41, 0x6e, 0x69, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x61, 0x75, 0x6e, 0x63, + 0x68, 0x65, 0x64, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x49, 0x6d, 0x61, + 0x67, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x4b, 0x0a, 0x0f, 0x69, 0x6e, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, + 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x0d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x73, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x74, + 0x6f, 0x70, 0x31, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x12, 0x4c, 0x0a, 0x0f, 0x69, 0x67, + 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x09, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0e, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x22, 0x94, 0x02, 0x0a, 0x15, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, + 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x6f, 0x6c, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, + 0x6f, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, + 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x21, + 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x69, 0x63, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x19, 0x0a, 0x08, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, + 0xe7, 0x02, 0x0a, 0x17, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x72, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x25, + 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x67, + 0x6e, 0x69, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x61, 0x75, + 0x6e, 0x63, 0x68, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x74, + 0x6f, 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x26, 0x0a, + 0x0f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x22, 0xce, 0x04, 0x0a, 0x0f, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, + 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x75, + 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x46, 0x75, 0x65, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x74, 0x68, + 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x66, + 0x75, 0x65, 0x6c, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x6c, 0x61, 0x75, 0x6e, + 0x63, 0x68, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, + 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x1e, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x73, 0x65, 0x74, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x31, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x70, 0x31, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x69, 0x67, 0x6e, 0x69, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x69, 0x67, 0x6e, + 0x69, 0x74, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, + 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x18, 0x0d, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x0b, 0x6c, 0x61, 0x73, 0x74, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x73, 0x12, 0x51, 0x0a, 0x10, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x5f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x52, 0x0f, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x22, 0xed, 0x02, 0x0a, 0x0e, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x18, 0x0a, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, + 0x34, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x62, + 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x5f, 0x64, + 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6c, + 0x61, 0x75, 0x6e, 0x63, 0x68, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, + 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, + 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, + 0x61, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, + 0x74, 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0xd2, 0x01, 0x0a, 0x16, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x46, 0x75, 0x65, + 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x75, 0x6c, 0x65, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, 0x72, 0x5f, 0x70, 0x70, 0x6d, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x69, 0x65, + 0x72, 0x50, 0x70, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x66, 0x75, + 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x66, 0x69, 0x78, 0x65, 0x64, 0x46, + 0x75, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x22, + 0xee, 0x04, 0x0a, 0x15, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x65, 0x6c, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, + 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0d, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2b, + 0x0a, 0x11, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x62, 0x72, 0x6f, 0x61, 0x64, + 0x63, 0x61, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x62, + 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x53, + 0x63, 0x6f, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, + 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x10, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, + 0x4d, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x74, 0x61, + 0x63, 0x6b, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x11, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x36, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x0a, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x4d, 0x0a, 0x0f, 0x67, 0x69, + 0x66, 0x74, 0x5f, 0x66, 0x75, 0x65, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x69, + 0x66, 0x74, 0x46, 0x75, 0x65, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x67, 0x69, 0x66, 0x74, + 0x46, 0x75, 0x65, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, + 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, + 0x22, 0x51, 0x0a, 0x1f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x22, 0x86, 0x01, 0x0a, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xad, 0x01, 0x0a, + 0x22, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x89, 0x01, 0x0a, + 0x23, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xcb, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x32, 0x0a, 0x15, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x65, + 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, + 0x13, 0x63, 0x61, 0x6e, 0x64, 0x69, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, + 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x05, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, + 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x10, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x4f, 0x0a, 0x1d, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, + 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x82, 0x01, 0x0a, 0x1e, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xb0, 0x01, 0x0a, + 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x2e, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x61, + 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x52, 0x11, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x73, 0x65, 0x61, + 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x64, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, + 0x85, 0x01, 0x0a, 0x21, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, + 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, + 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, + 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x22, 0xfb, 0x03, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, + 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, + 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x77, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x77, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x69, + 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x63, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x6c, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x15, 0x63, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6c, 0x65, + 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, + 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x4d, 0x73, 0x12, 0x33, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x69, 0x6e, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x69, 0x6e, 0x54, 0x79, + 0x70, 0x65, 0x22, 0xf4, 0x01, 0x0a, 0x18, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, + 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x70, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x22, 0x88, 0x01, 0x0a, 0x19, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x69, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x50, + 0x69, 0x6e, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x24, + 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, + 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x9d, 0x02, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, + 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x77, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x77, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x64, 0x61, 0x79, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x79, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x6e, 0x65, + 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x69, 0x6e, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x69, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x22, 0x71, 0x0a, 0x1a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x03, 0x70, 0x69, + 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x7d, 0x0a, 0x19, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x70, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x70, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x71, 0x0a, 0x1a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x03, + 0x70, 0x69, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x52, 0x6f, + 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x22, + 0xd5, 0x06, 0x0a, 0x0c, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x68, 0x61, + 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x63, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x09, + 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x61, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x6d, 0x69, 0x63, 0x53, 0x65, + 0x61, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x0c, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, + 0x24, 0x0a, 0x0e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0c, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x62, 0x61, 0x6e, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0a, 0x62, 0x61, 0x6e, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x75, 0x74, 0x65, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, + 0x6d, 0x75, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x34, 0x0a, 0x09, 0x67, + 0x69, 0x66, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x61, 0x6e, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x52, 0x61, 0x6e, + 0x6b, 0x12, 0x43, 0x0a, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x65, 0x78, 0x74, 0x18, 0x0d, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x45, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x45, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x74, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x65, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, + 0x74, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x36, 0x0a, 0x06, 0x72, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, + 0x3a, 0x0a, 0x0a, 0x62, 0x61, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x18, 0x15, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x09, 0x62, 0x61, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x52, + 0x6f, 0x6f, 0x6d, 0x45, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x01, 0x0a, 0x13, 0x52, 0x6f, 0x6f, 0x6d, + 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, + 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, + 0x81, 0x01, 0x0a, 0x19, 0x53, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, + 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, + 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x55, 0x72, 0x6c, 0x22, 0x86, 0x01, 0x0a, 0x1a, 0x53, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x42, 0x0a, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x62, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x8b, 0x01, 0x0a, + 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xc1, 0x01, 0x0a, 0x1b, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0b, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x52, 0x0b, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, + 0x12, 0x36, 0x0a, 0x17, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x61, 0x63, + 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x15, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x42, 0x61, 0x63, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x6f, + 0x0a, 0x18, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, + 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x64, 0x22, + 0xc6, 0x01, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, + 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x42, 0x0a, 0x0a, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, + 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, + 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0xaf, 0x02, 0x0a, 0x11, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, + 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x29, 0x0a, 0x10, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, + 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, + 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x22, 0x7b, 0x0a, 0x12, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0xa8, 0x02, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x4e, + 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x24, 0x0a, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x61, + 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x0a, 0x72, + 0x6f, 0x6f, 0x6d, 0x41, 0x76, 0x61, 0x74, 0x61, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0f, 0x72, 0x6f, 0x6f, 0x6d, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x0a, + 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, + 0x48, 0x03, 0x52, 0x09, 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x88, 0x01, 0x01, + 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0e, + 0x0a, 0x0c, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x42, 0x13, + 0x0a, 0x11, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x82, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, + 0x6d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0xc7, 0x02, 0x0a, 0x18, 0x52, 0x6f, 0x6f, 0x6d, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, + 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, + 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6a, 0x73, + 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x22, 0x0a, + 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, + 0x73, 0x22, 0x91, 0x02, 0x0a, 0x0f, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x4c, 0x0a, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x76, + 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, + 0x6d, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x56, 0x65, 0x68, 0x69, 0x63, 0x6c, 0x65, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x0c, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x56, 0x65, 0x68, 0x69, + 0x63, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, + 0x63, 0x74, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x26, 0x0a, + 0x0f, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xa6, 0x01, 0x0a, 0x10, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x12, 0x2b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x2f, 0x0a, + 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x46, + 0x0a, 0x14, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xab, 0x01, 0x0a, 0x15, 0x52, 0x6f, 0x6f, 0x6d, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, + 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x42, 0x0a, 0x10, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x7a, 0x0a, 0x11, 0x4c, 0x65, 0x61, 0x76, + 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, + 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x5a, 0x0a, 0x10, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x22, 0x7a, 0x0a, 0x11, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, + 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x8f, 0x05, 0x0a, + 0x11, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, + 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, + 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, + 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, + 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x2f, + 0x0a, 0x14, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, 0x69, + 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6c, + 0x6f, 0x73, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x20, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x41, 0x74, 0x4d, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x04, 0x68, 0x65, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x74, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, + 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x63, 0x63, 0x75, 0x70, + 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0x53, 0x65, + 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x6f, 0x72, + 0x74, 0x53, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xba, + 0x02, 0x0a, 0x15, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, + 0x6f, 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x62, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x72, 0x74, 0x42, 0x79, + 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x6f, 0x72, 0x74, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x16, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x5e, 0x0a, 0x13, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x22, 0x72, 0x0a, 0x14, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, + 0x65, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xc2, + 0x03, 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, + 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x03, 0x52, 0x04, 0x6d, + 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x12, 0x1b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x48, 0x04, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x88, 0x01, 0x01, 0x12, 0x2f, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x48, 0x05, + 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x73, + 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, + 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6d, 0x6f, + 0x64, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x14, 0x0a, + 0x12, 0x5f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x22, 0x80, 0x01, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x80, 0x01, 0x0a, 0x17, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, + 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x57, + 0x0a, 0x0c, 0x4d, 0x69, 0x63, 0x55, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, + 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, + 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x22, 0xe5, 0x01, 0x0a, 0x0d, 0x4d, 0x69, 0x63, 0x55, + 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, + 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x2e, 0x0a, 0x13, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x64, 0x65, 0x61, 0x64, 0x6c, + 0x69, 0x6e, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x4d, 0x73, 0x22, + 0x7e, 0x0a, 0x0e, 0x4d, 0x69, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, + 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, + 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, + 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, + 0x6f, 0x6f, 0x6d, 0x22, 0x85, 0x01, 0x0a, 0x14, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x69, + 0x63, 0x53, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x22, 0x7e, 0x0a, 0x15, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, + 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0xf8, 0x01, 0x0a, 0x1b, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4d, 0x69, 0x63, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, + 0x6f, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x72, 0x6d, 0x4d, 0x69, 0x63, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, + 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x13, 0x4d, 0x69, 0x63, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, + 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, + 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xc5, 0x01, 0x0a, 0x14, + 0x4d, 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, + 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, + 0x74, 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, + 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x69, 0x63, 0x5f, 0x68, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x10, 0x6d, 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x41, + 0x74, 0x4d, 0x73, 0x22, 0x7f, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x6d, + 0x75, 0x74, 0x65, 0x64, 0x22, 0x94, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, + 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x8b, 0x02, 0x0a, 0x14, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2a, 0x0a, + 0x11, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x97, 0x01, 0x0a, 0x15, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x65, 0x61, + 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x65, 0x61, 0x74, + 0x4e, 0x6f, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, + 0x6f, 0x6f, 0x6d, 0x22, 0x78, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, + 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, + 0x73, 0x65, 0x61, 0x74, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, + 0x65, 0x61, 0x74, 0x4e, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x7f, 0x0a, + 0x16, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, + 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x61, + 0x0a, 0x15, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x22, 0x7f, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, + 0x6f, 0x6d, 0x22, 0x7c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, + 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, + 0x63, 0x6b, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x22, 0x80, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, + 0x6f, 0x6f, 0x6d, 0x22, 0x85, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x7d, 0x0a, 0x14, 0x53, + 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, + 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x7d, 0x0a, 0x0f, 0x4d, 0x75, + 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x05, 0x6d, 0x75, 0x74, 0x65, 0x64, 0x22, 0x79, 0x0a, 0x10, 0x4d, 0x75, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, + 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, + 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x88, 0x01, 0x0a, 0x0f, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x22, + 0xbe, 0x01, 0x0a, 0x10, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, + 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x72, + 0x74, 0x63, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x72, 0x74, 0x63, 0x4b, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x74, + 0x63, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x74, 0x63, 0x4b, 0x69, 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0x68, 0x0a, 0x10, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x7a, 0x0a, 0x11, 0x55, 0x6e, + 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0xd4, 0x01, 0x0a, 0x16, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x62, 0x61, 0x6e, + 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0b, 0x62, 0x61, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x52, 0x6f, 0x6f, 0x6d, 0x22, 0x88, 0x02, + 0x0a, 0x17, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61, 0x64, + 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61, 0x64, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, + 0x6f, 0x6f, 0x6d, 0x12, 0x34, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, + 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, + 0x6d, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x74, 0x63, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x65, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x74, 0x63, 0x4b, 0x69, 0x63, 0x6b, + 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x72, 0x74, 0x63, 0x5f, 0x6b, 0x69, 0x63, 0x6b, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x74, 0x63, 0x4b, + 0x69, 0x63, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xee, 0x03, 0x0a, 0x0f, 0x53, 0x65, 0x6e, + 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, + 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x03, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x73, 0x48, 0x6f, + 0x73, 0x74, 0x12, 0x31, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x6f, 0x73, + 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x12, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, + 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, + 0x11, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x22, 0xba, 0x03, 0x0a, 0x10, 0x53, 0x65, + 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, + 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x68, 0x65, 0x61, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x74, 0x12, + 0x34, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x61, 0x6e, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x67, 0x69, 0x66, + 0x74, 0x52, 0x61, 0x6e, 0x6b, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x36, 0x0a, 0x06, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x06, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x41, + 0x0a, 0x0a, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x44, 0x72, 0x61, 0x77, + 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x09, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, + 0x74, 0x12, 0x43, 0x0a, 0x0b, 0x6c, 0x75, 0x63, 0x6b, 0x79, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x73, + 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, + 0x44, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0a, 0x6c, 0x75, 0x63, 0x6b, + 0x79, 0x47, 0x69, 0x66, 0x74, 0x73, 0x22, 0x6a, 0x0a, 0x1b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, + 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x22, 0x73, 0x0a, 0x1c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, + 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa6, 0x01, 0x0a, 0x19, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x22, 0x71, 0x0a, 0x1a, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, + 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x6f, 0x6f, 0x6d, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0xea, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, + 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, + 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, + 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x62, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, + 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x22, 0xb7, 0x02, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x46, 0x65, 0x65, + 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, + 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x2a, 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, + 0x62, 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x74, + 0x61, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x62, 0x12, 0x16, 0x0a, + 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, + 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x47, 0x0a, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x46, 0x65, 0x65, + 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x0c, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x22, 0x99, 0x01, 0x0a, 0x1e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x0a, + 0x06, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, + 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, + 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x63, 0x0a, 0x13, 0x52, 0x6f, 0x6f, 0x6d, 0x46, 0x65, + 0x65, 0x64, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, + 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x16, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb3, 0x03, 0x0a, 0x0c, + 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x12, 0x0a, 0x04, + 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x74, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x68, 0x65, 0x61, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0b, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e, + 0x0a, 0x13, 0x6f, 0x63, 0x63, 0x75, 0x70, 0x69, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x61, 0x74, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x6f, 0x63, 0x63, + 0x75, 0x70, 0x69, 0x65, 0x64, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, + 0x0a, 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x6c, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, + 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, + 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x73, 0x68, + 0x6f, 0x72, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x6f, + 0x6f, 0x6d, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x63, + 0x6b, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x22, 0x67, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, + 0x65, 0x6d, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x65, 0x78, + 0x74, 0x5f, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x6e, 0x65, 0x78, 0x74, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x22, 0x96, 0x01, 0x0a, 0x17, 0x52, + 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x72, 0x61, 0x6e, 0x6b, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, + 0x6d, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, + 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x72, + 0x6f, 0x6f, 0x6d, 0x22, 0xef, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, + 0x47, 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, + 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, + 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, + 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x66, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0d, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x85, 0x01, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x2f, + 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, + 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, + 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, + 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, + 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xd6, 0x02, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x43, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x61, 0x73, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x68, 0x61, + 0x73, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x6f, 0x6f, + 0x6d, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x0e, + 0x6d, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x69, 0x63, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2b, 0x0a, 0x12, 0x6e, 0x65, 0x65, 0x64, 0x5f, + 0x6a, 0x6f, 0x69, 0x6e, 0x5f, 0x69, 0x6d, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0f, 0x6e, 0x65, 0x65, 0x64, 0x4a, 0x6f, 0x69, 0x6e, 0x49, 0x6d, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x65, 0x65, 0x64, 0x5f, 0x72, 0x74, 0x63, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x65, + 0x65, 0x64, 0x52, 0x74, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, + 0x22, 0x87, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, + 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x47, + 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, + 0x74, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x69, 0x73, 0x5f, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x22, 0x85, + 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, + 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x74, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x35, 0x0a, 0x06, 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, + 0x72, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xd0, 0x01, 0x0a, + 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, + 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x22, + 0xee, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, + 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2d, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x6f, 0x6f, 0x6d, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x12, 0x33, 0x0a, 0x05, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, + 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x22, 0xd2, 0x01, 0x0a, 0x0e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, + 0x73, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, + 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x75, 0x6e, 0x62, 0x61, 0x6e, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x6e, 0x62, 0x61, 0x6e, + 0x41, 0x74, 0x4d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x61, + 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x4d, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, + 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, + 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x22, 0xbc, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, + 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, + 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, + 0x53, 0x69, 0x7a, 0x65, 0x22, 0xbf, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, + 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, + 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, + 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x75, 0x0a, 0x11, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x6d, + 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x95, 0x01, + 0x0a, 0x12, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, + 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, + 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x77, 0x0a, 0x13, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, + 0x6d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x71, + 0x0a, 0x14, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, + 0x1a, 0x0a, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, + 0x73, 0x32, 0xad, 0x17, 0x0a, 0x12, 0x52, 0x6f, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, + 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x66, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x53, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x42, + 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x52, 0x6f, + 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, + 0x0a, 0x11, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, + 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, + 0x6f, 0x6d, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x69, 0x6e, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x72, 0x74, + 0x62, 0x65, 0x61, 0x74, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x48, 0x65, + 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4e, 0x0a, 0x09, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1f, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, + 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, + 0x61, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4e, 0x0a, 0x09, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1f, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x6f, + 0x73, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x6f, 0x73, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x60, 0x0a, 0x0f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6f, 0x6d, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, + 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x84, 0x01, 0x0a, 0x1b, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x19, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, + 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, + 0x50, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x12, 0x28, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x42, 0x0a, 0x05, 0x4d, 0x69, 0x63, 0x55, 0x70, 0x12, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x63, 0x55, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x63, 0x55, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x07, 0x4d, 0x69, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x12, + 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x69, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x69, 0x63, 0x44, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, + 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x12, + 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4d, 0x69, 0x63, 0x53, 0x65, + 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4d, 0x69, 0x63, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4d, 0x69, 0x63, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4d, 0x69, 0x63, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x4d, + 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x22, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x63, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x4d, 0x69, 0x63, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, + 0x74, 0x65, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x4d, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x54, + 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x52, 0x54, 0x43, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, + 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, + 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x4d, + 0x69, 0x63, 0x53, 0x65, 0x61, 0x74, 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x43, 0x68, + 0x61, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, + 0x6f, 0x6f, 0x6d, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, + 0x6d, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, + 0x4d, 0x75, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x4b, 0x69, 0x63, + 0x6b, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x69, 0x63, 0x6b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, + 0x73, 0x65, 0x72, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x62, 0x61, 0x6e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x45, 0x76, 0x69, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x64, + 0x47, 0x69, 0x66, 0x74, 0x12, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, + 0x6f, 0x6f, 0x6d, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x46, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x55, 0x6e, 0x66, 0x6f, + 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, + 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x66, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0xee, 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x75, 0x61, 0x72, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6f, 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, + 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x53, 0x70, 0x65, 0x61, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x12, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x28, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x6f, + 0x6f, 0x6d, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x32, 0xff, 0x0b, 0x0a, 0x10, 0x52, 0x6f, 0x6f, 0x6d, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, + 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, + 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x7b, 0x0a, 0x18, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x16, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, + 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x53, 0x65, 0x61, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x11, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x73, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x50, + 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x09, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, + 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0d, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x46, 0x65, 0x65, 0x64, 0x73, 0x12, 0x23, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x46, 0x65, 0x65, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, + 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x12, 0x2d, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x47, 0x69, 0x66, 0x74, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, + 0x09, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1f, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4d, + 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, + 0x0e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, + 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x12, + 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, + 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, + 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, + 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, + 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x23, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, + 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x6f, 0x6f, 0x6d, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, + 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, + 0x6d, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x26, 0x5a, 0x24, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, + 0x63, 0x61, 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, + 0x6f, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x6f, 0x6f, 0x6d, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} var ( file_proto_room_v1_room_proto_rawDescOnce sync.Once - file_proto_room_v1_room_proto_rawDescData []byte + file_proto_room_v1_room_proto_rawDescData = file_proto_room_v1_room_proto_rawDesc ) func file_proto_room_v1_room_proto_rawDescGZIP() []byte { file_proto_room_v1_room_proto_rawDescOnce.Do(func() { - file_proto_room_v1_room_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_room_v1_room_proto_rawDesc), len(file_proto_room_v1_room_proto_rawDesc))) + file_proto_room_v1_room_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_room_v1_room_proto_rawDescData) }) return file_proto_room_v1_room_proto_rawDescData } @@ -10543,7 +11750,7 @@ func file_proto_room_v1_room_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_room_v1_room_proto_rawDesc), len(file_proto_room_v1_room_proto_rawDesc)), + RawDescriptor: file_proto_room_v1_room_proto_rawDesc, NumEnums: 0, NumMessages: 125, NumExtensions: 0, @@ -10554,6 +11761,7 @@ func file_proto_room_v1_room_proto_init() { MessageInfos: file_proto_room_v1_room_proto_msgTypes, }.Build() File_proto_room_v1_room_proto = out.File + file_proto_room_v1_room_proto_rawDesc = nil file_proto_room_v1_room_proto_goTypes = nil file_proto_room_v1_room_proto_depIdxs = nil } diff --git a/api/proto/room/v1/room.proto b/api/proto/room/v1/room.proto index 79bd073c..9dc29be0 100644 --- a/api/proto/room/v1/room.proto +++ b/api/proto/room/v1/room.proto @@ -468,6 +468,8 @@ message JoinRoomRequest { // password 只用于本次入房校验;room-service 不把明文写入 command log 或快照。 string password = 3; RoomEntryVehicleSnapshot entry_vehicle = 4; + int64 actor_country_id = 5; + int64 actor_region_id = 6; } // JoinRoomResponse 返回加入后的房间快照。 @@ -841,6 +843,8 @@ message SendGiftRequest { int64 target_agency_owner_user_id = 10; // sender_region_id 是 gateway 从 user-service 当前送礼用户资料注入的区域,用于 wallet 匹配礼物钻石比例。 int64 sender_region_id = 11; + // sender_country_id 是 gateway 从 user-service 当前送礼用户资料注入的真实国家,用于统计国家维度。 + int64 sender_country_id = 12; } // SendGiftResponse 返回扣费成功并落到房间后的状态结果。 diff --git a/api/proto/room/v1/room_grpc.pb.go b/api/proto/room/v1/room_grpc.pb.go index 03a9df6a..fd38b5d4 100644 --- a/api/proto/room/v1/room_grpc.pb.go +++ b/api/proto/room/v1/room_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.6.2 +// - protoc-gen-go-grpc v1.5.1 // - protoc v7.35.0 // source: proto/room/v1/room.proto @@ -470,100 +470,100 @@ type RoomCommandServiceServer interface { type UnimplementedRoomCommandServiceServer struct{} func (UnimplementedRoomCommandServiceServer) CreateRoom(context.Context, *CreateRoomRequest) (*CreateRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateRoom not implemented") } func (UnimplementedRoomCommandServiceServer) UpdateRoomProfile(context.Context, *UpdateRoomProfileRequest) (*UpdateRoomProfileResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateRoomProfile not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateRoomProfile not implemented") } func (UnimplementedRoomCommandServiceServer) SaveRoomBackground(context.Context, *SaveRoomBackgroundRequest) (*SaveRoomBackgroundResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SaveRoomBackground not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SaveRoomBackground not implemented") } func (UnimplementedRoomCommandServiceServer) SetRoomBackground(context.Context, *SetRoomBackgroundRequest) (*SetRoomBackgroundResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetRoomBackground not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetRoomBackground not implemented") } func (UnimplementedRoomCommandServiceServer) JoinRoom(context.Context, *JoinRoomRequest) (*JoinRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method JoinRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method JoinRoom not implemented") } func (UnimplementedRoomCommandServiceServer) RoomHeartbeat(context.Context, *RoomHeartbeatRequest) (*RoomHeartbeatResponse, error) { - return nil, status.Error(codes.Unimplemented, "method RoomHeartbeat not implemented") + return nil, status.Errorf(codes.Unimplemented, "method RoomHeartbeat not implemented") } func (UnimplementedRoomCommandServiceServer) LeaveRoom(context.Context, *LeaveRoomRequest) (*LeaveRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method LeaveRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method LeaveRoom not implemented") } func (UnimplementedRoomCommandServiceServer) CloseRoom(context.Context, *CloseRoomRequest) (*CloseRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CloseRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CloseRoom not implemented") } func (UnimplementedRoomCommandServiceServer) AdminUpdateRoom(context.Context, *AdminUpdateRoomRequest) (*AdminUpdateRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoom not implemented") } func (UnimplementedRoomCommandServiceServer) AdminDeleteRoom(context.Context, *AdminDeleteRoomRequest) (*AdminDeleteRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminDeleteRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminDeleteRoom not implemented") } func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomRocketConfig(context.Context, *AdminUpdateRoomRocketConfigRequest) (*AdminUpdateRoomRocketConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomRocketConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoomRocketConfig not implemented") } func (UnimplementedRoomCommandServiceServer) AdminUpdateRoomSeatConfig(context.Context, *AdminUpdateRoomSeatConfigRequest) (*AdminUpdateRoomSeatConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminUpdateRoomSeatConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminUpdateRoomSeatConfig not implemented") } func (UnimplementedRoomCommandServiceServer) AdminCreateRoomPin(context.Context, *AdminCreateRoomPinRequest) (*AdminCreateRoomPinResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminCreateRoomPin not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminCreateRoomPin not implemented") } func (UnimplementedRoomCommandServiceServer) AdminCancelRoomPin(context.Context, *AdminCancelRoomPinRequest) (*AdminCancelRoomPinResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminCancelRoomPin not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminCancelRoomPin not implemented") } func (UnimplementedRoomCommandServiceServer) MicUp(context.Context, *MicUpRequest) (*MicUpResponse, error) { - return nil, status.Error(codes.Unimplemented, "method MicUp not implemented") + return nil, status.Errorf(codes.Unimplemented, "method MicUp not implemented") } func (UnimplementedRoomCommandServiceServer) MicDown(context.Context, *MicDownRequest) (*MicDownResponse, error) { - return nil, status.Error(codes.Unimplemented, "method MicDown not implemented") + return nil, status.Errorf(codes.Unimplemented, "method MicDown not implemented") } func (UnimplementedRoomCommandServiceServer) ChangeMicSeat(context.Context, *ChangeMicSeatRequest) (*ChangeMicSeatResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ChangeMicSeat not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ChangeMicSeat not implemented") } func (UnimplementedRoomCommandServiceServer) ConfirmMicPublishing(context.Context, *ConfirmMicPublishingRequest) (*ConfirmMicPublishingResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ConfirmMicPublishing not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ConfirmMicPublishing not implemented") } func (UnimplementedRoomCommandServiceServer) MicHeartbeat(context.Context, *MicHeartbeatRequest) (*MicHeartbeatResponse, error) { - return nil, status.Error(codes.Unimplemented, "method MicHeartbeat not implemented") + return nil, status.Errorf(codes.Unimplemented, "method MicHeartbeat not implemented") } func (UnimplementedRoomCommandServiceServer) SetMicMute(context.Context, *SetMicMuteRequest) (*SetMicMuteResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetMicMute not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetMicMute not implemented") } func (UnimplementedRoomCommandServiceServer) ApplyRTCEvent(context.Context, *ApplyRTCEventRequest) (*ApplyRTCEventResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ApplyRTCEvent not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ApplyRTCEvent not implemented") } func (UnimplementedRoomCommandServiceServer) SetMicSeatLock(context.Context, *SetMicSeatLockRequest) (*SetMicSeatLockResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetMicSeatLock not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetMicSeatLock not implemented") } func (UnimplementedRoomCommandServiceServer) SetChatEnabled(context.Context, *SetChatEnabledRequest) (*SetChatEnabledResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetChatEnabled not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetChatEnabled not implemented") } func (UnimplementedRoomCommandServiceServer) SetRoomPassword(context.Context, *SetRoomPasswordRequest) (*SetRoomPasswordResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetRoomPassword not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetRoomPassword not implemented") } func (UnimplementedRoomCommandServiceServer) SetRoomAdmin(context.Context, *SetRoomAdminRequest) (*SetRoomAdminResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetRoomAdmin not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetRoomAdmin not implemented") } func (UnimplementedRoomCommandServiceServer) MuteUser(context.Context, *MuteUserRequest) (*MuteUserResponse, error) { - return nil, status.Error(codes.Unimplemented, "method MuteUser not implemented") + return nil, status.Errorf(codes.Unimplemented, "method MuteUser not implemented") } func (UnimplementedRoomCommandServiceServer) KickUser(context.Context, *KickUserRequest) (*KickUserResponse, error) { - return nil, status.Error(codes.Unimplemented, "method KickUser not implemented") + return nil, status.Errorf(codes.Unimplemented, "method KickUser not implemented") } func (UnimplementedRoomCommandServiceServer) UnbanUser(context.Context, *UnbanUserRequest) (*UnbanUserResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UnbanUser not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UnbanUser not implemented") } func (UnimplementedRoomCommandServiceServer) SystemEvictUser(context.Context, *SystemEvictUserRequest) (*SystemEvictUserResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SystemEvictUser not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SystemEvictUser not implemented") } func (UnimplementedRoomCommandServiceServer) SendGift(context.Context, *SendGiftRequest) (*SendGiftResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SendGift not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SendGift not implemented") } func (UnimplementedRoomCommandServiceServer) FollowRoom(context.Context, *FollowRoomRequest) (*FollowRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method FollowRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method FollowRoom not implemented") } func (UnimplementedRoomCommandServiceServer) UnfollowRoom(context.Context, *UnfollowRoomRequest) (*UnfollowRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UnfollowRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UnfollowRoom not implemented") } func (UnimplementedRoomCommandServiceServer) mustEmbedUnimplementedRoomCommandServiceServer() {} func (UnimplementedRoomCommandServiceServer) testEmbeddedByValue() {} @@ -576,7 +576,7 @@ type UnsafeRoomCommandServiceServer interface { } func RegisterRoomCommandServiceServer(s grpc.ServiceRegistrar, srv RoomCommandServiceServer) { - // If the following call panics, it indicates UnimplementedRoomCommandServiceServer was + // If the following call pancis, it indicates UnimplementedRoomCommandServiceServer 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. @@ -1364,10 +1364,10 @@ type RoomGuardServiceServer interface { type UnimplementedRoomGuardServiceServer struct{} func (UnimplementedRoomGuardServiceServer) CheckSpeakPermission(context.Context, *CheckSpeakPermissionRequest) (*CheckSpeakPermissionResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CheckSpeakPermission not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CheckSpeakPermission not implemented") } func (UnimplementedRoomGuardServiceServer) VerifyRoomPresence(context.Context, *VerifyRoomPresenceRequest) (*VerifyRoomPresenceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method VerifyRoomPresence not implemented") + return nil, status.Errorf(codes.Unimplemented, "method VerifyRoomPresence not implemented") } func (UnimplementedRoomGuardServiceServer) mustEmbedUnimplementedRoomGuardServiceServer() {} func (UnimplementedRoomGuardServiceServer) testEmbeddedByValue() {} @@ -1380,7 +1380,7 @@ type UnsafeRoomGuardServiceServer interface { } func RegisterRoomGuardServiceServer(s grpc.ServiceRegistrar, srv RoomGuardServiceServer) { - // If the following call panics, it indicates UnimplementedRoomGuardServiceServer was + // If the following call pancis, it indicates UnimplementedRoomGuardServiceServer 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. @@ -1677,49 +1677,49 @@ type RoomQueryServiceServer interface { type UnimplementedRoomQueryServiceServer struct{} func (UnimplementedRoomQueryServiceServer) AdminListRooms(context.Context, *AdminListRoomsRequest) (*AdminListRoomsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminListRooms not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminListRooms not implemented") } func (UnimplementedRoomQueryServiceServer) AdminGetRoom(context.Context, *AdminGetRoomRequest) (*AdminGetRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminGetRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoom not implemented") } func (UnimplementedRoomQueryServiceServer) AdminGetRoomRocketConfig(context.Context, *AdminGetRoomRocketConfigRequest) (*AdminGetRoomRocketConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminGetRoomRocketConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoomRocketConfig not implemented") } func (UnimplementedRoomQueryServiceServer) AdminGetRoomSeatConfig(context.Context, *AdminGetRoomSeatConfigRequest) (*AdminGetRoomSeatConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminGetRoomSeatConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminGetRoomSeatConfig not implemented") } func (UnimplementedRoomQueryServiceServer) AdminListRoomPins(context.Context, *AdminListRoomPinsRequest) (*AdminListRoomPinsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminListRoomPins not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminListRoomPins not implemented") } func (UnimplementedRoomQueryServiceServer) ListRooms(context.Context, *ListRoomsRequest) (*ListRoomsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRooms not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRooms not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomFeeds(context.Context, *ListRoomFeedsRequest) (*ListRoomsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRoomFeeds not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRoomFeeds not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomGiftLeaderboard(context.Context, *ListRoomGiftLeaderboardRequest) (*ListRoomGiftLeaderboardResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRoomGiftLeaderboard not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRoomGiftLeaderboard not implemented") } func (UnimplementedRoomQueryServiceServer) GetMyRoom(context.Context, *GetMyRoomRequest) (*GetMyRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetMyRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetMyRoom not implemented") } func (UnimplementedRoomQueryServiceServer) GetCurrentRoom(context.Context, *GetCurrentRoomRequest) (*GetCurrentRoomResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetCurrentRoom not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetCurrentRoom not implemented") } func (UnimplementedRoomQueryServiceServer) GetRoomSnapshot(context.Context, *GetRoomSnapshotRequest) (*GetRoomSnapshotResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRoomSnapshot not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetRoomSnapshot not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomBackgrounds(context.Context, *ListRoomBackgroundsRequest) (*ListRoomBackgroundsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRoomBackgrounds not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRoomBackgrounds not implemented") } func (UnimplementedRoomQueryServiceServer) GetRoomRocket(context.Context, *GetRoomRocketRequest) (*GetRoomRocketResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRoomRocket not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetRoomRocket not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomOnlineUsers(context.Context, *ListRoomOnlineUsersRequest) (*ListRoomOnlineUsersResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRoomOnlineUsers not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRoomOnlineUsers not implemented") } func (UnimplementedRoomQueryServiceServer) ListRoomBannedUsers(context.Context, *ListRoomBannedUsersRequest) (*ListRoomBannedUsersResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRoomBannedUsers not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRoomBannedUsers not implemented") } func (UnimplementedRoomQueryServiceServer) mustEmbedUnimplementedRoomQueryServiceServer() {} func (UnimplementedRoomQueryServiceServer) testEmbeddedByValue() {} @@ -1732,7 +1732,7 @@ type UnsafeRoomQueryServiceServer interface { } func RegisterRoomQueryServiceServer(s grpc.ServiceRegistrar, srv RoomQueryServiceServer) { - // If the following call panics, it indicates UnimplementedRoomQueryServiceServer was + // If the following call pancis, it indicates UnimplementedRoomQueryServiceServer 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. diff --git a/api/proto/wallet/v1/wallet.pb.go b/api/proto/wallet/v1/wallet.pb.go index 0bfed8fb..40db7dc9 100644 --- a/api/proto/wallet/v1/wallet.pb.go +++ b/api/proto/wallet/v1/wallet.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.11 +// protoc-gen-go v1.35.1 // protoc v7.35.0 // source: proto/wallet/v1/wallet.proto @@ -11,7 +11,6 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" - unsafe "unsafe" ) const ( @@ -23,13 +22,16 @@ const ( // DebitGiftRequest 是 room-service 送礼同步扣费的最小账务输入。 type DebitGiftRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GiftId string `protobuf:"bytes,5,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GiftId string `protobuf:"bytes,5,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,6,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` // price_version 为空时使用当前生效价格;非空时必须命中 active 价格版本。 PriceVersion string `protobuf:"bytes,7,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` @@ -43,8 +45,6 @@ type DebitGiftRequest struct { TargetAgencyOwnerUserId int64 `protobuf:"varint,12,opt,name=target_agency_owner_user_id,json=targetAgencyOwnerUserId,proto3" json:"target_agency_owner_user_id,omitempty"` // sender_region_id 是送礼用户所属区域快照;不能用房间 visible_region_id 替代。 SenderRegionId int64 `protobuf:"varint,13,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *DebitGiftRequest) Reset() { @@ -170,10 +170,13 @@ func (x *DebitGiftRequest) GetSenderRegionId() int64 { // DebitGiftResponse 返回扣费流水、服务端结算值和 sender COIN 账后余额。 type DebitGiftResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - BillingReceiptId string `protobuf:"bytes,1,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - CoinSpent int64 `protobuf:"varint,3,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + BillingReceiptId string `protobuf:"bytes,1,opt,name=billing_receipt_id,json=billingReceiptId,proto3" json:"billing_receipt_id,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CoinSpent int64 `protobuf:"varint,3,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` // gift_point_added 是历史回执字段;GIFT_POINT 已下线,新送礼固定返回 0。 GiftPointAdded int64 `protobuf:"varint,4,opt,name=gift_point_added,json=giftPointAdded,proto3" json:"gift_point_added,omitempty"` HeatValue int64 `protobuf:"varint,5,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` @@ -187,8 +190,6 @@ type DebitGiftResponse struct { HostPeriodDiamondAdded int64 `protobuf:"varint,11,opt,name=host_period_diamond_added,json=hostPeriodDiamondAdded,proto3" json:"host_period_diamond_added,omitempty"` // host_period_cycle_key 是 UTC 月周期,例如 2026-05;非主播为空。 HostPeriodCycleKey string `protobuf:"bytes,12,opt,name=host_period_cycle_key,json=hostPeriodCycleKey,proto3" json:"host_period_cycle_key,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *DebitGiftResponse) Reset() { @@ -307,15 +308,16 @@ func (x *DebitGiftResponse) GetHostPeriodCycleKey() string { // DebitGiftTarget 是一笔批量送礼中的单个接收方账务快照。 type DebitGiftTarget struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // command_id 是该目标的账务幂等键,由 room-service 从房间 command_id 派生。 CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` TargetIsHost bool `protobuf:"varint,3,opt,name=target_is_host,json=targetIsHost,proto3" json:"target_is_host,omitempty"` TargetHostRegionId int64 `protobuf:"varint,4,opt,name=target_host_region_id,json=targetHostRegionId,proto3" json:"target_host_region_id,omitempty"` TargetAgencyOwnerUserId int64 `protobuf:"varint,5,opt,name=target_agency_owner_user_id,json=targetAgencyOwnerUserId,proto3" json:"target_agency_owner_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *DebitGiftTarget) Reset() { @@ -385,20 +387,21 @@ func (x *DebitGiftTarget) GetTargetAgencyOwnerUserId() int64 { // BatchDebitGiftRequest 在一个钱包事务内完成同一 sender 对多个 target 的送礼扣费。 type BatchDebitGiftRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` - AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RoomId string `protobuf:"bytes,2,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + SenderUserId int64 `protobuf:"varint,3,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + GiftId string `protobuf:"bytes,4,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftCount int32 `protobuf:"varint,5,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + PriceVersion string `protobuf:"bytes,6,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + AppCode string `protobuf:"bytes,7,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` // region_id 来自 room-service 房间 visible_region_id,用于校验礼物区域可用性和匹配房间贡献比例。 RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` SenderRegionId int64 `protobuf:"varint,9,opt,name=sender_region_id,json=senderRegionId,proto3" json:"sender_region_id,omitempty"` Targets []*DebitGiftTarget `protobuf:"bytes,10,rep,name=targets,proto3" json:"targets,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *BatchDebitGiftRequest) Reset() { @@ -503,12 +506,13 @@ func (x *BatchDebitGiftRequest) GetTargets() []*DebitGiftTarget { // BatchDebitGiftReceipt 保留每个目标独立交易的回执,房间事件按它逐目标落事实。 type BatchDebitGiftReceipt struct { - state protoimpl.MessageState `protogen:"open.v1"` - TargetUserId int64 `protobuf:"varint,1,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - Billing *DebitGiftResponse `protobuf:"bytes,3,opt,name=billing,proto3" json:"billing,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TargetUserId int64 `protobuf:"varint,1,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + CommandId string `protobuf:"bytes,2,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + Billing *DebitGiftResponse `protobuf:"bytes,3,opt,name=billing,proto3" json:"billing,omitempty"` } func (x *BatchDebitGiftReceipt) Reset() { @@ -564,11 +568,12 @@ func (x *BatchDebitGiftReceipt) GetBilling() *DebitGiftResponse { // BatchDebitGiftResponse 返回批量聚合值和逐目标账务回执。 type BatchDebitGiftResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Aggregate *DebitGiftResponse `protobuf:"bytes,1,opt,name=aggregate,proto3" json:"aggregate,omitempty"` - Receipts []*BatchDebitGiftReceipt `protobuf:"bytes,2,rep,name=receipts,proto3" json:"receipts,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Aggregate *DebitGiftResponse `protobuf:"bytes,1,opt,name=aggregate,proto3" json:"aggregate,omitempty"` + Receipts []*BatchDebitGiftReceipt `protobuf:"bytes,2,rep,name=receipts,proto3" json:"receipts,omitempty"` } func (x *BatchDebitGiftResponse) Reset() { @@ -617,14 +622,15 @@ func (x *BatchDebitGiftResponse) GetReceipts() []*BatchDebitGiftReceipt { // AssetBalance 是用户某类资产的余额投影。 type AssetBalance struct { - state protoimpl.MessageState `protogen:"open.v1"` - AssetType string `protobuf:"bytes,1,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - AvailableAmount int64 `protobuf:"varint,2,opt,name=available_amount,json=availableAmount,proto3" json:"available_amount,omitempty"` - FrozenAmount int64 `protobuf:"varint,3,opt,name=frozen_amount,json=frozenAmount,proto3" json:"frozen_amount,omitempty"` - Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` - AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetType string `protobuf:"bytes,1,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + AvailableAmount int64 `protobuf:"varint,2,opt,name=available_amount,json=availableAmount,proto3" json:"available_amount,omitempty"` + FrozenAmount int64 `protobuf:"varint,3,opt,name=frozen_amount,json=frozenAmount,proto3" json:"frozen_amount,omitempty"` + Version int64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` + AppCode string `protobuf:"bytes,5,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *AssetBalance) Reset() { @@ -694,13 +700,14 @@ func (x *AssetBalance) GetAppCode() string { // GetBalancesRequest 查询用户多资产余额;内部调用方负责鉴权和用户范围控制。 type GetBalancesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - AssetTypes []string `protobuf:"bytes,3,rep,name=asset_types,json=assetTypes,proto3" json:"asset_types,omitempty"` - AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + AssetTypes []string `protobuf:"bytes,3,rep,name=asset_types,json=assetTypes,proto3" json:"asset_types,omitempty"` + AppCode string `protobuf:"bytes,4,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *GetBalancesRequest) Reset() { @@ -762,10 +769,11 @@ func (x *GetBalancesRequest) GetAppCode() string { } type GetBalancesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` } func (x *GetBalancesResponse) Reset() { @@ -806,16 +814,17 @@ func (x *GetBalancesResponse) GetBalances() []*AssetBalance { } type HostSalaryPolicyLevel struct { - state protoimpl.MessageState `protogen:"open.v1"` - LevelNo int32 `protobuf:"varint,1,opt,name=level_no,json=levelNo,proto3" json:"level_no,omitempty"` - RequiredDiamonds int64 `protobuf:"varint,2,opt,name=required_diamonds,json=requiredDiamonds,proto3" json:"required_diamonds,omitempty"` - HostSalaryUsdMinor int64 `protobuf:"varint,3,opt,name=host_salary_usd_minor,json=hostSalaryUsdMinor,proto3" json:"host_salary_usd_minor,omitempty"` - HostCoinReward int64 `protobuf:"varint,4,opt,name=host_coin_reward,json=hostCoinReward,proto3" json:"host_coin_reward,omitempty"` - AgencySalaryUsdMinor int64 `protobuf:"varint,5,opt,name=agency_salary_usd_minor,json=agencySalaryUsdMinor,proto3" json:"agency_salary_usd_minor,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + LevelNo int32 `protobuf:"varint,1,opt,name=level_no,json=levelNo,proto3" json:"level_no,omitempty"` + RequiredDiamonds int64 `protobuf:"varint,2,opt,name=required_diamonds,json=requiredDiamonds,proto3" json:"required_diamonds,omitempty"` + HostSalaryUsdMinor int64 `protobuf:"varint,3,opt,name=host_salary_usd_minor,json=hostSalaryUsdMinor,proto3" json:"host_salary_usd_minor,omitempty"` + HostCoinReward int64 `protobuf:"varint,4,opt,name=host_coin_reward,json=hostCoinReward,proto3" json:"host_coin_reward,omitempty"` + AgencySalaryUsdMinor int64 `protobuf:"varint,5,opt,name=agency_salary_usd_minor,json=agencySalaryUsdMinor,proto3" json:"agency_salary_usd_minor,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` } func (x *HostSalaryPolicyLevel) Reset() { @@ -898,7 +907,10 @@ func (x *HostSalaryPolicyLevel) GetSortOrder() int32 { } type HostSalaryPolicy struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + PolicyId uint64 `protobuf:"varint,1,opt,name=policy_id,json=policyId,proto3" json:"policy_id,omitempty"` Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` @@ -910,8 +922,6 @@ type HostSalaryPolicy struct { EffectiveFromMs int64 `protobuf:"varint,9,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` EffectiveToMs int64 `protobuf:"varint,10,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` Levels []*HostSalaryPolicyLevel `protobuf:"bytes,11,rep,name=levels,proto3" json:"levels,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *HostSalaryPolicy) Reset() { @@ -1022,15 +1032,16 @@ func (x *HostSalaryPolicy) GetLevels() []*HostSalaryPolicyLevel { } type GetActiveHostSalaryPolicyRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - SettlementMode string `protobuf:"bytes,4,opt,name=settlement_mode,json=settlementMode,proto3" json:"settlement_mode,omitempty"` - SettlementTriggerMode string `protobuf:"bytes,5,opt,name=settlement_trigger_mode,json=settlementTriggerMode,proto3" json:"settlement_trigger_mode,omitempty"` - NowMs int64 `protobuf:"varint,6,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + SettlementMode string `protobuf:"bytes,4,opt,name=settlement_mode,json=settlementMode,proto3" json:"settlement_mode,omitempty"` + SettlementTriggerMode string `protobuf:"bytes,5,opt,name=settlement_trigger_mode,json=settlementTriggerMode,proto3" json:"settlement_trigger_mode,omitempty"` + NowMs int64 `protobuf:"varint,6,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` } func (x *GetActiveHostSalaryPolicyRequest) Reset() { @@ -1106,11 +1117,12 @@ func (x *GetActiveHostSalaryPolicyRequest) GetNowMs() int64 { } type GetActiveHostSalaryPolicyResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` - Policy *HostSalaryPolicy `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Found bool `protobuf:"varint,1,opt,name=found,proto3" json:"found,omitempty"` + Policy *HostSalaryPolicy `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"` } func (x *GetActiveHostSalaryPolicyResponse) Reset() { @@ -1158,16 +1170,17 @@ func (x *GetActiveHostSalaryPolicyResponse) GetPolicy() *HostSalaryPolicy { } type HostSalaryProgress struct { - state protoimpl.MessageState `protogen:"open.v1"` - HostUserId int64 `protobuf:"varint,1,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` - CycleKey string `protobuf:"bytes,2,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` - RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - AgencyOwnerUserId int64 `protobuf:"varint,4,opt,name=agency_owner_user_id,json=agencyOwnerUserId,proto3" json:"agency_owner_user_id,omitempty"` - TotalDiamonds int64 `protobuf:"varint,5,opt,name=total_diamonds,json=totalDiamonds,proto3" json:"total_diamonds,omitempty"` - GiftDiamondTotal int64 `protobuf:"varint,6,opt,name=gift_diamond_total,json=giftDiamondTotal,proto3" json:"gift_diamond_total,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HostUserId int64 `protobuf:"varint,1,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` + CycleKey string `protobuf:"bytes,2,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + AgencyOwnerUserId int64 `protobuf:"varint,4,opt,name=agency_owner_user_id,json=agencyOwnerUserId,proto3" json:"agency_owner_user_id,omitempty"` + TotalDiamonds int64 `protobuf:"varint,5,opt,name=total_diamonds,json=totalDiamonds,proto3" json:"total_diamonds,omitempty"` + GiftDiamondTotal int64 `protobuf:"varint,6,opt,name=gift_diamond_total,json=giftDiamondTotal,proto3" json:"gift_diamond_total,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *HostSalaryProgress) Reset() { @@ -1250,14 +1263,15 @@ func (x *HostSalaryProgress) GetUpdatedAtMs() int64 { } type GetHostSalaryProgressRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - HostUserId int64 `protobuf:"varint,3,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` - CycleKey string `protobuf:"bytes,4,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` - NowMs int64 `protobuf:"varint,5,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + HostUserId int64 `protobuf:"varint,3,opt,name=host_user_id,json=hostUserId,proto3" json:"host_user_id,omitempty"` + CycleKey string `protobuf:"bytes,4,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + NowMs int64 `protobuf:"varint,5,opt,name=now_ms,json=nowMs,proto3" json:"now_ms,omitempty"` } func (x *GetHostSalaryProgressRequest) Reset() { @@ -1326,10 +1340,11 @@ func (x *GetHostSalaryProgressRequest) GetNowMs() int64 { } type GetHostSalaryProgressResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Progress *HostSalaryProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Progress *HostSalaryProgress `protobuf:"bytes,1,opt,name=progress,proto3" json:"progress,omitempty"` } func (x *GetHostSalaryProgressResponse) Reset() { @@ -1371,17 +1386,18 @@ func (x *GetHostSalaryProgressResponse) GetProgress() *HostSalaryProgress { // AdminCreditAssetRequest 是后台手动入账/调账的最小审计命令。 type AdminCreditAssetRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` - EvidenceRef string `protobuf:"bytes,7,opt,name=evidence_ref,json=evidenceRef,proto3" json:"evidence_ref,omitempty"` - AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + TargetUserId int64 `protobuf:"varint,2,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + EvidenceRef string `protobuf:"bytes,7,opt,name=evidence_ref,json=evidenceRef,proto3" json:"evidence_ref,omitempty"` + AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *AdminCreditAssetRequest) Reset() { @@ -1471,11 +1487,12 @@ func (x *AdminCreditAssetRequest) GetAppCode() string { } type AdminCreditAssetResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` } func (x *AdminCreditAssetResponse) Reset() { @@ -1524,20 +1541,23 @@ func (x *AdminCreditAssetResponse) GetBalance() *AssetBalance { // AdminCreditCoinSellerStockRequest 是后台给 active 币商专用库存入账的账务命令。 type AdminCreditCoinSellerStockRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - StockType string `protobuf:"bytes,3,opt,name=stock_type,json=stockType,proto3" json:"stock_type,omitempty"` - CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - PaidCurrencyCode string `protobuf:"bytes,5,opt,name=paid_currency_code,json=paidCurrencyCode,proto3" json:"paid_currency_code,omitempty"` - PaidAmountMicro int64 `protobuf:"varint,6,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` - PaymentRef string `protobuf:"bytes,7,opt,name=payment_ref,json=paymentRef,proto3" json:"payment_ref,omitempty"` - EvidenceRef string `protobuf:"bytes,8,opt,name=evidence_ref,json=evidenceRef,proto3" json:"evidence_ref,omitempty"` - OperatorUserId int64 `protobuf:"varint,9,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,omitempty"` - AppCode string `protobuf:"bytes,11,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + StockType string `protobuf:"bytes,3,opt,name=stock_type,json=stockType,proto3" json:"stock_type,omitempty"` + CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + PaidCurrencyCode string `protobuf:"bytes,5,opt,name=paid_currency_code,json=paidCurrencyCode,proto3" json:"paid_currency_code,omitempty"` + PaidAmountMicro int64 `protobuf:"varint,6,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` + PaymentRef string `protobuf:"bytes,7,opt,name=payment_ref,json=paymentRef,proto3" json:"payment_ref,omitempty"` + EvidenceRef string `protobuf:"bytes,8,opt,name=evidence_ref,json=evidenceRef,proto3" json:"evidence_ref,omitempty"` + OperatorUserId int64 `protobuf:"varint,9,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,10,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,11,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + SellerCountryId int64 `protobuf:"varint,12,opt,name=seller_country_id,json=sellerCountryId,proto3" json:"seller_country_id,omitempty"` + SellerRegionId int64 `protobuf:"varint,13,opt,name=seller_region_id,json=sellerRegionId,proto3" json:"seller_region_id,omitempty"` } func (x *AdminCreditCoinSellerStockRequest) Reset() { @@ -1647,19 +1667,34 @@ func (x *AdminCreditCoinSellerStockRequest) GetAppCode() string { return "" } +func (x *AdminCreditCoinSellerStockRequest) GetSellerCountryId() int64 { + if x != nil { + return x.SellerCountryId + } + return 0 +} + +func (x *AdminCreditCoinSellerStockRequest) GetSellerRegionId() int64 { + if x != nil { + return x.SellerRegionId + } + return 0 +} + type AdminCreditCoinSellerStockResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - StockType string `protobuf:"bytes,3,opt,name=stock_type,json=stockType,proto3" json:"stock_type,omitempty"` - CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - PaidCurrencyCode string `protobuf:"bytes,5,opt,name=paid_currency_code,json=paidCurrencyCode,proto3" json:"paid_currency_code,omitempty"` - PaidAmountMicro int64 `protobuf:"varint,6,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` - CountsAsSellerRecharge bool `protobuf:"varint,7,opt,name=counts_as_seller_recharge,json=countsAsSellerRecharge,proto3" json:"counts_as_seller_recharge,omitempty"` - BalanceAfter int64 `protobuf:"varint,8,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` - CreatedAtMs int64 `protobuf:"varint,9,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + StockType string `protobuf:"bytes,3,opt,name=stock_type,json=stockType,proto3" json:"stock_type,omitempty"` + CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + PaidCurrencyCode string `protobuf:"bytes,5,opt,name=paid_currency_code,json=paidCurrencyCode,proto3" json:"paid_currency_code,omitempty"` + PaidAmountMicro int64 `protobuf:"varint,6,opt,name=paid_amount_micro,json=paidAmountMicro,proto3" json:"paid_amount_micro,omitempty"` + CountsAsSellerRecharge bool `protobuf:"varint,7,opt,name=counts_as_seller_recharge,json=countsAsSellerRecharge,proto3" json:"counts_as_seller_recharge,omitempty"` + BalanceAfter int64 `protobuf:"varint,8,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` + CreatedAtMs int64 `protobuf:"varint,9,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` } func (x *AdminCreditCoinSellerStockResponse) Reset() { @@ -1757,18 +1792,20 @@ func (x *AdminCreditCoinSellerStockResponse) GetCreatedAtMs() int64 { // TransferCoinFromSellerRequest 是币商给玩家转普通金币的内部账务命令。 type TransferCoinFromSellerRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - // seller_region_id 和 target_region_id 由 gateway 从 user-service 查询,不接受客户端提交。 - SellerRegionId int64 `protobuf:"varint,7,opt,name=seller_region_id,json=sellerRegionId,proto3" json:"seller_region_id,omitempty"` - TargetRegionId int64 `protobuf:"varint,8,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SellerUserId int64 `protobuf:"varint,2,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + // seller_region_id、target_region_id 和 target_country_id 由 gateway 从 user-service 查询,不接受客户端提交。 + SellerRegionId int64 `protobuf:"varint,7,opt,name=seller_region_id,json=sellerRegionId,proto3" json:"seller_region_id,omitempty"` + TargetRegionId int64 `protobuf:"varint,8,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` + TargetCountryId int64 `protobuf:"varint,9,opt,name=target_country_id,json=targetCountryId,proto3" json:"target_country_id,omitempty"` } func (x *TransferCoinFromSellerRequest) Reset() { @@ -1857,21 +1894,29 @@ func (x *TransferCoinFromSellerRequest) GetTargetRegionId() int64 { return 0 } +func (x *TransferCoinFromSellerRequest) GetTargetCountryId() int64 { + if x != nil { + return x.TargetCountryId + } + return 0 +} + // TransferCoinFromSellerResponse 同时返回金币到账结果和本次转账对应的充值金额口径。 type TransferCoinFromSellerResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - SellerBalanceAfter int64 `protobuf:"varint,2,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` - TargetBalanceAfter int64 `protobuf:"varint,3,opt,name=target_balance_after,json=targetBalanceAfter,proto3" json:"target_balance_after,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - RechargeUsdMinor int64 `protobuf:"varint,5,opt,name=recharge_usd_minor,json=rechargeUsdMinor,proto3" json:"recharge_usd_minor,omitempty"` - RechargeCurrencyCode string `protobuf:"bytes,6,opt,name=recharge_currency_code,json=rechargeCurrencyCode,proto3" json:"recharge_currency_code,omitempty"` - RechargePolicyId int64 `protobuf:"varint,7,opt,name=recharge_policy_id,json=rechargePolicyId,proto3" json:"recharge_policy_id,omitempty"` - RechargePolicyVersion string `protobuf:"bytes,8,opt,name=recharge_policy_version,json=rechargePolicyVersion,proto3" json:"recharge_policy_version,omitempty"` - RechargePolicyCoinAmount int64 `protobuf:"varint,9,opt,name=recharge_policy_coin_amount,json=rechargePolicyCoinAmount,proto3" json:"recharge_policy_coin_amount,omitempty"` - RechargePolicyUsdMinorAmount int64 `protobuf:"varint,10,opt,name=recharge_policy_usd_minor_amount,json=rechargePolicyUsdMinorAmount,proto3" json:"recharge_policy_usd_minor_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SellerBalanceAfter int64 `protobuf:"varint,2,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` + TargetBalanceAfter int64 `protobuf:"varint,3,opt,name=target_balance_after,json=targetBalanceAfter,proto3" json:"target_balance_after,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + RechargeUsdMinor int64 `protobuf:"varint,5,opt,name=recharge_usd_minor,json=rechargeUsdMinor,proto3" json:"recharge_usd_minor,omitempty"` + RechargeCurrencyCode string `protobuf:"bytes,6,opt,name=recharge_currency_code,json=rechargeCurrencyCode,proto3" json:"recharge_currency_code,omitempty"` + RechargePolicyId int64 `protobuf:"varint,7,opt,name=recharge_policy_id,json=rechargePolicyId,proto3" json:"recharge_policy_id,omitempty"` + RechargePolicyVersion string `protobuf:"bytes,8,opt,name=recharge_policy_version,json=rechargePolicyVersion,proto3" json:"recharge_policy_version,omitempty"` + RechargePolicyCoinAmount int64 `protobuf:"varint,9,opt,name=recharge_policy_coin_amount,json=rechargePolicyCoinAmount,proto3" json:"recharge_policy_coin_amount,omitempty"` + RechargePolicyUsdMinorAmount int64 `protobuf:"varint,10,opt,name=recharge_policy_usd_minor_amount,json=rechargePolicyUsdMinorAmount,proto3" json:"recharge_policy_usd_minor_amount,omitempty"` } func (x *TransferCoinFromSellerResponse) Reset() { @@ -1976,16 +2021,17 @@ func (x *TransferCoinFromSellerResponse) GetRechargePolicyUsdMinorAmount() int64 // CoinSellerSalaryExchangeRateTier 是用户工资转给币商时,按区域和美元金额命中的金币兑换区间。 type CoinSellerSalaryExchangeRateTier struct { - state protoimpl.MessageState `protogen:"open.v1"` - RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - MinUsdMinor int64 `protobuf:"varint,2,opt,name=min_usd_minor,json=minUsdMinor,proto3" json:"min_usd_minor,omitempty"` - MaxUsdMinor int64 `protobuf:"varint,3,opt,name=max_usd_minor,json=maxUsdMinor,proto3" json:"max_usd_minor,omitempty"` - CoinPerUsd int64 `protobuf:"varint,4,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RegionId int64 `protobuf:"varint,1,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + MinUsdMinor int64 `protobuf:"varint,2,opt,name=min_usd_minor,json=minUsdMinor,proto3" json:"min_usd_minor,omitempty"` + MaxUsdMinor int64 `protobuf:"varint,3,opt,name=max_usd_minor,json=maxUsdMinor,proto3" json:"max_usd_minor,omitempty"` + CoinPerUsd int64 `protobuf:"varint,4,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *CoinSellerSalaryExchangeRateTier) Reset() { @@ -2068,13 +2114,14 @@ func (x *CoinSellerSalaryExchangeRateTier) GetUpdatedAtMs() int64 { } type ListCoinSellerSalaryExchangeRateTiersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - IncludeDisabled bool `protobuf:"varint,4,opt,name=include_disabled,json=includeDisabled,proto3" json:"include_disabled,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RegionId int64 `protobuf:"varint,3,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + IncludeDisabled bool `protobuf:"varint,4,opt,name=include_disabled,json=includeDisabled,proto3" json:"include_disabled,omitempty"` } func (x *ListCoinSellerSalaryExchangeRateTiersRequest) Reset() { @@ -2136,10 +2183,11 @@ func (x *ListCoinSellerSalaryExchangeRateTiersRequest) GetIncludeDisabled() bool } type ListCoinSellerSalaryExchangeRateTiersResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Tiers []*CoinSellerSalaryExchangeRateTier `protobuf:"bytes,1,rep,name=tiers,proto3" json:"tiers,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Tiers []*CoinSellerSalaryExchangeRateTier `protobuf:"bytes,1,rep,name=tiers,proto3" json:"tiers,omitempty"` } func (x *ListCoinSellerSalaryExchangeRateTiersResponse) Reset() { @@ -2181,15 +2229,16 @@ func (x *ListCoinSellerSalaryExchangeRateTiersResponse) GetTiers() []*CoinSeller // ExchangeSalaryToCoinRequest 扣当前用户某个身份工资美元钱包,并按固定比例给同一用户加普通 COIN。 type ExchangeSalaryToCoinRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - SalaryAssetType string `protobuf:"bytes,3,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` - SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SalaryAssetType string `protobuf:"bytes,3,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,6,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *ExchangeSalaryToCoinRequest) Reset() { @@ -2265,15 +2314,16 @@ func (x *ExchangeSalaryToCoinRequest) GetAppCode() string { } type ExchangeSalaryToCoinResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - SalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=salary_balance_after,json=salaryBalanceAfter,proto3" json:"salary_balance_after,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` - CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=salary_balance_after,json=salaryBalanceAfter,proto3" json:"salary_balance_after,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,3,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` } func (x *ExchangeSalaryToCoinResponse) Reset() { @@ -2350,17 +2400,18 @@ func (x *ExchangeSalaryToCoinResponse) GetCoinPerUsd() int64 { // TransferSalaryToCoinSellerRequest 扣当前用户某个身份工资美元钱包,并按区域区间比例给同区域币商加专用金币库存。 type TransferSalaryToCoinSellerRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - SourceUserId int64 `protobuf:"varint,2,opt,name=source_user_id,json=sourceUserId,proto3" json:"source_user_id,omitempty"` - SellerUserId int64 `protobuf:"varint,3,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - SalaryAssetType string `protobuf:"bytes,4,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` - SalaryUsdMinor int64 `protobuf:"varint,5,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` - RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SourceUserId int64 `protobuf:"varint,2,opt,name=source_user_id,json=sourceUserId,proto3" json:"source_user_id,omitempty"` + SellerUserId int64 `protobuf:"varint,3,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + SalaryAssetType string `protobuf:"bytes,4,opt,name=salary_asset_type,json=salaryAssetType,proto3" json:"salary_asset_type,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,5,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + AppCode string `protobuf:"bytes,8,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *TransferSalaryToCoinSellerRequest) Reset() { @@ -2450,17 +2501,18 @@ func (x *TransferSalaryToCoinSellerRequest) GetAppCode() string { } type TransferSalaryToCoinSellerResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - SourceSalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=source_salary_balance_after,json=sourceSalaryBalanceAfter,proto3" json:"source_salary_balance_after,omitempty"` - SellerBalanceAfter int64 `protobuf:"varint,3,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` - SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` - CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` - RateMinUsdMinor int64 `protobuf:"varint,7,opt,name=rate_min_usd_minor,json=rateMinUsdMinor,proto3" json:"rate_min_usd_minor,omitempty"` - RateMaxUsdMinor int64 `protobuf:"varint,8,opt,name=rate_max_usd_minor,json=rateMaxUsdMinor,proto3" json:"rate_max_usd_minor,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + SourceSalaryBalanceAfter int64 `protobuf:"varint,2,opt,name=source_salary_balance_after,json=sourceSalaryBalanceAfter,proto3" json:"source_salary_balance_after,omitempty"` + SellerBalanceAfter int64 `protobuf:"varint,3,opt,name=seller_balance_after,json=sellerBalanceAfter,proto3" json:"seller_balance_after,omitempty"` + SalaryUsdMinor int64 `protobuf:"varint,4,opt,name=salary_usd_minor,json=salaryUsdMinor,proto3" json:"salary_usd_minor,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + CoinPerUsd int64 `protobuf:"varint,6,opt,name=coin_per_usd,json=coinPerUsd,proto3" json:"coin_per_usd,omitempty"` + RateMinUsdMinor int64 `protobuf:"varint,7,opt,name=rate_min_usd_minor,json=rateMinUsdMinor,proto3" json:"rate_min_usd_minor,omitempty"` + RateMaxUsdMinor int64 `protobuf:"varint,8,opt,name=rate_max_usd_minor,json=rateMaxUsdMinor,proto3" json:"rate_max_usd_minor,omitempty"` } func (x *TransferSalaryToCoinSellerResponse) Reset() { @@ -2551,34 +2603,35 @@ func (x *TransferSalaryToCoinSellerResponse) GetRateMaxUsdMinor() int64 { // Resource 是资源库里可配置、可赠送、可被礼物引用的最小资源。 type Resource struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceId int64 `protobuf:"varint,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceCode string `protobuf:"bytes,3,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - Grantable bool `protobuf:"varint,7,opt,name=grantable,proto3" json:"grantable,omitempty"` - GrantStrategy string `protobuf:"bytes,8,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` - WalletAssetType string `protobuf:"bytes,9,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` - WalletAssetAmount int64 `protobuf:"varint,10,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` - UsageScopes []string `protobuf:"bytes,11,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` - AssetUrl string `protobuf:"bytes,12,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,13,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,14,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - MetadataJson string `protobuf:"bytes,15,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - SortOrder int32 `protobuf:"varint,16,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedByUserId int64 `protobuf:"varint,17,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,18,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,19,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,20,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - ManagerGrantEnabled bool `protobuf:"varint,21,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3" json:"manager_grant_enabled,omitempty"` - PriceType string `protobuf:"bytes,22,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` - CoinPrice int64 `protobuf:"varint,23,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceId int64 `protobuf:"varint,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceCode string `protobuf:"bytes,3,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + Grantable bool `protobuf:"varint,7,opt,name=grantable,proto3" json:"grantable,omitempty"` + GrantStrategy string `protobuf:"bytes,8,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` + WalletAssetType string `protobuf:"bytes,9,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` + WalletAssetAmount int64 `protobuf:"varint,10,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` + UsageScopes []string `protobuf:"bytes,11,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` + AssetUrl string `protobuf:"bytes,12,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,13,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,14,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + MetadataJson string `protobuf:"bytes,15,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + SortOrder int32 `protobuf:"varint,16,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedByUserId int64 `protobuf:"varint,17,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,18,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,19,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,20,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + ManagerGrantEnabled bool `protobuf:"varint,21,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3" json:"manager_grant_enabled,omitempty"` + PriceType string `protobuf:"bytes,22,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` + CoinPrice int64 `protobuf:"varint,23,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;资源和礼物价格现在只维护真实 COIN 价格,新写入固定为 0。 GiftPointAmount int64 `protobuf:"varint,24,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *Resource) Reset() { @@ -2780,21 +2833,22 @@ func (x *Resource) GetGiftPointAmount() int64 { } type ResourceGroupItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - GroupItemId int64 `protobuf:"varint,1,opt,name=group_item_id,json=groupItemId,proto3" json:"group_item_id,omitempty"` - GroupId int64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` - Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` - DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - ItemType string `protobuf:"bytes,10,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"` - WalletAssetType string `protobuf:"bytes,11,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` - WalletAssetAmount int64 `protobuf:"varint,12,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GroupItemId int64 `protobuf:"varint,1,opt,name=group_item_id,json=groupItemId,proto3" json:"group_item_id,omitempty"` + GroupId int64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` + Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` + DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedAtMs int64 `protobuf:"varint,8,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,9,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + ItemType string `protobuf:"bytes,10,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"` + WalletAssetType string `protobuf:"bytes,11,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` + WalletAssetAmount int64 `protobuf:"varint,12,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` } func (x *ResourceGroupItem) Reset() { @@ -2912,21 +2966,22 @@ func (x *ResourceGroupItem) GetWalletAssetAmount() int64 { } type ResourceGroup struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GroupId int64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - GroupCode string `protobuf:"bytes,3,opt,name=group_code,json=groupCode,proto3" json:"group_code,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - Items []*ResourceGroupItem `protobuf:"bytes,8,rep,name=items,proto3" json:"items,omitempty"` - CreatedByUserId int64 `protobuf:"varint,9,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,10,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,12,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GroupId int64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + GroupCode string `protobuf:"bytes,3,opt,name=group_code,json=groupCode,proto3" json:"group_code,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + Items []*ResourceGroupItem `protobuf:"bytes,8,rep,name=items,proto3" json:"items,omitempty"` + CreatedByUserId int64 `protobuf:"varint,9,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,10,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,12,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *ResourceGroup) Reset() { @@ -3044,17 +3099,20 @@ func (x *ResourceGroup) GetUpdatedAtMs() int64 { } type GiftConfig struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` - PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` - CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GiftId string `protobuf:"bytes,2,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` + PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;送礼结算不再读取该值,新写入固定为 0。 GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` @@ -3068,8 +3126,6 @@ type GiftConfig struct { EffectiveFromMs int64 `protobuf:"varint,20,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` EffectiveToMs int64 `protobuf:"varint,21,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` EffectTypes []string `protobuf:"bytes,22,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *GiftConfig) Reset() { @@ -3257,19 +3313,20 @@ func (x *GiftConfig) GetEffectTypes() []string { } type GiftTypeConfig struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TypeCode string `protobuf:"bytes,2,opt,name=type_code,json=typeCode,proto3" json:"type_code,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - TabKey string `protobuf:"bytes,4,opt,name=tab_key,json=tabKey,proto3" json:"tab_key,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedByUserId int64 `protobuf:"varint,7,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,8,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,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 + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TypeCode string `protobuf:"bytes,2,opt,name=type_code,json=typeCode,proto3" json:"type_code,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + TabKey string `protobuf:"bytes,4,opt,name=tab_key,json=tabKey,proto3" json:"tab_key,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,6,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedByUserId int64 `protobuf:"varint,7,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,8,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,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"` } func (x *GiftTypeConfig) Reset() { @@ -3373,24 +3430,25 @@ func (x *GiftTypeConfig) GetUpdatedAtMs() int64 { } type ResourceShopItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ShopItemId int64 `protobuf:"varint,2,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - DurationDays int32 `protobuf:"varint,6,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` - PriceType string `protobuf:"bytes,7,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` - CoinPrice int64 `protobuf:"varint,8,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,9,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - EffectiveToMs int64 `protobuf:"varint,10,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` - SortOrder int32 `protobuf:"varint,11,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - CreatedByUserId int64 `protobuf:"varint,12,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,13,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,15,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ShopItemId int64 `protobuf:"varint,2,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + DurationDays int32 `protobuf:"varint,6,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` + PriceType string `protobuf:"bytes,7,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` + CoinPrice int64 `protobuf:"varint,8,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,9,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,10,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + SortOrder int32 `protobuf:"varint,11,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + CreatedByUserId int64 `protobuf:"varint,12,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,13,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,15,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *ResourceShopItem) Reset() { @@ -3529,23 +3587,24 @@ func (x *ResourceShopItem) GetUpdatedAtMs() int64 { } type UserResourceEntitlement struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - EntitlementId string `protobuf:"bytes,2,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - Quantity int64 `protobuf:"varint,7,opt,name=quantity,proto3" json:"quantity,omitempty"` - RemainingQuantity int64 `protobuf:"varint,8,opt,name=remaining_quantity,json=remainingQuantity,proto3" json:"remaining_quantity,omitempty"` - EffectiveAtMs int64 `protobuf:"varint,9,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,10,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - SourceGrantId string `protobuf:"bytes,11,opt,name=source_grant_id,json=sourceGrantId,proto3" json:"source_grant_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,12,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - Equipped bool `protobuf:"varint,14,opt,name=equipped,proto3" json:"equipped,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + EntitlementId string `protobuf:"bytes,2,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + Quantity int64 `protobuf:"varint,7,opt,name=quantity,proto3" json:"quantity,omitempty"` + RemainingQuantity int64 `protobuf:"varint,8,opt,name=remaining_quantity,json=remainingQuantity,proto3" json:"remaining_quantity,omitempty"` + EffectiveAtMs int64 `protobuf:"varint,9,opt,name=effective_at_ms,json=effectiveAtMs,proto3" json:"effective_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,10,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + SourceGrantId string `protobuf:"bytes,11,opt,name=source_grant_id,json=sourceGrantId,proto3" json:"source_grant_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,12,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + Equipped bool `protobuf:"varint,14,opt,name=equipped,proto3" json:"equipped,omitempty"` } func (x *UserResourceEntitlement) Reset() { @@ -3677,19 +3736,20 @@ func (x *UserResourceEntitlement) GetEquipped() bool { } type ResourceGrantItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - GrantItemId int64 `protobuf:"varint,1,opt,name=grant_item_id,json=grantItemId,proto3" json:"grant_item_id,omitempty"` - GrantId string `protobuf:"bytes,2,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceSnapshotJson string `protobuf:"bytes,4,opt,name=resource_snapshot_json,json=resourceSnapshotJson,proto3" json:"resource_snapshot_json,omitempty"` - Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` - DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - ResultType string `protobuf:"bytes,7,opt,name=result_type,json=resultType,proto3" json:"result_type,omitempty"` - WalletTransactionId string `protobuf:"bytes,8,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - EntitlementId string `protobuf:"bytes,9,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GrantItemId int64 `protobuf:"varint,1,opt,name=grant_item_id,json=grantItemId,proto3" json:"grant_item_id,omitempty"` + GrantId string `protobuf:"bytes,2,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceSnapshotJson string `protobuf:"bytes,4,opt,name=resource_snapshot_json,json=resourceSnapshotJson,proto3" json:"resource_snapshot_json,omitempty"` + Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` + DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + ResultType string `protobuf:"bytes,7,opt,name=result_type,json=resultType,proto3" json:"result_type,omitempty"` + WalletTransactionId string `protobuf:"bytes,8,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + EntitlementId string `protobuf:"bytes,9,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` } func (x *ResourceGrantItem) Reset() { @@ -3793,22 +3853,23 @@ func (x *ResourceGrantItem) GetCreatedAtMs() int64 { } type ResourceGrant struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GrantId string `protobuf:"bytes,2,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GrantSource string `protobuf:"bytes,5,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - GrantSubjectType string `protobuf:"bytes,6,opt,name=grant_subject_type,json=grantSubjectType,proto3" json:"grant_subject_type,omitempty"` - GrantSubjectId string `protobuf:"bytes,7,opt,name=grant_subject_id,json=grantSubjectId,proto3" json:"grant_subject_id,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorUserId int64 `protobuf:"varint,10,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Items []*ResourceGrantItem `protobuf:"bytes,11,rep,name=items,proto3" json:"items,omitempty"` - CreatedAtMs int64 `protobuf:"varint,12,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GrantId string `protobuf:"bytes,2,opt,name=grant_id,json=grantId,proto3" json:"grant_id,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + TargetUserId int64 `protobuf:"varint,4,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GrantSource string `protobuf:"bytes,5,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` + GrantSubjectType string `protobuf:"bytes,6,opt,name=grant_subject_type,json=grantSubjectType,proto3" json:"grant_subject_type,omitempty"` + GrantSubjectId string `protobuf:"bytes,7,opt,name=grant_subject_id,json=grantSubjectId,proto3" json:"grant_subject_id,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorUserId int64 `protobuf:"varint,10,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Items []*ResourceGrantItem `protobuf:"bytes,11,rep,name=items,proto3" json:"items,omitempty"` + CreatedAtMs int64 `protobuf:"varint,12,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,13,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *ResourceGrant) Reset() { @@ -3933,16 +3994,17 @@ func (x *ResourceGrant) GetUpdatedAtMs() int64 { } type ResourceGroupItemInput struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Quantity int64 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"` - DurationMs int64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - SortOrder int32 `protobuf:"varint,4,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - ItemType string `protobuf:"bytes,5,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"` - WalletAssetType string `protobuf:"bytes,6,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` - WalletAssetAmount int64 `protobuf:"varint,7,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Quantity int64 `protobuf:"varint,2,opt,name=quantity,proto3" json:"quantity,omitempty"` + DurationMs int64 `protobuf:"varint,3,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + SortOrder int32 `protobuf:"varint,4,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + ItemType string `protobuf:"bytes,5,opt,name=item_type,json=itemType,proto3" json:"item_type,omitempty"` + WalletAssetType string `protobuf:"bytes,6,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` + WalletAssetAmount int64 `protobuf:"varint,7,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` } func (x *ResourceGroupItemInput) Reset() { @@ -4025,18 +4087,19 @@ func (x *ResourceGroupItemInput) GetWalletAssetAmount() int64 { } type ListResourcesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - Keyword string `protobuf:"bytes,5,opt,name=keyword,proto3" json:"keyword,omitempty"` - Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ActiveOnly bool `protobuf:"varint,8,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - ManagerGrantOnly bool `protobuf:"varint,9,opt,name=manager_grant_only,json=managerGrantOnly,proto3" json:"manager_grant_only,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Keyword string `protobuf:"bytes,5,opt,name=keyword,proto3" json:"keyword,omitempty"` + Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ActiveOnly bool `protobuf:"varint,8,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` + ManagerGrantOnly bool `protobuf:"varint,9,opt,name=manager_grant_only,json=managerGrantOnly,proto3" json:"manager_grant_only,omitempty"` } func (x *ListResourcesRequest) Reset() { @@ -4133,11 +4196,12 @@ func (x *ListResourcesRequest) GetManagerGrantOnly() bool { } type ListResourcesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Resources []*Resource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resources []*Resource `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListResourcesResponse) Reset() { @@ -4185,12 +4249,13 @@ func (x *ListResourcesResponse) GetTotal() int64 { } type GetResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` } func (x *GetResourceRequest) Reset() { @@ -4245,10 +4310,11 @@ func (x *GetResourceRequest) GetResourceId() int64 { } type GetResourceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` } func (x *GetResourceResponse) Reset() { @@ -4289,31 +4355,32 @@ func (x *GetResourceResponse) GetResource() *Resource { } type CreateResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceCode string `protobuf:"bytes,3,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - Grantable bool `protobuf:"varint,7,opt,name=grantable,proto3" json:"grantable,omitempty"` - GrantStrategy string `protobuf:"bytes,8,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` - WalletAssetType string `protobuf:"bytes,9,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` - WalletAssetAmount int64 `protobuf:"varint,10,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` - UsageScopes []string `protobuf:"bytes,11,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` - AssetUrl string `protobuf:"bytes,12,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,13,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,14,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - MetadataJson string `protobuf:"bytes,15,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - SortOrder int32 `protobuf:"varint,16,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorUserId int64 `protobuf:"varint,17,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - ManagerGrantEnabled *bool `protobuf:"varint,18,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` - PriceType string `protobuf:"bytes,19,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` - CoinPrice int64 `protobuf:"varint,20,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceCode string `protobuf:"bytes,3,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + Grantable bool `protobuf:"varint,7,opt,name=grantable,proto3" json:"grantable,omitempty"` + GrantStrategy string `protobuf:"bytes,8,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` + WalletAssetType string `protobuf:"bytes,9,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` + WalletAssetAmount int64 `protobuf:"varint,10,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` + UsageScopes []string `protobuf:"bytes,11,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` + AssetUrl string `protobuf:"bytes,12,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,13,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,14,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + MetadataJson string `protobuf:"bytes,15,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + SortOrder int32 `protobuf:"varint,16,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorUserId int64 `protobuf:"varint,17,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + ManagerGrantEnabled *bool `protobuf:"varint,18,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` + PriceType string `protobuf:"bytes,19,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` + CoinPrice int64 `protobuf:"varint,20,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 GiftPointAmount int64 `protobuf:"varint,21,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *CreateResourceRequest) Reset() { @@ -4494,32 +4561,33 @@ func (x *CreateResourceRequest) GetGiftPointAmount() int64 { } type UpdateResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceCode string `protobuf:"bytes,4,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - ResourceType string `protobuf:"bytes,5,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - Grantable bool `protobuf:"varint,8,opt,name=grantable,proto3" json:"grantable,omitempty"` - GrantStrategy string `protobuf:"bytes,9,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` - WalletAssetType string `protobuf:"bytes,10,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` - WalletAssetAmount int64 `protobuf:"varint,11,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` - UsageScopes []string `protobuf:"bytes,12,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` - AssetUrl string `protobuf:"bytes,13,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,14,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,15,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - MetadataJson string `protobuf:"bytes,16,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` - SortOrder int32 `protobuf:"varint,17,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorUserId int64 `protobuf:"varint,18,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - ManagerGrantEnabled *bool `protobuf:"varint,19,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` - PriceType string `protobuf:"bytes,20,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` - CoinPrice int64 `protobuf:"varint,21,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceCode string `protobuf:"bytes,4,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + ResourceType string `protobuf:"bytes,5,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + Grantable bool `protobuf:"varint,8,opt,name=grantable,proto3" json:"grantable,omitempty"` + GrantStrategy string `protobuf:"bytes,9,opt,name=grant_strategy,json=grantStrategy,proto3" json:"grant_strategy,omitempty"` + WalletAssetType string `protobuf:"bytes,10,opt,name=wallet_asset_type,json=walletAssetType,proto3" json:"wallet_asset_type,omitempty"` + WalletAssetAmount int64 `protobuf:"varint,11,opt,name=wallet_asset_amount,json=walletAssetAmount,proto3" json:"wallet_asset_amount,omitempty"` + UsageScopes []string `protobuf:"bytes,12,rep,name=usage_scopes,json=usageScopes,proto3" json:"usage_scopes,omitempty"` + AssetUrl string `protobuf:"bytes,13,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,14,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,15,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` + MetadataJson string `protobuf:"bytes,16,opt,name=metadata_json,json=metadataJson,proto3" json:"metadata_json,omitempty"` + SortOrder int32 `protobuf:"varint,17,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorUserId int64 `protobuf:"varint,18,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + ManagerGrantEnabled *bool `protobuf:"varint,19,opt,name=manager_grant_enabled,json=managerGrantEnabled,proto3,oneof" json:"manager_grant_enabled,omitempty"` + PriceType string `protobuf:"bytes,20,opt,name=price_type,json=priceType,proto3" json:"price_type,omitempty"` + CoinPrice int64 `protobuf:"varint,21,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 GiftPointAmount int64 `protobuf:"varint,22,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *UpdateResourceRequest) Reset() { @@ -4707,14 +4775,15 @@ func (x *UpdateResourceRequest) GetGiftPointAmount() int64 { } type SetResourceStatusRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *SetResourceStatusRequest) Reset() { @@ -4783,10 +4852,11 @@ func (x *SetResourceStatusRequest) GetOperatorUserId() int64 { } type ResourceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *Resource `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` } func (x *ResourceResponse) Reset() { @@ -4827,16 +4897,17 @@ func (x *ResourceResponse) GetResource() *Resource { } type ListResourceGroupsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` - Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ActiveOnly bool `protobuf:"varint,7,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` + Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ActiveOnly bool `protobuf:"varint,7,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` } func (x *ListResourceGroupsRequest) Reset() { @@ -4919,11 +4990,12 @@ func (x *ListResourceGroupsRequest) GetActiveOnly() bool { } type ListResourceGroupsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Groups []*ResourceGroup `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Groups []*ResourceGroup `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListResourceGroupsResponse) Reset() { @@ -4971,12 +5043,13 @@ func (x *ListResourceGroupsResponse) GetTotal() int64 { } type GetResourceGroupRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GroupId int64 `protobuf:"varint,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GroupId int64 `protobuf:"varint,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` } func (x *GetResourceGroupRequest) Reset() { @@ -5031,10 +5104,11 @@ func (x *GetResourceGroupRequest) GetGroupId() int64 { } type GetResourceGroupResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` } func (x *GetResourceGroupResponse) Reset() { @@ -5075,7 +5149,10 @@ func (x *GetResourceGroupResponse) GetGroup() *ResourceGroup { } type CreateResourceGroupRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` GroupCode string `protobuf:"bytes,3,opt,name=group_code,json=groupCode,proto3" json:"group_code,omitempty"` @@ -5085,8 +5162,6 @@ type CreateResourceGroupRequest struct { SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` Items []*ResourceGroupItemInput `protobuf:"bytes,8,rep,name=items,proto3" json:"items,omitempty"` OperatorUserId int64 `protobuf:"varint,9,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *CreateResourceGroupRequest) Reset() { @@ -5183,7 +5258,10 @@ func (x *CreateResourceGroupRequest) GetOperatorUserId() int64 { } type UpdateResourceGroupRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` GroupId int64 `protobuf:"varint,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` @@ -5194,8 +5272,6 @@ type UpdateResourceGroupRequest struct { SortOrder int32 `protobuf:"varint,8,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` Items []*ResourceGroupItemInput `protobuf:"bytes,9,rep,name=items,proto3" json:"items,omitempty"` OperatorUserId int64 `protobuf:"varint,10,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *UpdateResourceGroupRequest) Reset() { @@ -5299,14 +5375,15 @@ func (x *UpdateResourceGroupRequest) GetOperatorUserId() int64 { } type SetResourceGroupStatusRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GroupId int64 `protobuf:"varint,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GroupId int64 `protobuf:"varint,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *SetResourceGroupStatusRequest) Reset() { @@ -5375,10 +5452,11 @@ func (x *SetResourceGroupStatusRequest) GetOperatorUserId() int64 { } type ResourceGroupResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Group *ResourceGroup `protobuf:"bytes,1,opt,name=group,proto3" json:"group,omitempty"` } func (x *ResourceGroupResponse) Reset() { @@ -5419,19 +5497,20 @@ func (x *ResourceGroupResponse) GetGroup() *ResourceGroup { } type ListGiftConfigsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` - Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ActiveOnly bool `protobuf:"varint,7,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - FilterRegion bool `protobuf:"varint,9,opt,name=filter_region,json=filterRegion,proto3" json:"filter_region,omitempty"` - GiftTypeCode string `protobuf:"bytes,10,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Keyword string `protobuf:"bytes,4,opt,name=keyword,proto3" json:"keyword,omitempty"` + Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ActiveOnly bool `protobuf:"varint,7,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` + RegionId int64 `protobuf:"varint,8,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + FilterRegion bool `protobuf:"varint,9,opt,name=filter_region,json=filterRegion,proto3" json:"filter_region,omitempty"` + GiftTypeCode string `protobuf:"bytes,10,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` } func (x *ListGiftConfigsRequest) Reset() { @@ -5535,11 +5614,12 @@ func (x *ListGiftConfigsRequest) GetGiftTypeCode() string { } type ListGiftConfigsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Gifts []*GiftConfig `protobuf:"bytes,1,rep,name=gifts,proto3" json:"gifts,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListGiftConfigsResponse) Reset() { @@ -5587,13 +5667,14 @@ func (x *ListGiftConfigsResponse) GetTotal() int64 { } type ListGiftTypeConfigsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - ActiveOnly bool `protobuf:"varint,4,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + ActiveOnly bool `protobuf:"varint,4,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` } func (x *ListGiftTypeConfigsRequest) Reset() { @@ -5655,10 +5736,11 @@ func (x *ListGiftTypeConfigsRequest) GetActiveOnly() bool { } type ListGiftTypeConfigsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - GiftTypes []*GiftTypeConfig `protobuf:"bytes,1,rep,name=gift_types,json=giftTypes,proto3" json:"gift_types,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GiftTypes []*GiftTypeConfig `protobuf:"bytes,1,rep,name=gift_types,json=giftTypes,proto3" json:"gift_types,omitempty"` } func (x *ListGiftTypeConfigsResponse) Reset() { @@ -5699,17 +5781,18 @@ func (x *ListGiftTypeConfigsResponse) GetGiftTypes() []*GiftTypeConfig { } type UpsertGiftTypeConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TypeCode string `protobuf:"bytes,3,opt,name=type_code,json=typeCode,proto3" json:"type_code,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - TabKey string `protobuf:"bytes,5,opt,name=tab_key,json=tabKey,proto3" json:"tab_key,omitempty"` - Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TypeCode string `protobuf:"bytes,3,opt,name=type_code,json=typeCode,proto3" json:"type_code,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + TabKey string `protobuf:"bytes,5,opt,name=tab_key,json=tabKey,proto3" json:"tab_key,omitempty"` + Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *UpsertGiftTypeConfigRequest) Reset() { @@ -5799,10 +5882,11 @@ func (x *UpsertGiftTypeConfigRequest) GetOperatorUserId() int64 { } type GiftTypeConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - GiftType *GiftTypeConfig `protobuf:"bytes,1,opt,name=gift_type,json=giftType,proto3" json:"gift_type,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GiftType *GiftTypeConfig `protobuf:"bytes,1,opt,name=gift_type,json=giftType,proto3" json:"gift_type,omitempty"` } func (x *GiftTypeConfigResponse) Reset() { @@ -5843,17 +5927,20 @@ func (x *GiftTypeConfigResponse) GetGiftType() *GiftTypeConfig { } type CreateGiftConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` - PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` - CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` + PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` @@ -5865,8 +5952,6 @@ type CreateGiftConfigRequest struct { EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *CreateGiftConfigRequest) Reset() { @@ -6040,17 +6125,20 @@ func (x *CreateGiftConfigRequest) GetEffectTypes() []string { } type UpdateGiftConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` - PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` - CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + Name string `protobuf:"bytes,6,opt,name=name,proto3" json:"name,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + PresentationJson string `protobuf:"bytes,8,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` + PriceVersion string `protobuf:"bytes,9,opt,name=price_version,json=priceVersion,proto3" json:"price_version,omitempty"` + CoinPrice int64 `protobuf:"varint,10,opt,name=coin_price,json=coinPrice,proto3" json:"coin_price,omitempty"` // gift_point_amount 是历史字段;服务端忽略请求值并固定写入 0。 GiftPointAmount int64 `protobuf:"varint,11,opt,name=gift_point_amount,json=giftPointAmount,proto3" json:"gift_point_amount,omitempty"` HeatValue int64 `protobuf:"varint,12,opt,name=heat_value,json=heatValue,proto3" json:"heat_value,omitempty"` @@ -6062,8 +6150,6 @@ type UpdateGiftConfigRequest struct { EffectiveFromMs int64 `protobuf:"varint,18,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` EffectiveToMs int64 `protobuf:"varint,19,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` EffectTypes []string `protobuf:"bytes,20,rep,name=effect_types,json=effectTypes,proto3" json:"effect_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *UpdateGiftConfigRequest) Reset() { @@ -6237,14 +6323,15 @@ func (x *UpdateGiftConfigRequest) GetEffectTypes() []string { } type SetGiftConfigStatusRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + GiftId string `protobuf:"bytes,3,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *SetGiftConfigStatusRequest) Reset() { @@ -6313,10 +6400,11 @@ func (x *SetGiftConfigStatusRequest) GetOperatorUserId() int64 { } type GiftConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Gift *GiftConfig `protobuf:"bytes,1,opt,name=gift,proto3" json:"gift,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Gift *GiftConfig `protobuf:"bytes,1,opt,name=gift,proto3" json:"gift,omitempty"` } func (x *GiftConfigResponse) Reset() { @@ -6357,18 +6445,19 @@ func (x *GiftConfigResponse) GetGift() *GiftConfig { } type GrantResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` - DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - GrantSource string `protobuf:"bytes,9,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` + DurationMs int64 `protobuf:"varint,6,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorUserId int64 `protobuf:"varint,8,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + GrantSource string `protobuf:"bytes,9,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` } func (x *GrantResourceRequest) Reset() { @@ -6465,16 +6554,17 @@ func (x *GrantResourceRequest) GetGrantSource() string { } type GrantResourceGroupRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - GroupId int64 `protobuf:"varint,4,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` - OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - GrantSource string `protobuf:"bytes,7,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + GroupId int64 `protobuf:"varint,4,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Reason string `protobuf:"bytes,5,opt,name=reason,proto3" json:"reason,omitempty"` + OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + GrantSource string `protobuf:"bytes,7,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` } func (x *GrantResourceGroupRequest) Reset() { @@ -6557,10 +6647,11 @@ func (x *GrantResourceGroupRequest) GetGrantSource() string { } type ResourceGrantResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Grant *ResourceGrant `protobuf:"bytes,1,opt,name=grant,proto3" json:"grant,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Grant *ResourceGrant `protobuf:"bytes,1,opt,name=grant,proto3" json:"grant,omitempty"` } func (x *ResourceGrantResponse) Reset() { @@ -6601,14 +6692,15 @@ func (x *ResourceGrantResponse) GetGrant() *ResourceGrant { } type ListUserResourcesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - ActiveOnly bool `protobuf:"varint,5,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + ActiveOnly bool `protobuf:"varint,5,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` } func (x *ListUserResourcesRequest) Reset() { @@ -6677,10 +6769,11 @@ func (x *ListUserResourcesRequest) GetActiveOnly() bool { } type ListUserResourcesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Resources []*UserResourceEntitlement `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resources []*UserResourceEntitlement `protobuf:"bytes,1,rep,name=resources,proto3" json:"resources,omitempty"` } func (x *ListUserResourcesResponse) Reset() { @@ -6721,14 +6814,15 @@ func (x *ListUserResourcesResponse) GetResources() []*UserResourceEntitlement { } type EquipUserResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - EntitlementId string `protobuf:"bytes,5,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ResourceId int64 `protobuf:"varint,4,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + EntitlementId string `protobuf:"bytes,5,opt,name=entitlement_id,json=entitlementId,proto3" json:"entitlement_id,omitempty"` } func (x *EquipUserResourceRequest) Reset() { @@ -6797,10 +6891,11 @@ func (x *EquipUserResourceRequest) GetEntitlementId() string { } type EquipUserResourceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Resource *UserResourceEntitlement `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Resource *UserResourceEntitlement `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"` } func (x *EquipUserResourceResponse) Reset() { @@ -6841,13 +6936,14 @@ func (x *EquipUserResourceResponse) GetResource() *UserResourceEntitlement { } type UnequipUserResourceRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ResourceType string `protobuf:"bytes,4,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` } func (x *UnequipUserResourceRequest) Reset() { @@ -6909,12 +7005,13 @@ func (x *UnequipUserResourceRequest) GetResourceType() string { } type UnequipUserResourceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Unequipped bool `protobuf:"varint,2,opt,name=unequipped,proto3" json:"unequipped,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceType string `protobuf:"bytes,1,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Unequipped bool `protobuf:"varint,2,opt,name=unequipped,proto3" json:"unequipped,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,3,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *UnequipUserResourceResponse) Reset() { @@ -6969,13 +7066,14 @@ func (x *UnequipUserResourceResponse) GetUpdatedAtMs() int64 { } type BatchGetUserEquippedResourcesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` - ResourceTypes []string `protobuf:"bytes,4,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserIds []int64 `protobuf:"varint,3,rep,packed,name=user_ids,json=userIds,proto3" json:"user_ids,omitempty"` + ResourceTypes []string `protobuf:"bytes,4,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` } func (x *BatchGetUserEquippedResourcesRequest) Reset() { @@ -7037,11 +7135,12 @@ func (x *BatchGetUserEquippedResourcesRequest) GetResourceTypes() []string { } type UserEquippedResources struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Resources []*UserResourceEntitlement `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Resources []*UserResourceEntitlement `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` } func (x *UserEquippedResources) Reset() { @@ -7089,10 +7188,11 @@ func (x *UserEquippedResources) GetResources() []*UserResourceEntitlement { } type BatchGetUserEquippedResourcesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Users []*UserEquippedResources `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Users []*UserEquippedResources `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"` } func (x *BatchGetUserEquippedResourcesResponse) Reset() { @@ -7133,15 +7233,16 @@ func (x *BatchGetUserEquippedResourcesResponse) GetUsers() []*UserEquippedResour } type ListResourceGrantsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListResourceGrantsRequest) Reset() { @@ -7217,11 +7318,12 @@ func (x *ListResourceGrantsRequest) GetPageSize() int32 { } type ListResourceGrantsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Grants []*ResourceGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Grants []*ResourceGrant `protobuf:"bytes,1,rep,name=grants,proto3" json:"grants,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListResourceGrantsResponse) Reset() { @@ -7269,16 +7371,17 @@ func (x *ListResourceGrantsResponse) GetTotal() int64 { } type ResourceShopItemInput struct { - state protoimpl.MessageState `protogen:"open.v1"` - ShopItemId int64 `protobuf:"varint,1,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` - ResourceId int64 `protobuf:"varint,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - DurationDays int32 `protobuf:"varint,4,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` - EffectiveFromMs int64 `protobuf:"varint,5,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` - EffectiveToMs int64 `protobuf:"varint,6,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ShopItemId int64 `protobuf:"varint,1,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` + ResourceId int64 `protobuf:"varint,2,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + DurationDays int32 `protobuf:"varint,4,opt,name=duration_days,json=durationDays,proto3" json:"duration_days,omitempty"` + EffectiveFromMs int64 `protobuf:"varint,5,opt,name=effective_from_ms,json=effectiveFromMs,proto3" json:"effective_from_ms,omitempty"` + EffectiveToMs int64 `protobuf:"varint,6,opt,name=effective_to_ms,json=effectiveToMs,proto3" json:"effective_to_ms,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` } func (x *ResourceShopItemInput) Reset() { @@ -7361,17 +7464,18 @@ func (x *ResourceShopItemInput) GetSortOrder() int32 { } type ListResourceShopItemsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - Keyword string `protobuf:"bytes,5,opt,name=keyword,proto3" json:"keyword,omitempty"` - Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - ActiveOnly bool `protobuf:"varint,8,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Keyword string `protobuf:"bytes,5,opt,name=keyword,proto3" json:"keyword,omitempty"` + Page int32 `protobuf:"varint,6,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,7,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + ActiveOnly bool `protobuf:"varint,8,opt,name=active_only,json=activeOnly,proto3" json:"active_only,omitempty"` } func (x *ListResourceShopItemsRequest) Reset() { @@ -7461,11 +7565,12 @@ func (x *ListResourceShopItemsRequest) GetActiveOnly() bool { } type ListResourceShopItemsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListResourceShopItemsResponse) Reset() { @@ -7513,13 +7618,14 @@ func (x *ListResourceShopItemsResponse) GetTotal() int64 { } type UpsertResourceShopItemsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` Items []*ResourceShopItemInput `protobuf:"bytes,3,rep,name=items,proto3" json:"items,omitempty"` OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *UpsertResourceShopItemsRequest) Reset() { @@ -7581,10 +7687,11 @@ func (x *UpsertResourceShopItemsRequest) GetOperatorUserId() int64 { } type UpsertResourceShopItemsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*ResourceShopItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` } func (x *UpsertResourceShopItemsResponse) Reset() { @@ -7625,14 +7732,15 @@ func (x *UpsertResourceShopItemsResponse) GetItems() []*ResourceShopItem { } type SetResourceShopItemStatusRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ShopItemId int64 `protobuf:"varint,3,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` - OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ShopItemId int64 `protobuf:"varint,3,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + OperatorUserId int64 `protobuf:"varint,5,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *SetResourceShopItemStatusRequest) Reset() { @@ -7701,10 +7809,11 @@ func (x *SetResourceShopItemStatusRequest) GetOperatorUserId() int64 { } type ResourceShopItemResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Item *ResourceShopItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *ResourceShopItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` } func (x *ResourceShopItemResponse) Reset() { @@ -7745,13 +7854,14 @@ func (x *ResourceShopItemResponse) GetItem() *ResourceShopItem { } type PurchaseResourceShopItemRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - ShopItemId int64 `protobuf:"varint,4,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + ShopItemId int64 `protobuf:"varint,4,opt,name=shop_item_id,json=shopItemId,proto3" json:"shop_item_id,omitempty"` } func (x *PurchaseResourceShopItemRequest) Reset() { @@ -7813,7 +7923,10 @@ func (x *PurchaseResourceShopItemRequest) GetShopItemId() int64 { } type PurchaseResourceShopItemResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` ResourceGrantId string `protobuf:"bytes,3,opt,name=resource_grant_id,json=resourceGrantId,proto3" json:"resource_grant_id,omitempty"` @@ -7821,8 +7934,6 @@ type PurchaseResourceShopItemResponse struct { Resource *UserResourceEntitlement `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` Balance *AssetBalance `protobuf:"bytes,6,opt,name=balance,proto3" json:"balance,omitempty"` CoinSpent int64 `protobuf:"varint,7,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *PurchaseResourceShopItemResponse) Reset() { @@ -7905,27 +8016,28 @@ func (x *PurchaseResourceShopItemResponse) GetCoinSpent() int64 { } type RechargeBill struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - RechargeType string `protobuf:"bytes,4,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` - Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` - ExternalRef string `protobuf:"bytes,6,opt,name=external_ref,json=externalRef,proto3" json:"external_ref,omitempty"` - UserId int64 `protobuf:"varint,7,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - SellerUserId int64 `protobuf:"varint,8,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - SellerRegionId int64 `protobuf:"varint,9,opt,name=seller_region_id,json=sellerRegionId,proto3" json:"seller_region_id,omitempty"` - TargetRegionId int64 `protobuf:"varint,10,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` - PolicyId int64 `protobuf:"varint,11,opt,name=policy_id,json=policyId,proto3" json:"policy_id,omitempty"` - PolicyVersion string `protobuf:"bytes,12,opt,name=policy_version,json=policyVersion,proto3" json:"policy_version,omitempty"` - CurrencyCode string `protobuf:"bytes,13,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - CoinAmount int64 `protobuf:"varint,14,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - UsdMinorAmount int64 `protobuf:"varint,15,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` - ExchangeCoinAmount int64 `protobuf:"varint,16,opt,name=exchange_coin_amount,json=exchangeCoinAmount,proto3" json:"exchange_coin_amount,omitempty"` - ExchangeUsdMinorAmount int64 `protobuf:"varint,17,opt,name=exchange_usd_minor_amount,json=exchangeUsdMinorAmount,proto3" json:"exchange_usd_minor_amount,omitempty"` - CreatedAtMs int64 `protobuf:"varint,18,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + RechargeType string `protobuf:"bytes,4,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` + Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"` + ExternalRef string `protobuf:"bytes,6,opt,name=external_ref,json=externalRef,proto3" json:"external_ref,omitempty"` + UserId int64 `protobuf:"varint,7,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SellerUserId int64 `protobuf:"varint,8,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + SellerRegionId int64 `protobuf:"varint,9,opt,name=seller_region_id,json=sellerRegionId,proto3" json:"seller_region_id,omitempty"` + TargetRegionId int64 `protobuf:"varint,10,opt,name=target_region_id,json=targetRegionId,proto3" json:"target_region_id,omitempty"` + PolicyId int64 `protobuf:"varint,11,opt,name=policy_id,json=policyId,proto3" json:"policy_id,omitempty"` + PolicyVersion string `protobuf:"bytes,12,opt,name=policy_version,json=policyVersion,proto3" json:"policy_version,omitempty"` + CurrencyCode string `protobuf:"bytes,13,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + CoinAmount int64 `protobuf:"varint,14,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + UsdMinorAmount int64 `protobuf:"varint,15,opt,name=usd_minor_amount,json=usdMinorAmount,proto3" json:"usd_minor_amount,omitempty"` + ExchangeCoinAmount int64 `protobuf:"varint,16,opt,name=exchange_coin_amount,json=exchangeCoinAmount,proto3" json:"exchange_coin_amount,omitempty"` + ExchangeUsdMinorAmount int64 `protobuf:"varint,17,opt,name=exchange_usd_minor_amount,json=exchangeUsdMinorAmount,proto3" json:"exchange_usd_minor_amount,omitempty"` + CreatedAtMs int64 `protobuf:"varint,18,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` } func (x *RechargeBill) Reset() { @@ -8085,21 +8197,22 @@ func (x *RechargeBill) GetCreatedAtMs() int64 { } type ListRechargeBillsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - SellerUserId int64 `protobuf:"varint,4,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` - RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - RechargeType string `protobuf:"bytes,6,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - Keyword string `protobuf:"bytes,8,opt,name=keyword,proto3" json:"keyword,omitempty"` - StartAtMs int64 `protobuf:"varint,9,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` - EndAtMs int64 `protobuf:"varint,10,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` - Page int32 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,12,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + SellerUserId int64 `protobuf:"varint,4,opt,name=seller_user_id,json=sellerUserId,proto3" json:"seller_user_id,omitempty"` + RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + RechargeType string `protobuf:"bytes,6,opt,name=recharge_type,json=rechargeType,proto3" json:"recharge_type,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + Keyword string `protobuf:"bytes,8,opt,name=keyword,proto3" json:"keyword,omitempty"` + StartAtMs int64 `protobuf:"varint,9,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` + EndAtMs int64 `protobuf:"varint,10,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` + Page int32 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,12,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListRechargeBillsRequest) Reset() { @@ -8217,11 +8330,12 @@ func (x *ListRechargeBillsRequest) GetPageSize() int32 { } type ListRechargeBillsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Bills []*RechargeBill `protobuf:"bytes,1,rep,name=bills,proto3" json:"bills,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Bills []*RechargeBill `protobuf:"bytes,1,rep,name=bills,proto3" json:"bills,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListRechargeBillsResponse) Reset() { @@ -8270,11 +8384,12 @@ func (x *ListRechargeBillsResponse) GetTotal() int64 { // WalletFeatureFlags 是我的页和钱包首页使用的操作开关,来源属于 wallet-service。 type WalletFeatureFlags struct { - state protoimpl.MessageState `protogen:"open.v1"` - RechargeEnabled bool `protobuf:"varint,1,opt,name=recharge_enabled,json=rechargeEnabled,proto3" json:"recharge_enabled,omitempty"` - DiamondExchangeEnabled bool `protobuf:"varint,2,opt,name=diamond_exchange_enabled,json=diamondExchangeEnabled,proto3" json:"diamond_exchange_enabled,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RechargeEnabled bool `protobuf:"varint,1,opt,name=recharge_enabled,json=rechargeEnabled,proto3" json:"recharge_enabled,omitempty"` + DiamondExchangeEnabled bool `protobuf:"varint,2,opt,name=diamond_exchange_enabled,json=diamondExchangeEnabled,proto3" json:"diamond_exchange_enabled,omitempty"` } func (x *WalletFeatureFlags) Reset() { @@ -8322,12 +8437,13 @@ func (x *WalletFeatureFlags) GetDiamondExchangeEnabled() bool { } type GetWalletOverviewRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *GetWalletOverviewRequest) Reset() { @@ -8382,11 +8498,12 @@ func (x *GetWalletOverviewRequest) GetUserId() int64 { } type GetWalletOverviewResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` - FeatureFlags *WalletFeatureFlags `protobuf:"bytes,2,opt,name=feature_flags,json=featureFlags,proto3" json:"feature_flags,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Balances []*AssetBalance `protobuf:"bytes,1,rep,name=balances,proto3" json:"balances,omitempty"` + FeatureFlags *WalletFeatureFlags `protobuf:"bytes,2,opt,name=feature_flags,json=featureFlags,proto3" json:"feature_flags,omitempty"` } func (x *GetWalletOverviewResponse) Reset() { @@ -8435,11 +8552,12 @@ func (x *GetWalletOverviewResponse) GetFeatureFlags() *WalletFeatureFlags { // WalletValueSummary 是我的页钱包价值展示的轻量投影,只返回首屏展示需要的金币余额。 type WalletValueSummary struct { - state protoimpl.MessageState `protogen:"open.v1"` - CoinAmount int64 `protobuf:"varint,1,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CoinAmount int64 `protobuf:"varint,1,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,2,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *WalletValueSummary) Reset() { @@ -8487,12 +8605,13 @@ func (x *WalletValueSummary) GetUpdatedAtMs() int64 { } type GetWalletValueSummaryRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *GetWalletValueSummaryRequest) Reset() { @@ -8547,10 +8666,11 @@ func (x *GetWalletValueSummaryRequest) GetUserId() int64 { } type GetWalletValueSummaryResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Summary *WalletValueSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Summary *WalletValueSummary `protobuf:"bytes,1,opt,name=summary,proto3" json:"summary,omitempty"` } func (x *GetWalletValueSummaryResponse) Reset() { @@ -8592,18 +8712,21 @@ func (x *GetWalletValueSummaryResponse) GetSummary() *WalletValueSummary { // GiftWallItem 是用户礼物墙按礼物类型聚合后的当前投影。 type GiftWallItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - GiftId string `protobuf:"bytes,1,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - GiftName string `protobuf:"bytes,2,opt,name=gift_name,json=giftName,proto3" json:"gift_name,omitempty"` - ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` - ResourceSnapshotJson string `protobuf:"bytes,5,opt,name=resource_snapshot_json,json=resourceSnapshotJson,proto3" json:"resource_snapshot_json,omitempty"` - GiftTypeCode string `protobuf:"bytes,6,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` - PresentationJson string `protobuf:"bytes,7,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` - GiftCount int64 `protobuf:"varint,8,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` - TotalValue int64 `protobuf:"varint,9,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` - TotalCoinValue int64 `protobuf:"varint,10,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` - TotalDiamondValue int64 `protobuf:"varint,11,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GiftId string `protobuf:"bytes,1,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + GiftName string `protobuf:"bytes,2,opt,name=gift_name,json=giftName,proto3" json:"gift_name,omitempty"` + ResourceId int64 `protobuf:"varint,3,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + Resource *Resource `protobuf:"bytes,4,opt,name=resource,proto3" json:"resource,omitempty"` + ResourceSnapshotJson string `protobuf:"bytes,5,opt,name=resource_snapshot_json,json=resourceSnapshotJson,proto3" json:"resource_snapshot_json,omitempty"` + GiftTypeCode string `protobuf:"bytes,6,opt,name=gift_type_code,json=giftTypeCode,proto3" json:"gift_type_code,omitempty"` + PresentationJson string `protobuf:"bytes,7,opt,name=presentation_json,json=presentationJson,proto3" json:"presentation_json,omitempty"` + GiftCount int64 `protobuf:"varint,8,opt,name=gift_count,json=giftCount,proto3" json:"gift_count,omitempty"` + TotalValue int64 `protobuf:"varint,9,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` + TotalCoinValue int64 `protobuf:"varint,10,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` + TotalDiamondValue int64 `protobuf:"varint,11,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` // total_gift_point 是历史礼物墙字段;新送礼不再累加。 TotalGiftPoint int64 `protobuf:"varint,12,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` TotalHeatValue int64 `protobuf:"varint,13,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` @@ -8612,8 +8735,6 @@ type GiftWallItem struct { FirstReceivedAtMs int64 `protobuf:"varint,16,opt,name=first_received_at_ms,json=firstReceivedAtMs,proto3" json:"first_received_at_ms,omitempty"` LastReceivedAtMs int64 `protobuf:"varint,17,opt,name=last_received_at_ms,json=lastReceivedAtMs,proto3" json:"last_received_at_ms,omitempty"` SortOrder int32 `protobuf:"varint,18,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *GiftWallItem) Reset() { @@ -8773,12 +8894,13 @@ func (x *GiftWallItem) GetSortOrder() int32 { } type GetUserGiftWallRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *GetUserGiftWallRequest) Reset() { @@ -8833,18 +8955,19 @@ func (x *GetUserGiftWallRequest) GetUserId() int64 { } type GetUserGiftWallResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Items []*GiftWallItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` - GiftKindCount int64 `protobuf:"varint,2,opt,name=gift_kind_count,json=giftKindCount,proto3" json:"gift_kind_count,omitempty"` - GiftTotalCount int64 `protobuf:"varint,3,opt,name=gift_total_count,json=giftTotalCount,proto3" json:"gift_total_count,omitempty"` - TotalValue int64 `protobuf:"varint,4,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` - TotalCoinValue int64 `protobuf:"varint,5,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` - TotalDiamondValue int64 `protobuf:"varint,6,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*GiftWallItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + GiftKindCount int64 `protobuf:"varint,2,opt,name=gift_kind_count,json=giftKindCount,proto3" json:"gift_kind_count,omitempty"` + GiftTotalCount int64 `protobuf:"varint,3,opt,name=gift_total_count,json=giftTotalCount,proto3" json:"gift_total_count,omitempty"` + TotalValue int64 `protobuf:"varint,4,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"` + TotalCoinValue int64 `protobuf:"varint,5,opt,name=total_coin_value,json=totalCoinValue,proto3" json:"total_coin_value,omitempty"` + TotalDiamondValue int64 `protobuf:"varint,6,opt,name=total_diamond_value,json=totalDiamondValue,proto3" json:"total_diamond_value,omitempty"` // total_gift_point 是历史礼物墙汇总字段;新送礼不再累加。 TotalGiftPoint int64 `protobuf:"varint,7,opt,name=total_gift_point,json=totalGiftPoint,proto3" json:"total_gift_point,omitempty"` TotalHeatValue int64 `protobuf:"varint,8,opt,name=total_heat_value,json=totalHeatValue,proto3" json:"total_heat_value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache } func (x *GetUserGiftWallResponse) Reset() { @@ -8935,30 +9058,31 @@ func (x *GetUserGiftWallResponse) GetTotalHeatValue() int64 { // RechargeProduct 是 App 充值页可展示的区域化充值档位。 type RechargeProduct struct { - state protoimpl.MessageState `protogen:"open.v1"` - ProductId int64 `protobuf:"varint,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - ProductCode string `protobuf:"bytes,2,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` - Channel string `protobuf:"bytes,3,opt,name=channel,proto3" json:"channel,omitempty"` - CurrencyCode string `protobuf:"bytes,4,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` - CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - AmountMinor int64 `protobuf:"varint,6,opt,name=amount_minor,json=amountMinor,proto3" json:"amount_minor,omitempty"` - PolicyVersion string `protobuf:"bytes,7,opt,name=policy_version,json=policyVersion,proto3" json:"policy_version,omitempty"` - Enabled bool `protobuf:"varint,8,opt,name=enabled,proto3" json:"enabled,omitempty"` - SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - ProductName string `protobuf:"bytes,10,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` - Description string `protobuf:"bytes,11,opt,name=description,proto3" json:"description,omitempty"` - Platform string `protobuf:"bytes,12,opt,name=platform,proto3" json:"platform,omitempty"` - RegionIds []int64 `protobuf:"varint,13,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - ResourceAssetType string `protobuf:"bytes,14,opt,name=resource_asset_type,json=resourceAssetType,proto3" json:"resource_asset_type,omitempty"` - AmountMicro int64 `protobuf:"varint,15,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` - CreatedByUserId int64 `protobuf:"varint,16,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` - UpdatedByUserId int64 `protobuf:"varint,17,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,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"` - AppCode string `protobuf:"bytes,20,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Status string `protobuf:"bytes,21,opt,name=status,proto3" json:"status,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ProductId int64 `protobuf:"varint,1,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + ProductCode string `protobuf:"bytes,2,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` + Channel string `protobuf:"bytes,3,opt,name=channel,proto3" json:"channel,omitempty"` + CurrencyCode string `protobuf:"bytes,4,opt,name=currency_code,json=currencyCode,proto3" json:"currency_code,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + AmountMinor int64 `protobuf:"varint,6,opt,name=amount_minor,json=amountMinor,proto3" json:"amount_minor,omitempty"` + PolicyVersion string `protobuf:"bytes,7,opt,name=policy_version,json=policyVersion,proto3" json:"policy_version,omitempty"` + Enabled bool `protobuf:"varint,8,opt,name=enabled,proto3" json:"enabled,omitempty"` + SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + ProductName string `protobuf:"bytes,10,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + Description string `protobuf:"bytes,11,opt,name=description,proto3" json:"description,omitempty"` + Platform string `protobuf:"bytes,12,opt,name=platform,proto3" json:"platform,omitempty"` + RegionIds []int64 `protobuf:"varint,13,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + ResourceAssetType string `protobuf:"bytes,14,opt,name=resource_asset_type,json=resourceAssetType,proto3" json:"resource_asset_type,omitempty"` + AmountMicro int64 `protobuf:"varint,15,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` + CreatedByUserId int64 `protobuf:"varint,16,opt,name=created_by_user_id,json=createdByUserId,proto3" json:"created_by_user_id,omitempty"` + UpdatedByUserId int64 `protobuf:"varint,17,opt,name=updated_by_user_id,json=updatedByUserId,proto3" json:"updated_by_user_id,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"` + AppCode string `protobuf:"bytes,20,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Status string `protobuf:"bytes,21,opt,name=status,proto3" json:"status,omitempty"` } func (x *RechargeProduct) Reset() { @@ -9139,15 +9263,16 @@ func (x *RechargeProduct) GetStatus() string { } type ListRechargeProductsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RegionId int64 `protobuf:"varint,4,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - // platform 来自 gateway 解析的 App 平台请求头;为空时返回该区域全部已上架商品。 - Platform string `protobuf:"bytes,5,opt,name=platform,proto3" json:"platform,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RegionId int64 `protobuf:"varint,4,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + // platform 来自 gateway 解析的 App 平台请求头;为空时返回该区域全部已上架商品。 + Platform string `protobuf:"bytes,5,opt,name=platform,proto3" json:"platform,omitempty"` } func (x *ListRechargeProductsRequest) Reset() { @@ -9216,11 +9341,12 @@ func (x *ListRechargeProductsRequest) GetPlatform() string { } type ListRechargeProductsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` - Channels []string `protobuf:"bytes,2,rep,name=channels,proto3" json:"channels,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` + Channels []string `protobuf:"bytes,2,rep,name=channels,proto3" json:"channels,omitempty"` } func (x *ListRechargeProductsResponse) Reset() { @@ -9268,20 +9394,21 @@ func (x *ListRechargeProductsResponse) GetChannels() []string { } type ConfirmGooglePaymentRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - ProductId int64 `protobuf:"varint,6,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - ProductCode string `protobuf:"bytes,7,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` - PackageName string `protobuf:"bytes,8,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` - PurchaseToken string `protobuf:"bytes,9,opt,name=purchase_token,json=purchaseToken,proto3" json:"purchase_token,omitempty"` - OrderId string `protobuf:"bytes,10,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` - PurchaseTimeMs int64 `protobuf:"varint,11,opt,name=purchase_time_ms,json=purchaseTimeMs,proto3" json:"purchase_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + ProductId int64 `protobuf:"varint,6,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + ProductCode string `protobuf:"bytes,7,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` + PackageName string `protobuf:"bytes,8,opt,name=package_name,json=packageName,proto3" json:"package_name,omitempty"` + PurchaseToken string `protobuf:"bytes,9,opt,name=purchase_token,json=purchaseToken,proto3" json:"purchase_token,omitempty"` + OrderId string `protobuf:"bytes,10,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + PurchaseTimeMs int64 `protobuf:"varint,11,opt,name=purchase_time_ms,json=purchaseTimeMs,proto3" json:"purchase_time_ms,omitempty"` } func (x *ConfirmGooglePaymentRequest) Reset() { @@ -9392,18 +9519,19 @@ func (x *ConfirmGooglePaymentRequest) GetPurchaseTimeMs() int64 { } type ConfirmGooglePaymentResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - PaymentOrderId string `protobuf:"bytes,1,opt,name=payment_order_id,json=paymentOrderId,proto3" json:"payment_order_id,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - ProductId int64 `protobuf:"varint,4,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - ProductCode string `protobuf:"bytes,5,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` - CoinAmount int64 `protobuf:"varint,6,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - Balance *AssetBalance `protobuf:"bytes,7,opt,name=balance,proto3" json:"balance,omitempty"` - IdempotentReplay bool `protobuf:"varint,8,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` - ConsumeState string `protobuf:"bytes,9,opt,name=consume_state,json=consumeState,proto3" json:"consume_state,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PaymentOrderId string `protobuf:"bytes,1,opt,name=payment_order_id,json=paymentOrderId,proto3" json:"payment_order_id,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + ProductId int64 `protobuf:"varint,4,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + ProductCode string `protobuf:"bytes,5,opt,name=product_code,json=productCode,proto3" json:"product_code,omitempty"` + CoinAmount int64 `protobuf:"varint,6,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + Balance *AssetBalance `protobuf:"bytes,7,opt,name=balance,proto3" json:"balance,omitempty"` + IdempotentReplay bool `protobuf:"varint,8,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` + ConsumeState string `protobuf:"bytes,9,opt,name=consume_state,json=consumeState,proto3" json:"consume_state,omitempty"` } func (x *ConfirmGooglePaymentResponse) Reset() { @@ -9501,17 +9629,18 @@ func (x *ConfirmGooglePaymentResponse) GetConsumeState() string { // ListAdminRechargeProductsRequest 是后台内购配置列表查询,不参与用户充值主链路。 type ListAdminRechargeProductsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Platform string `protobuf:"bytes,4,opt,name=platform,proto3" json:"platform,omitempty"` - RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - Keyword string `protobuf:"bytes,6,opt,name=keyword,proto3" json:"keyword,omitempty"` - Page int32 `protobuf:"varint,7,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,8,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Platform string `protobuf:"bytes,4,opt,name=platform,proto3" json:"platform,omitempty"` + RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + Keyword string `protobuf:"bytes,6,opt,name=keyword,proto3" json:"keyword,omitempty"` + Page int32 `protobuf:"varint,7,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,8,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListAdminRechargeProductsRequest) Reset() { @@ -9601,11 +9730,12 @@ func (x *ListAdminRechargeProductsRequest) GetPageSize() int32 { } type ListAdminRechargeProductsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Products []*RechargeProduct `protobuf:"bytes,1,rep,name=products,proto3" json:"products,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListAdminRechargeProductsResponse) Reset() { @@ -9654,19 +9784,20 @@ func (x *ListAdminRechargeProductsResponse) GetTotal() int64 { // CreateRechargeProductRequest 配置一个 App 内购商品;首版资源资产固定为 COIN。 type CreateRechargeProductRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - AmountMicro int64 `protobuf:"varint,3,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` - CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - ProductName string `protobuf:"bytes,5,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` - Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` - Platform string `protobuf:"bytes,7,opt,name=platform,proto3" json:"platform,omitempty"` - RegionIds []int64 `protobuf:"varint,8,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - Enabled bool `protobuf:"varint,9,opt,name=enabled,proto3" json:"enabled,omitempty"` - OperatorUserId int64 `protobuf:"varint,10,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + AmountMicro int64 `protobuf:"varint,3,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` + CoinAmount int64 `protobuf:"varint,4,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + ProductName string `protobuf:"bytes,5,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` + Platform string `protobuf:"bytes,7,opt,name=platform,proto3" json:"platform,omitempty"` + RegionIds []int64 `protobuf:"varint,8,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + Enabled bool `protobuf:"varint,9,opt,name=enabled,proto3" json:"enabled,omitempty"` + OperatorUserId int64 `protobuf:"varint,10,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *CreateRechargeProductRequest) Reset() { @@ -9770,20 +9901,21 @@ func (x *CreateRechargeProductRequest) GetOperatorUserId() int64 { } type UpdateRechargeProductRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ProductId int64 `protobuf:"varint,3,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - AmountMicro int64 `protobuf:"varint,4,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` - CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - ProductName string `protobuf:"bytes,6,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` - Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"` - Platform string `protobuf:"bytes,8,opt,name=platform,proto3" json:"platform,omitempty"` - RegionIds []int64 `protobuf:"varint,9,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` - Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"` - OperatorUserId int64 `protobuf:"varint,11,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ProductId int64 `protobuf:"varint,3,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + AmountMicro int64 `protobuf:"varint,4,opt,name=amount_micro,json=amountMicro,proto3" json:"amount_micro,omitempty"` + CoinAmount int64 `protobuf:"varint,5,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + ProductName string `protobuf:"bytes,6,opt,name=product_name,json=productName,proto3" json:"product_name,omitempty"` + Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"` + Platform string `protobuf:"bytes,8,opt,name=platform,proto3" json:"platform,omitempty"` + RegionIds []int64 `protobuf:"varint,9,rep,packed,name=region_ids,json=regionIds,proto3" json:"region_ids,omitempty"` + Enabled bool `protobuf:"varint,10,opt,name=enabled,proto3" json:"enabled,omitempty"` + OperatorUserId int64 `protobuf:"varint,11,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *UpdateRechargeProductRequest) Reset() { @@ -9894,13 +10026,14 @@ func (x *UpdateRechargeProductRequest) GetOperatorUserId() int64 { } type DeleteRechargeProductRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ProductId int64 `protobuf:"varint,3,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ProductId int64 `protobuf:"varint,3,opt,name=product_id,json=productId,proto3" json:"product_id,omitempty"` + OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *DeleteRechargeProductRequest) Reset() { @@ -9962,10 +10095,11 @@ func (x *DeleteRechargeProductRequest) GetOperatorUserId() int64 { } type RechargeProductResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Product *RechargeProduct `protobuf:"bytes,1,opt,name=product,proto3" json:"product,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Product *RechargeProduct `protobuf:"bytes,1,opt,name=product,proto3" json:"product,omitempty"` } func (x *RechargeProductResponse) Reset() { @@ -10006,10 +10140,11 @@ func (x *RechargeProductResponse) GetProduct() *RechargeProduct { } type DeleteRechargeProductResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"` } func (x *DeleteRechargeProductResponse) Reset() { @@ -10050,15 +10185,16 @@ func (x *DeleteRechargeProductResponse) GetDeleted() bool { } type DiamondExchangeRule struct { - state protoimpl.MessageState `protogen:"open.v1"` - ExchangeType string `protobuf:"bytes,1,opt,name=exchange_type,json=exchangeType,proto3" json:"exchange_type,omitempty"` - FromAssetType string `protobuf:"bytes,2,opt,name=from_asset_type,json=fromAssetType,proto3" json:"from_asset_type,omitempty"` - ToAssetType string `protobuf:"bytes,3,opt,name=to_asset_type,json=toAssetType,proto3" json:"to_asset_type,omitempty"` - FromAmount int64 `protobuf:"varint,4,opt,name=from_amount,json=fromAmount,proto3" json:"from_amount,omitempty"` - ToAmount int64 `protobuf:"varint,5,opt,name=to_amount,json=toAmount,proto3" json:"to_amount,omitempty"` - Enabled bool `protobuf:"varint,6,opt,name=enabled,proto3" json:"enabled,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExchangeType string `protobuf:"bytes,1,opt,name=exchange_type,json=exchangeType,proto3" json:"exchange_type,omitempty"` + FromAssetType string `protobuf:"bytes,2,opt,name=from_asset_type,json=fromAssetType,proto3" json:"from_asset_type,omitempty"` + ToAssetType string `protobuf:"bytes,3,opt,name=to_asset_type,json=toAssetType,proto3" json:"to_asset_type,omitempty"` + FromAmount int64 `protobuf:"varint,4,opt,name=from_amount,json=fromAmount,proto3" json:"from_amount,omitempty"` + ToAmount int64 `protobuf:"varint,5,opt,name=to_amount,json=toAmount,proto3" json:"to_amount,omitempty"` + Enabled bool `protobuf:"varint,6,opt,name=enabled,proto3" json:"enabled,omitempty"` } func (x *DiamondExchangeRule) Reset() { @@ -10134,12 +10270,13 @@ func (x *DiamondExchangeRule) GetEnabled() bool { } type GetDiamondExchangeConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *GetDiamondExchangeConfigRequest) Reset() { @@ -10194,10 +10331,11 @@ func (x *GetDiamondExchangeConfigRequest) GetUserId() int64 { } type GetDiamondExchangeConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Rules []*DiamondExchangeRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rules []*DiamondExchangeRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` } func (x *GetDiamondExchangeConfigResponse) Reset() { @@ -10239,20 +10377,21 @@ func (x *GetDiamondExchangeConfigResponse) GetRules() []*DiamondExchangeRule { // WalletTransaction 是用户钱包流水页使用的分录级投影。 type WalletTransaction struct { - state protoimpl.MessageState `protogen:"open.v1"` - EntryId int64 `protobuf:"varint,1,opt,name=entry_id,json=entryId,proto3" json:"entry_id,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - BizType string `protobuf:"bytes,3,opt,name=biz_type,json=bizType,proto3" json:"biz_type,omitempty"` - AssetType string `protobuf:"bytes,4,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - AvailableDelta int64 `protobuf:"varint,5,opt,name=available_delta,json=availableDelta,proto3" json:"available_delta,omitempty"` - FrozenDelta int64 `protobuf:"varint,6,opt,name=frozen_delta,json=frozenDelta,proto3" json:"frozen_delta,omitempty"` - AvailableAfter int64 `protobuf:"varint,7,opt,name=available_after,json=availableAfter,proto3" json:"available_after,omitempty"` - FrozenAfter int64 `protobuf:"varint,8,opt,name=frozen_after,json=frozenAfter,proto3" json:"frozen_after,omitempty"` - CounterpartyUserId int64 `protobuf:"varint,9,opt,name=counterparty_user_id,json=counterpartyUserId,proto3" json:"counterparty_user_id,omitempty"` - RoomId string `protobuf:"bytes,10,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EntryId int64 `protobuf:"varint,1,opt,name=entry_id,json=entryId,proto3" json:"entry_id,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + BizType string `protobuf:"bytes,3,opt,name=biz_type,json=bizType,proto3" json:"biz_type,omitempty"` + AssetType string `protobuf:"bytes,4,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + AvailableDelta int64 `protobuf:"varint,5,opt,name=available_delta,json=availableDelta,proto3" json:"available_delta,omitempty"` + FrozenDelta int64 `protobuf:"varint,6,opt,name=frozen_delta,json=frozenDelta,proto3" json:"frozen_delta,omitempty"` + AvailableAfter int64 `protobuf:"varint,7,opt,name=available_after,json=availableAfter,proto3" json:"available_after,omitempty"` + FrozenAfter int64 `protobuf:"varint,8,opt,name=frozen_after,json=frozenAfter,proto3" json:"frozen_after,omitempty"` + CounterpartyUserId int64 `protobuf:"varint,9,opt,name=counterparty_user_id,json=counterpartyUserId,proto3" json:"counterparty_user_id,omitempty"` + RoomId string `protobuf:"bytes,10,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + CreatedAtMs int64 `protobuf:"varint,11,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` } func (x *WalletTransaction) Reset() { @@ -10363,15 +10502,16 @@ func (x *WalletTransaction) GetCreatedAtMs() int64 { } type ListWalletTransactionsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - AssetType string `protobuf:"bytes,4,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` - Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + AssetType string `protobuf:"bytes,4,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"` + Page int32 `protobuf:"varint,5,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,6,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListWalletTransactionsRequest) Reset() { @@ -10447,11 +10587,12 @@ func (x *ListWalletTransactionsRequest) GetPageSize() int32 { } type ListWalletTransactionsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Transactions []*WalletTransaction `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Transactions []*WalletTransaction `protobuf:"bytes,1,rep,name=transactions,proto3" json:"transactions,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` } func (x *ListWalletTransactionsResponse) Reset() { @@ -10499,18 +10640,19 @@ func (x *ListWalletTransactionsResponse) GetTotal() int64 { } type VipRewardItem struct { - state protoimpl.MessageState `protogen:"open.v1"` - ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` - ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,6,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - AssetUrl string `protobuf:"bytes,7,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` - PreviewUrl string `protobuf:"bytes,8,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` - AnimationUrl string `protobuf:"bytes,9,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ResourceId int64 `protobuf:"varint,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` + ResourceCode string `protobuf:"bytes,2,opt,name=resource_code,json=resourceCode,proto3" json:"resource_code,omitempty"` + ResourceType string `protobuf:"bytes,3,opt,name=resource_type,json=resourceType,proto3" json:"resource_type,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + Quantity int64 `protobuf:"varint,5,opt,name=quantity,proto3" json:"quantity,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,6,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + AssetUrl string `protobuf:"bytes,7,opt,name=asset_url,json=assetUrl,proto3" json:"asset_url,omitempty"` + PreviewUrl string `protobuf:"bytes,8,opt,name=preview_url,json=previewUrl,proto3" json:"preview_url,omitempty"` + AnimationUrl string `protobuf:"bytes,9,opt,name=animation_url,json=animationUrl,proto3" json:"animation_url,omitempty"` } func (x *VipRewardItem) Reset() { @@ -10607,24 +10749,25 @@ func (x *VipRewardItem) GetAnimationUrl() string { } type VipLevel struct { - state protoimpl.MessageState `protogen:"open.v1"` - Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - PriceCoin int64 `protobuf:"varint,4,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` - DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - RewardResourceGroupId int64 `protobuf:"varint,6,opt,name=reward_resource_group_id,json=rewardResourceGroupId,proto3" json:"reward_resource_group_id,omitempty"` - RewardItems []*VipRewardItem `protobuf:"bytes,7,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` - CanPurchase bool `protobuf:"varint,8,opt,name=can_purchase,json=canPurchase,proto3" json:"can_purchase,omitempty"` - SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - RechargeGateRequired bool `protobuf:"varint,10,opt,name=recharge_gate_required,json=rechargeGateRequired,proto3" json:"recharge_gate_required,omitempty"` - RequiredRechargeCoinAmount int64 `protobuf:"varint,11,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` - UserRechargeCoinAmount int64 `protobuf:"varint,12,opt,name=user_recharge_coin_amount,json=userRechargeCoinAmount,proto3" json:"user_recharge_coin_amount,omitempty"` - PurchaseLockedReason string `protobuf:"bytes,13,opt,name=purchase_locked_reason,json=purchaseLockedReason,proto3" json:"purchase_locked_reason,omitempty"` - CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,15,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + PriceCoin int64 `protobuf:"varint,4,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` + DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + RewardResourceGroupId int64 `protobuf:"varint,6,opt,name=reward_resource_group_id,json=rewardResourceGroupId,proto3" json:"reward_resource_group_id,omitempty"` + RewardItems []*VipRewardItem `protobuf:"bytes,7,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` + CanPurchase bool `protobuf:"varint,8,opt,name=can_purchase,json=canPurchase,proto3" json:"can_purchase,omitempty"` + SortOrder int32 `protobuf:"varint,9,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + RechargeGateRequired bool `protobuf:"varint,10,opt,name=recharge_gate_required,json=rechargeGateRequired,proto3" json:"recharge_gate_required,omitempty"` + RequiredRechargeCoinAmount int64 `protobuf:"varint,11,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` + UserRechargeCoinAmount int64 `protobuf:"varint,12,opt,name=user_recharge_coin_amount,json=userRechargeCoinAmount,proto3" json:"user_recharge_coin_amount,omitempty"` + PurchaseLockedReason string `protobuf:"bytes,13,opt,name=purchase_locked_reason,json=purchaseLockedReason,proto3" json:"purchase_locked_reason,omitempty"` + CreatedAtMs int64 `protobuf:"varint,14,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,15,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *VipLevel) Reset() { @@ -10763,16 +10906,17 @@ func (x *VipLevel) GetUpdatedAtMs() int64 { } type UserVip struct { - state protoimpl.MessageState `protogen:"open.v1"` - UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Active bool `protobuf:"varint,4,opt,name=active,proto3" json:"active,omitempty"` - StartedAtMs int64 `protobuf:"varint,5,opt,name=started_at_ms,json=startedAtMs,proto3" json:"started_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,6,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Level int32 `protobuf:"varint,2,opt,name=level,proto3" json:"level,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Active bool `protobuf:"varint,4,opt,name=active,proto3" json:"active,omitempty"` + StartedAtMs int64 `protobuf:"varint,5,opt,name=started_at_ms,json=startedAtMs,proto3" json:"started_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,6,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,7,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *UserVip) Reset() { @@ -10855,12 +10999,13 @@ func (x *UserVip) GetUpdatedAtMs() int64 { } type ListVipPackagesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *ListVipPackagesRequest) Reset() { @@ -10915,11 +11060,12 @@ func (x *ListVipPackagesRequest) GetUserId() int64 { } type ListVipPackagesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - CurrentVip *UserVip `protobuf:"bytes,1,opt,name=current_vip,json=currentVip,proto3" json:"current_vip,omitempty"` - Packages []*VipLevel `protobuf:"bytes,2,rep,name=packages,proto3" json:"packages,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CurrentVip *UserVip `protobuf:"bytes,1,opt,name=current_vip,json=currentVip,proto3" json:"current_vip,omitempty"` + Packages []*VipLevel `protobuf:"bytes,2,rep,name=packages,proto3" json:"packages,omitempty"` } func (x *ListVipPackagesResponse) Reset() { @@ -10967,12 +11113,13 @@ func (x *ListVipPackagesResponse) GetPackages() []*VipLevel { } type GetMyVipRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *GetMyVipRequest) Reset() { @@ -11027,10 +11174,11 @@ func (x *GetMyVipRequest) GetUserId() int64 { } type GetMyVipResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Vip *UserVip `protobuf:"bytes,1,opt,name=vip,proto3" json:"vip,omitempty"` } func (x *GetMyVipResponse) Reset() { @@ -11071,13 +11219,14 @@ func (x *GetMyVipResponse) GetVip() *UserVip { } type PurchaseVipRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Level int32 `protobuf:"varint,4,opt,name=level,proto3" json:"level,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Level int32 `protobuf:"varint,4,opt,name=level,proto3" json:"level,omitempty"` } func (x *PurchaseVipRequest) Reset() { @@ -11139,15 +11288,16 @@ func (x *PurchaseVipRequest) GetLevel() int32 { } type PurchaseVipResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` - TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Vip *UserVip `protobuf:"bytes,3,opt,name=vip,proto3" json:"vip,omitempty"` - CoinSpent int64 `protobuf:"varint,4,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - CoinBalanceAfter int64 `protobuf:"varint,5,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` - RewardItems []*VipRewardItem `protobuf:"bytes,6,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OrderId string `protobuf:"bytes,1,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"` + TransactionId string `protobuf:"bytes,2,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Vip *UserVip `protobuf:"bytes,3,opt,name=vip,proto3" json:"vip,omitempty"` + CoinSpent int64 `protobuf:"varint,4,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + CoinBalanceAfter int64 `protobuf:"varint,5,opt,name=coin_balance_after,json=coinBalanceAfter,proto3" json:"coin_balance_after,omitempty"` + RewardItems []*VipRewardItem `protobuf:"bytes,6,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` } func (x *PurchaseVipResponse) Reset() { @@ -11223,16 +11373,17 @@ func (x *PurchaseVipResponse) GetRewardItems() []*VipRewardItem { } type GrantVipRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Level int32 `protobuf:"varint,4,opt,name=level,proto3" json:"level,omitempty"` - GrantSource string `protobuf:"bytes,5,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` - OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Level int32 `protobuf:"varint,4,opt,name=level,proto3" json:"level,omitempty"` + GrantSource string `protobuf:"bytes,5,opt,name=grant_source,json=grantSource,proto3" json:"grant_source,omitempty"` + OperatorUserId int64 `protobuf:"varint,6,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + Reason string `protobuf:"bytes,7,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *GrantVipRequest) Reset() { @@ -11315,13 +11466,14 @@ func (x *GrantVipRequest) GetReason() string { } type GrantVipResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Vip *UserVip `protobuf:"bytes,2,opt,name=vip,proto3" json:"vip,omitempty"` - RewardItems []*VipRewardItem `protobuf:"bytes,3,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` - ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Vip *UserVip `protobuf:"bytes,2,opt,name=vip,proto3" json:"vip,omitempty"` + RewardItems []*VipRewardItem `protobuf:"bytes,3,rep,name=reward_items,json=rewardItems,proto3" json:"reward_items,omitempty"` + ServerTimeMs int64 `protobuf:"varint,4,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GrantVipResponse) Reset() { @@ -11383,17 +11535,18 @@ func (x *GrantVipResponse) GetServerTimeMs() int64 { } type AdminVipLevelInput struct { - state protoimpl.MessageState `protogen:"open.v1"` - Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - PriceCoin int64 `protobuf:"varint,4,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` - DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` - RewardResourceGroupId int64 `protobuf:"varint,6,opt,name=reward_resource_group_id,json=rewardResourceGroupId,proto3" json:"reward_resource_group_id,omitempty"` - SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` - RequiredRechargeCoinAmount int64 `protobuf:"varint,8,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Level int32 `protobuf:"varint,1,opt,name=level,proto3" json:"level,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + PriceCoin int64 `protobuf:"varint,4,opt,name=price_coin,json=priceCoin,proto3" json:"price_coin,omitempty"` + DurationMs int64 `protobuf:"varint,5,opt,name=duration_ms,json=durationMs,proto3" json:"duration_ms,omitempty"` + RewardResourceGroupId int64 `protobuf:"varint,6,opt,name=reward_resource_group_id,json=rewardResourceGroupId,proto3" json:"reward_resource_group_id,omitempty"` + SortOrder int32 `protobuf:"varint,7,opt,name=sort_order,json=sortOrder,proto3" json:"sort_order,omitempty"` + RequiredRechargeCoinAmount int64 `protobuf:"varint,8,opt,name=required_recharge_coin_amount,json=requiredRechargeCoinAmount,proto3" json:"required_recharge_coin_amount,omitempty"` } func (x *AdminVipLevelInput) Reset() { @@ -11483,11 +11636,12 @@ func (x *AdminVipLevelInput) GetRequiredRechargeCoinAmount() int64 { } type ListAdminVipLevelsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *ListAdminVipLevelsRequest) Reset() { @@ -11535,11 +11689,12 @@ func (x *ListAdminVipLevelsRequest) GetAppCode() string { } type ListAdminVipLevelsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *ListAdminVipLevelsResponse) Reset() { @@ -11587,13 +11742,14 @@ func (x *ListAdminVipLevelsResponse) GetServerTimeMs() int64 { } type UpdateAdminVipLevelsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Levels []*AdminVipLevelInput `protobuf:"bytes,3,rep,name=levels,proto3" json:"levels,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Levels []*AdminVipLevelInput `protobuf:"bytes,3,rep,name=levels,proto3" json:"levels,omitempty"` + OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *UpdateAdminVipLevelsRequest) Reset() { @@ -11655,11 +11811,12 @@ func (x *UpdateAdminVipLevelsRequest) GetOperatorUserId() int64 { } type UpdateAdminVipLevelsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Levels []*VipLevel `protobuf:"bytes,1,rep,name=levels,proto3" json:"levels,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *UpdateAdminVipLevelsResponse) Reset() { @@ -11708,17 +11865,18 @@ func (x *UpdateAdminVipLevelsResponse) GetServerTimeMs() int64 { // CreditTaskRewardRequest 是 activity-service 领取任务奖励时调用的钱包入账命令。 type CreditTaskRewardRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - TaskType string `protobuf:"bytes,5,opt,name=task_type,json=taskType,proto3" json:"task_type,omitempty"` - TaskId string `protobuf:"bytes,6,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` - CycleKey string `protobuf:"bytes,7,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` - Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + TaskType string `protobuf:"bytes,5,opt,name=task_type,json=taskType,proto3" json:"task_type,omitempty"` + TaskId string `protobuf:"bytes,6,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` + CycleKey string `protobuf:"bytes,7,opt,name=cycle_key,json=cycleKey,proto3" json:"cycle_key,omitempty"` + Reason string `protobuf:"bytes,8,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *CreditTaskRewardRequest) Reset() { @@ -11809,13 +11967,14 @@ func (x *CreditTaskRewardRequest) GetReason() string { // CreditTaskRewardResponse 返回任务奖励入账流水和用户 COIN 账后余额。 type CreditTaskRewardResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` } func (x *CreditTaskRewardResponse) Reset() { @@ -11878,19 +12037,20 @@ func (x *CreditTaskRewardResponse) GetGrantedAtMs() int64 { // CreditLuckyGiftRewardRequest 是 activity-service 抽奖 outbox 补偿 worker 调用的钱包入账命令。 type CreditLuckyGiftRewardRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - DrawId string `protobuf:"bytes,5,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` - RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - GiftId string `protobuf:"bytes,7,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` - PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` - Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` - VisibleRegionId int64 `protobuf:"varint,10,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + DrawId string `protobuf:"bytes,5,opt,name=draw_id,json=drawId,proto3" json:"draw_id,omitempty"` + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + GiftId string `protobuf:"bytes,7,opt,name=gift_id,json=giftId,proto3" json:"gift_id,omitempty"` + PoolId string `protobuf:"bytes,8,opt,name=pool_id,json=poolId,proto3" json:"pool_id,omitempty"` + Reason string `protobuf:"bytes,9,opt,name=reason,proto3" json:"reason,omitempty"` + VisibleRegionId int64 `protobuf:"varint,10,opt,name=visible_region_id,json=visibleRegionId,proto3" json:"visible_region_id,omitempty"` } func (x *CreditLuckyGiftRewardRequest) Reset() { @@ -11995,13 +12155,14 @@ func (x *CreditLuckyGiftRewardRequest) GetVisibleRegionId() int64 { // CreditLuckyGiftRewardResponse 返回幸运礼物返奖入账流水和用户 COIN 账后余额。 type CreditLuckyGiftRewardResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` } func (x *CreditLuckyGiftRewardResponse) Reset() { @@ -12064,21 +12225,22 @@ func (x *CreditLuckyGiftRewardResponse) GetGrantedAtMs() int64 { // CreditRoomTurnoverRewardRequest 是 activity-service 每周房间流水奖励结算后的金币入账命令。 type CreditRoomTurnoverRewardRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` - Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` - SettlementId string `protobuf:"bytes,5,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` - RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - PeriodStartMs int64 `protobuf:"varint,7,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` - PeriodEndMs int64 `protobuf:"varint,8,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` - CoinSpent int64 `protobuf:"varint,9,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` - TierId int64 `protobuf:"varint,10,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` - TierCode string `protobuf:"bytes,11,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` - Reason string `protobuf:"bytes,12,opt,name=reason,proto3" json:"reason,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandId string `protobuf:"bytes,1,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + TargetUserId int64 `protobuf:"varint,3,opt,name=target_user_id,json=targetUserId,proto3" json:"target_user_id,omitempty"` + Amount int64 `protobuf:"varint,4,opt,name=amount,proto3" json:"amount,omitempty"` + SettlementId string `protobuf:"bytes,5,opt,name=settlement_id,json=settlementId,proto3" json:"settlement_id,omitempty"` + RoomId string `protobuf:"bytes,6,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + PeriodStartMs int64 `protobuf:"varint,7,opt,name=period_start_ms,json=periodStartMs,proto3" json:"period_start_ms,omitempty"` + PeriodEndMs int64 `protobuf:"varint,8,opt,name=period_end_ms,json=periodEndMs,proto3" json:"period_end_ms,omitempty"` + CoinSpent int64 `protobuf:"varint,9,opt,name=coin_spent,json=coinSpent,proto3" json:"coin_spent,omitempty"` + TierId int64 `protobuf:"varint,10,opt,name=tier_id,json=tierId,proto3" json:"tier_id,omitempty"` + TierCode string `protobuf:"bytes,11,opt,name=tier_code,json=tierCode,proto3" json:"tier_code,omitempty"` + Reason string `protobuf:"bytes,12,opt,name=reason,proto3" json:"reason,omitempty"` } func (x *CreditRoomTurnoverRewardRequest) Reset() { @@ -12197,13 +12359,14 @@ func (x *CreditRoomTurnoverRewardRequest) GetReason() string { // CreditRoomTurnoverRewardResponse 返回房间流水奖励入账流水和用户 COIN 账后余额。 type CreditRoomTurnoverRewardResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` - Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` - Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` - GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransactionId string `protobuf:"bytes,1,opt,name=transaction_id,json=transactionId,proto3" json:"transaction_id,omitempty"` + Balance *AssetBalance `protobuf:"bytes,2,opt,name=balance,proto3" json:"balance,omitempty"` + Amount int64 `protobuf:"varint,3,opt,name=amount,proto3" json:"amount,omitempty"` + GrantedAtMs int64 `protobuf:"varint,4,opt,name=granted_at_ms,json=grantedAtMs,proto3" json:"granted_at_ms,omitempty"` } func (x *CreditRoomTurnoverRewardResponse) Reset() { @@ -12266,21 +12429,22 @@ func (x *CreditRoomTurnoverRewardResponse) GetGrantedAtMs() int64 { // ApplyGameCoinChangeRequest 是 game-service 唯一可以调用的钱包游戏改账入口。 type ApplyGameCoinChangeRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - PlatformCode string `protobuf:"bytes,5,opt,name=platform_code,json=platformCode,proto3" json:"platform_code,omitempty"` - GameId string `protobuf:"bytes,6,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"` - ProviderOrderId string `protobuf:"bytes,7,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` - ProviderRoundId string `protobuf:"bytes,8,opt,name=provider_round_id,json=providerRoundId,proto3" json:"provider_round_id,omitempty"` - OpType string `protobuf:"bytes,9,opt,name=op_type,json=opType,proto3" json:"op_type,omitempty"` - CoinAmount int64 `protobuf:"varint,10,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` - RoomId string `protobuf:"bytes,11,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RequestHash string `protobuf:"bytes,12,opt,name=request_hash,json=requestHash,proto3" json:"request_hash,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + UserId int64 `protobuf:"varint,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + PlatformCode string `protobuf:"bytes,5,opt,name=platform_code,json=platformCode,proto3" json:"platform_code,omitempty"` + GameId string `protobuf:"bytes,6,opt,name=game_id,json=gameId,proto3" json:"game_id,omitempty"` + ProviderOrderId string `protobuf:"bytes,7,opt,name=provider_order_id,json=providerOrderId,proto3" json:"provider_order_id,omitempty"` + ProviderRoundId string `protobuf:"bytes,8,opt,name=provider_round_id,json=providerRoundId,proto3" json:"provider_round_id,omitempty"` + OpType string `protobuf:"bytes,9,opt,name=op_type,json=opType,proto3" json:"op_type,omitempty"` + CoinAmount int64 `protobuf:"varint,10,opt,name=coin_amount,json=coinAmount,proto3" json:"coin_amount,omitempty"` + RoomId string `protobuf:"bytes,11,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RequestHash string `protobuf:"bytes,12,opt,name=request_hash,json=requestHash,proto3" json:"request_hash,omitempty"` } func (x *ApplyGameCoinChangeRequest) Reset() { @@ -12399,12 +12563,13 @@ func (x *ApplyGameCoinChangeRequest) GetRequestHash() string { // ApplyGameCoinChangeResponse 返回游戏改账流水和用户 COIN 账后余额。 type ApplyGameCoinChangeResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - WalletTransactionId string `protobuf:"bytes,1,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` - IdempotentReplay bool `protobuf:"varint,3,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + WalletTransactionId string `protobuf:"bytes,1,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` + IdempotentReplay bool `protobuf:"varint,3,opt,name=idempotent_replay,json=idempotentReplay,proto3" json:"idempotent_replay,omitempty"` } func (x *ApplyGameCoinChangeResponse) Reset() { @@ -12459,20 +12624,21 @@ func (x *ApplyGameCoinChangeResponse) GetIdempotentReplay() bool { } type RedPacketConfig 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"` - CountTiers []int32 `protobuf:"varint,3,rep,packed,name=count_tiers,json=countTiers,proto3" json:"count_tiers,omitempty"` - AmountTiers []int64 `protobuf:"varint,4,rep,packed,name=amount_tiers,json=amountTiers,proto3" json:"amount_tiers,omitempty"` - DelayedOpenSeconds int32 `protobuf:"varint,5,opt,name=delayed_open_seconds,json=delayedOpenSeconds,proto3" json:"delayed_open_seconds,omitempty"` - ExpireSeconds int32 `protobuf:"varint,6,opt,name=expire_seconds,json=expireSeconds,proto3" json:"expire_seconds,omitempty"` - DailySendLimit int32 `protobuf:"varint,7,opt,name=daily_send_limit,json=dailySendLimit,proto3" json:"daily_send_limit,omitempty"` - UpdatedByAdminId int64 `protobuf:"varint,8,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,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"` - RuleUrl string `protobuf:"bytes,11,opt,name=rule_url,json=ruleUrl,proto3" json:"rule_url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + 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"` + CountTiers []int32 `protobuf:"varint,3,rep,packed,name=count_tiers,json=countTiers,proto3" json:"count_tiers,omitempty"` + AmountTiers []int64 `protobuf:"varint,4,rep,packed,name=amount_tiers,json=amountTiers,proto3" json:"amount_tiers,omitempty"` + DelayedOpenSeconds int32 `protobuf:"varint,5,opt,name=delayed_open_seconds,json=delayedOpenSeconds,proto3" json:"delayed_open_seconds,omitempty"` + ExpireSeconds int32 `protobuf:"varint,6,opt,name=expire_seconds,json=expireSeconds,proto3" json:"expire_seconds,omitempty"` + DailySendLimit int32 `protobuf:"varint,7,opt,name=daily_send_limit,json=dailySendLimit,proto3" json:"daily_send_limit,omitempty"` + UpdatedByAdminId int64 `protobuf:"varint,8,opt,name=updated_by_admin_id,json=updatedByAdminId,proto3" json:"updated_by_admin_id,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"` + RuleUrl string `protobuf:"bytes,11,opt,name=rule_url,json=ruleUrl,proto3" json:"rule_url,omitempty"` } func (x *RedPacketConfig) Reset() { @@ -12583,20 +12749,21 @@ func (x *RedPacketConfig) GetRuleUrl() string { } type RedPacketClaim struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - ClaimId string `protobuf:"bytes,2,opt,name=claim_id,json=claimId,proto3" json:"claim_id,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - PacketId string `protobuf:"bytes,4,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` - UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` - WalletTransactionId string `protobuf:"bytes,7,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` - Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` - FailureReason string `protobuf:"bytes,9,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` - CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,11,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + ClaimId string `protobuf:"bytes,2,opt,name=claim_id,json=claimId,proto3" json:"claim_id,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + PacketId string `protobuf:"bytes,4,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` + UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` + Amount int64 `protobuf:"varint,6,opt,name=amount,proto3" json:"amount,omitempty"` + WalletTransactionId string `protobuf:"bytes,7,opt,name=wallet_transaction_id,json=walletTransactionId,proto3" json:"wallet_transaction_id,omitempty"` + Status string `protobuf:"bytes,8,opt,name=status,proto3" json:"status,omitempty"` + FailureReason string `protobuf:"bytes,9,opt,name=failure_reason,json=failureReason,proto3" json:"failure_reason,omitempty"` + CreatedAtMs int64 `protobuf:"varint,10,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,11,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` } func (x *RedPacketClaim) Reset() { @@ -12707,31 +12874,32 @@ func (x *RedPacketClaim) GetUpdatedAtMs() int64 { } type RedPacket struct { - state protoimpl.MessageState `protogen:"open.v1"` - AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - PacketId string `protobuf:"bytes,2,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - PacketType string `protobuf:"bytes,7,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` - TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` - PacketCount int32 `protobuf:"varint,9,opt,name=packet_count,json=packetCount,proto3" json:"packet_count,omitempty"` - RemainingAmount int64 `protobuf:"varint,10,opt,name=remaining_amount,json=remainingAmount,proto3" json:"remaining_amount,omitempty"` - RemainingCount int32 `protobuf:"varint,11,opt,name=remaining_count,json=remainingCount,proto3" json:"remaining_count,omitempty"` - Status string `protobuf:"bytes,12,opt,name=status,proto3" json:"status,omitempty"` - OpenAtMs int64 `protobuf:"varint,13,opt,name=open_at_ms,json=openAtMs,proto3" json:"open_at_ms,omitempty"` - ExpiresAtMs int64 `protobuf:"varint,14,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` - CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` - UpdatedAtMs int64 `protobuf:"varint,16,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` - ClaimedByViewer bool `protobuf:"varint,17,opt,name=claimed_by_viewer,json=claimedByViewer,proto3" json:"claimed_by_viewer,omitempty"` - ViewerClaimAmount int64 `protobuf:"varint,18,opt,name=viewer_claim_amount,json=viewerClaimAmount,proto3" json:"viewer_claim_amount,omitempty"` - Claims []*RedPacketClaim `protobuf:"bytes,19,rep,name=claims,proto3" json:"claims,omitempty"` - RefundAmount int64 `protobuf:"varint,20,opt,name=refund_amount,json=refundAmount,proto3" json:"refund_amount,omitempty"` - RefundStatus string `protobuf:"bytes,21,opt,name=refund_status,json=refundStatus,proto3" json:"refund_status,omitempty"` - RefundedAtMs int64 `protobuf:"varint,22,opt,name=refunded_at_ms,json=refundedAtMs,proto3" json:"refunded_at_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AppCode string `protobuf:"bytes,1,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PacketId string `protobuf:"bytes,2,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + PacketType string `protobuf:"bytes,7,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` + TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + PacketCount int32 `protobuf:"varint,9,opt,name=packet_count,json=packetCount,proto3" json:"packet_count,omitempty"` + RemainingAmount int64 `protobuf:"varint,10,opt,name=remaining_amount,json=remainingAmount,proto3" json:"remaining_amount,omitempty"` + RemainingCount int32 `protobuf:"varint,11,opt,name=remaining_count,json=remainingCount,proto3" json:"remaining_count,omitempty"` + Status string `protobuf:"bytes,12,opt,name=status,proto3" json:"status,omitempty"` + OpenAtMs int64 `protobuf:"varint,13,opt,name=open_at_ms,json=openAtMs,proto3" json:"open_at_ms,omitempty"` + ExpiresAtMs int64 `protobuf:"varint,14,opt,name=expires_at_ms,json=expiresAtMs,proto3" json:"expires_at_ms,omitempty"` + CreatedAtMs int64 `protobuf:"varint,15,opt,name=created_at_ms,json=createdAtMs,proto3" json:"created_at_ms,omitempty"` + UpdatedAtMs int64 `protobuf:"varint,16,opt,name=updated_at_ms,json=updatedAtMs,proto3" json:"updated_at_ms,omitempty"` + ClaimedByViewer bool `protobuf:"varint,17,opt,name=claimed_by_viewer,json=claimedByViewer,proto3" json:"claimed_by_viewer,omitempty"` + ViewerClaimAmount int64 `protobuf:"varint,18,opt,name=viewer_claim_amount,json=viewerClaimAmount,proto3" json:"viewer_claim_amount,omitempty"` + Claims []*RedPacketClaim `protobuf:"bytes,19,rep,name=claims,proto3" json:"claims,omitempty"` + RefundAmount int64 `protobuf:"varint,20,opt,name=refund_amount,json=refundAmount,proto3" json:"refund_amount,omitempty"` + RefundStatus string `protobuf:"bytes,21,opt,name=refund_status,json=refundStatus,proto3" json:"refund_status,omitempty"` + RefundedAtMs int64 `protobuf:"varint,22,opt,name=refunded_at_ms,json=refundedAtMs,proto3" json:"refunded_at_ms,omitempty"` } func (x *RedPacket) Reset() { @@ -12919,11 +13087,12 @@ func (x *RedPacket) GetRefundedAtMs() int64 { } type GetRedPacketConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` } func (x *GetRedPacketConfigRequest) Reset() { @@ -12971,11 +13140,12 @@ func (x *GetRedPacketConfigRequest) GetAppCode() string { } type GetRedPacketConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *RedPacketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *RedPacketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GetRedPacketConfigResponse) Reset() { @@ -13023,19 +13193,20 @@ func (x *GetRedPacketConfigResponse) GetServerTimeMs() int64 { } type UpdateRedPacketConfigRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` - CountTiers []int32 `protobuf:"varint,4,rep,packed,name=count_tiers,json=countTiers,proto3" json:"count_tiers,omitempty"` - AmountTiers []int64 `protobuf:"varint,5,rep,packed,name=amount_tiers,json=amountTiers,proto3" json:"amount_tiers,omitempty"` - DelayedOpenSeconds int32 `protobuf:"varint,6,opt,name=delayed_open_seconds,json=delayedOpenSeconds,proto3" json:"delayed_open_seconds,omitempty"` - ExpireSeconds int32 `protobuf:"varint,7,opt,name=expire_seconds,json=expireSeconds,proto3" json:"expire_seconds,omitempty"` - DailySendLimit int32 `protobuf:"varint,8,opt,name=daily_send_limit,json=dailySendLimit,proto3" json:"daily_send_limit,omitempty"` - OperatorUserId int64 `protobuf:"varint,9,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - RuleUrl string `protobuf:"bytes,10,opt,name=rule_url,json=ruleUrl,proto3" json:"rule_url,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"` + CountTiers []int32 `protobuf:"varint,4,rep,packed,name=count_tiers,json=countTiers,proto3" json:"count_tiers,omitempty"` + AmountTiers []int64 `protobuf:"varint,5,rep,packed,name=amount_tiers,json=amountTiers,proto3" json:"amount_tiers,omitempty"` + DelayedOpenSeconds int32 `protobuf:"varint,6,opt,name=delayed_open_seconds,json=delayedOpenSeconds,proto3" json:"delayed_open_seconds,omitempty"` + ExpireSeconds int32 `protobuf:"varint,7,opt,name=expire_seconds,json=expireSeconds,proto3" json:"expire_seconds,omitempty"` + DailySendLimit int32 `protobuf:"varint,8,opt,name=daily_send_limit,json=dailySendLimit,proto3" json:"daily_send_limit,omitempty"` + OperatorUserId int64 `protobuf:"varint,9,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` + RuleUrl string `protobuf:"bytes,10,opt,name=rule_url,json=ruleUrl,proto3" json:"rule_url,omitempty"` } func (x *UpdateRedPacketConfigRequest) Reset() { @@ -13139,11 +13310,12 @@ func (x *UpdateRedPacketConfigRequest) GetRuleUrl() string { } type UpdateRedPacketConfigResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Config *RedPacketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *RedPacketConfig `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *UpdateRedPacketConfigResponse) Reset() { @@ -13191,18 +13363,19 @@ func (x *UpdateRedPacketConfigResponse) GetServerTimeMs() int64 { } type CreateRedPacketRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - PacketType string `protobuf:"bytes,7,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` - TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` - PacketCount int32 `protobuf:"varint,9,opt,name=packet_count,json=packetCount,proto3" json:"packet_count,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + RoomId string `protobuf:"bytes,5,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + RegionId int64 `protobuf:"varint,6,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + PacketType string `protobuf:"bytes,7,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` + TotalAmount int64 `protobuf:"varint,8,opt,name=total_amount,json=totalAmount,proto3" json:"total_amount,omitempty"` + PacketCount int32 `protobuf:"varint,9,opt,name=packet_count,json=packetCount,proto3" json:"packet_count,omitempty"` } func (x *CreateRedPacketRequest) Reset() { @@ -13299,12 +13472,13 @@ func (x *CreateRedPacketRequest) GetPacketCount() int32 { } type CreateRedPacketResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` - BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` + BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *CreateRedPacketResponse) Reset() { @@ -13359,14 +13533,15 @@ func (x *CreateRedPacketResponse) GetServerTimeMs() int64 { } type ClaimRedPacketRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` - PacketId string `protobuf:"bytes,4,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` - UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + CommandId string `protobuf:"bytes,3,opt,name=command_id,json=commandId,proto3" json:"command_id,omitempty"` + PacketId string `protobuf:"bytes,4,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` + UserId int64 `protobuf:"varint,5,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` } func (x *ClaimRedPacketRequest) Reset() { @@ -13435,13 +13610,14 @@ func (x *ClaimRedPacketRequest) GetUserId() int64 { } type ClaimRedPacketResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Claim *RedPacketClaim `protobuf:"bytes,1,opt,name=claim,proto3" json:"claim,omitempty"` - BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - Packet *RedPacket `protobuf:"bytes,4,opt,name=packet,proto3" json:"packet,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Claim *RedPacketClaim `protobuf:"bytes,1,opt,name=claim,proto3" json:"claim,omitempty"` + BalanceAfter int64 `protobuf:"varint,2,opt,name=balance_after,json=balanceAfter,proto3" json:"balance_after,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` + Packet *RedPacket `protobuf:"bytes,4,opt,name=packet,proto3" json:"packet,omitempty"` } func (x *ClaimRedPacketResponse) Reset() { @@ -13503,21 +13679,22 @@ func (x *ClaimRedPacketResponse) GetPacket() *RedPacket { } type ListRedPacketsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` - SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` - RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` - PacketType string `protobuf:"bytes,6,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` - Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` - ViewerUserId int64 `protobuf:"varint,8,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - StartAtMs int64 `protobuf:"varint,9,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` - EndAtMs int64 `protobuf:"varint,10,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` - Page int32 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"` - PageSize int32 `protobuf:"varint,12,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RoomId string `protobuf:"bytes,3,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"` + SenderUserId int64 `protobuf:"varint,4,opt,name=sender_user_id,json=senderUserId,proto3" json:"sender_user_id,omitempty"` + RegionId int64 `protobuf:"varint,5,opt,name=region_id,json=regionId,proto3" json:"region_id,omitempty"` + PacketType string `protobuf:"bytes,6,opt,name=packet_type,json=packetType,proto3" json:"packet_type,omitempty"` + Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` + ViewerUserId int64 `protobuf:"varint,8,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` + StartAtMs int64 `protobuf:"varint,9,opt,name=start_at_ms,json=startAtMs,proto3" json:"start_at_ms,omitempty"` + EndAtMs int64 `protobuf:"varint,10,opt,name=end_at_ms,json=endAtMs,proto3" json:"end_at_ms,omitempty"` + Page int32 `protobuf:"varint,11,opt,name=page,proto3" json:"page,omitempty"` + PageSize int32 `protobuf:"varint,12,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` } func (x *ListRedPacketsRequest) Reset() { @@ -13635,12 +13812,13 @@ func (x *ListRedPacketsRequest) GetPageSize() int32 { } type ListRedPacketsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Packets []*RedPacket `protobuf:"bytes,1,rep,name=packets,proto3" json:"packets,omitempty"` - Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packets []*RedPacket `protobuf:"bytes,1,rep,name=packets,proto3" json:"packets,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *ListRedPacketsResponse) Reset() { @@ -13695,14 +13873,15 @@ func (x *ListRedPacketsResponse) GetServerTimeMs() int64 { } type GetRedPacketRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - PacketId string `protobuf:"bytes,3,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` - ViewerUserId int64 `protobuf:"varint,4,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` - IncludeClaims bool `protobuf:"varint,5,opt,name=include_claims,json=includeClaims,proto3" json:"include_claims,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PacketId string `protobuf:"bytes,3,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` + ViewerUserId int64 `protobuf:"varint,4,opt,name=viewer_user_id,json=viewerUserId,proto3" json:"viewer_user_id,omitempty"` + IncludeClaims bool `protobuf:"varint,5,opt,name=include_claims,json=includeClaims,proto3" json:"include_claims,omitempty"` } func (x *GetRedPacketRequest) Reset() { @@ -13771,11 +13950,12 @@ func (x *GetRedPacketRequest) GetIncludeClaims() bool { } type GetRedPacketResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` - ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` + ServerTimeMs int64 `protobuf:"varint,2,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *GetRedPacketResponse) Reset() { @@ -13823,12 +14003,13 @@ func (x *GetRedPacketResponse) GetServerTimeMs() int64 { } type ExpireRedPacketsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - BatchSize int32 `protobuf:"varint,3,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + BatchSize int32 `protobuf:"varint,3,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` } func (x *ExpireRedPacketsRequest) Reset() { @@ -13883,12 +14064,13 @@ func (x *ExpireRedPacketsRequest) GetBatchSize() int32 { } type ExpireRedPacketsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ExpiredCount int32 `protobuf:"varint,1,opt,name=expired_count,json=expiredCount,proto3" json:"expired_count,omitempty"` - RefundedAmount int64 `protobuf:"varint,2,opt,name=refunded_amount,json=refundedAmount,proto3" json:"refunded_amount,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExpiredCount int32 `protobuf:"varint,1,opt,name=expired_count,json=expiredCount,proto3" json:"expired_count,omitempty"` + RefundedAmount int64 `protobuf:"varint,2,opt,name=refunded_amount,json=refundedAmount,proto3" json:"refunded_amount,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *ExpireRedPacketsResponse) Reset() { @@ -13943,13 +14125,14 @@ func (x *ExpireRedPacketsResponse) GetServerTimeMs() int64 { } type RetryRedPacketRefundRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - PacketId string `protobuf:"bytes,3,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` - OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + PacketId string `protobuf:"bytes,3,opt,name=packet_id,json=packetId,proto3" json:"packet_id,omitempty"` + OperatorUserId int64 `protobuf:"varint,4,opt,name=operator_user_id,json=operatorUserId,proto3" json:"operator_user_id,omitempty"` } func (x *RetryRedPacketRefundRequest) Reset() { @@ -14011,12 +14194,13 @@ func (x *RetryRedPacketRefundRequest) GetOperatorUserId() int64 { } type RetryRedPacketRefundResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` - RefundedAmount int64 `protobuf:"varint,2,opt,name=refunded_amount,json=refundedAmount,proto3" json:"refunded_amount,omitempty"` - ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packet *RedPacket `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` + RefundedAmount int64 `protobuf:"varint,2,opt,name=refunded_amount,json=refundedAmount,proto3" json:"refunded_amount,omitempty"` + ServerTimeMs int64 `protobuf:"varint,3,opt,name=server_time_ms,json=serverTimeMs,proto3" json:"server_time_ms,omitempty"` } func (x *RetryRedPacketRefundResponse) Reset() { @@ -14072,15 +14256,16 @@ func (x *RetryRedPacketRefundResponse) GetServerTimeMs() int64 { // CronBatchRequest 是 cron-service 触发 wallet-service 后台批处理的统一请求。 type CronBatchRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` - AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` - RunId string `protobuf:"bytes,3,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` - WorkerId string `protobuf:"bytes,4,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` - BatchSize int32 `protobuf:"varint,5,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` - LockTtlMs int64 `protobuf:"varint,6,opt,name=lock_ttl_ms,json=lockTtlMs,proto3" json:"lock_ttl_ms,omitempty"` - unknownFields protoimpl.UnknownFields + state protoimpl.MessageState sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + AppCode string `protobuf:"bytes,2,opt,name=app_code,json=appCode,proto3" json:"app_code,omitempty"` + RunId string `protobuf:"bytes,3,opt,name=run_id,json=runId,proto3" json:"run_id,omitempty"` + WorkerId string `protobuf:"bytes,4,opt,name=worker_id,json=workerId,proto3" json:"worker_id,omitempty"` + BatchSize int32 `protobuf:"varint,5,opt,name=batch_size,json=batchSize,proto3" json:"batch_size,omitempty"` + LockTtlMs int64 `protobuf:"varint,6,opt,name=lock_ttl_ms,json=lockTtlMs,proto3" json:"lock_ttl_ms,omitempty"` } func (x *CronBatchRequest) Reset() { @@ -14157,14 +14342,15 @@ func (x *CronBatchRequest) GetLockTtlMs() int64 { // CronBatchResponse 返回一个批处理 run 的执行摘要。 type CronBatchResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ClaimedCount int32 `protobuf:"varint,1,opt,name=claimed_count,json=claimedCount,proto3" json:"claimed_count,omitempty"` - ProcessedCount int32 `protobuf:"varint,2,opt,name=processed_count,json=processedCount,proto3" json:"processed_count,omitempty"` - SuccessCount int32 `protobuf:"varint,3,opt,name=success_count,json=successCount,proto3" json:"success_count,omitempty"` - FailureCount int32 `protobuf:"varint,4,opt,name=failure_count,json=failureCount,proto3" json:"failure_count,omitempty"` - HasMore bool `protobuf:"varint,5,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClaimedCount int32 `protobuf:"varint,1,opt,name=claimed_count,json=claimedCount,proto3" json:"claimed_count,omitempty"` + ProcessedCount int32 `protobuf:"varint,2,opt,name=processed_count,json=processedCount,proto3" json:"processed_count,omitempty"` + SuccessCount int32 `protobuf:"varint,3,opt,name=success_count,json=successCount,proto3" json:"success_count,omitempty"` + FailureCount int32 `protobuf:"varint,4,opt,name=failure_count,json=failureCount,proto3" json:"failure_count,omitempty"` + HasMore bool `protobuf:"varint,5,opt,name=has_more,json=hasMore,proto3" json:"has_more,omitempty"` } func (x *CronBatchResponse) Reset() { @@ -14234,1546 +14420,3118 @@ func (x *CronBatchResponse) GetHasMore() bool { var File_proto_wallet_v1_wallet_proto protoreflect.FileDescriptor -const file_proto_wallet_v1_wallet_proto_rawDesc = "" + - "\n" + - "\x1cproto/wallet/v1/wallet.proto\x12\x0fhyapp.wallet.v1\"\xec\x03\n" + - "\x10DebitGiftRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0esender_user_id\x18\x03 \x01(\x03R\fsenderUserId\x12$\n" + - "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12\x17\n" + - "\agift_id\x18\x05 \x01(\tR\x06giftId\x12\x1d\n" + - "\n" + - "gift_count\x18\x06 \x01(\x05R\tgiftCount\x12#\n" + - "\rprice_version\x18\a \x01(\tR\fpriceVersion\x12\x19\n" + - "\bapp_code\x18\b \x01(\tR\aappCode\x12\x1b\n" + - "\tregion_id\x18\t \x01(\x03R\bregionId\x12$\n" + - "\x0etarget_is_host\x18\n" + - " \x01(\bR\ftargetIsHost\x121\n" + - "\x15target_host_region_id\x18\v \x01(\x03R\x12targetHostRegionId\x12<\n" + - "\x1btarget_agency_owner_user_id\x18\f \x01(\x03R\x17targetAgencyOwnerUserId\x12(\n" + - "\x10sender_region_id\x18\r \x01(\x03R\x0esenderRegionId\"\xff\x03\n" + - "\x11DebitGiftResponse\x12,\n" + - "\x12billing_receipt_id\x18\x01 \x01(\tR\x10billingReceiptId\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12\x1d\n" + - "\n" + - "coin_spent\x18\x03 \x01(\x03R\tcoinSpent\x12(\n" + - "\x10gift_point_added\x18\x04 \x01(\x03R\x0egiftPointAdded\x12\x1d\n" + - "\n" + - "heat_value\x18\x05 \x01(\x03R\theatValue\x12#\n" + - "\rprice_version\x18\x06 \x01(\tR\fpriceVersion\x12#\n" + - "\rbalance_after\x18\a \x01(\x03R\fbalanceAfter\x12*\n" + - "\x11charge_asset_type\x18\b \x01(\tR\x0fchargeAssetType\x12#\n" + - "\rcharge_amount\x18\t \x01(\x03R\fchargeAmount\x12$\n" + - "\x0egift_type_code\x18\n" + - " \x01(\tR\fgiftTypeCode\x129\n" + - "\x19host_period_diamond_added\x18\v \x01(\x03R\x16hostPeriodDiamondAdded\x121\n" + - "\x15host_period_cycle_key\x18\f \x01(\tR\x12hostPeriodCycleKey\"\xed\x01\n" + - "\x0fDebitGiftTarget\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12$\n" + - "\x0etarget_is_host\x18\x03 \x01(\bR\ftargetIsHost\x121\n" + - "\x15target_host_region_id\x18\x04 \x01(\x03R\x12targetHostRegionId\x12<\n" + - "\x1btarget_agency_owner_user_id\x18\x05 \x01(\x03R\x17targetAgencyOwnerUserId\"\xf0\x02\n" + - "\x15BatchDebitGiftRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + - "\aroom_id\x18\x02 \x01(\tR\x06roomId\x12$\n" + - "\x0esender_user_id\x18\x03 \x01(\x03R\fsenderUserId\x12\x17\n" + - "\agift_id\x18\x04 \x01(\tR\x06giftId\x12\x1d\n" + - "\n" + - "gift_count\x18\x05 \x01(\x05R\tgiftCount\x12#\n" + - "\rprice_version\x18\x06 \x01(\tR\fpriceVersion\x12\x19\n" + - "\bapp_code\x18\a \x01(\tR\aappCode\x12\x1b\n" + - "\tregion_id\x18\b \x01(\x03R\bregionId\x12(\n" + - "\x10sender_region_id\x18\t \x01(\x03R\x0esenderRegionId\x12:\n" + - "\atargets\x18\n" + - " \x03(\v2 .hyapp.wallet.v1.DebitGiftTargetR\atargets\"\x9a\x01\n" + - "\x15BatchDebitGiftReceipt\x12$\n" + - "\x0etarget_user_id\x18\x01 \x01(\x03R\ftargetUserId\x12\x1d\n" + - "\n" + - "command_id\x18\x02 \x01(\tR\tcommandId\x12<\n" + - "\abilling\x18\x03 \x01(\v2\".hyapp.wallet.v1.DebitGiftResponseR\abilling\"\x9e\x01\n" + - "\x16BatchDebitGiftResponse\x12@\n" + - "\taggregate\x18\x01 \x01(\v2\".hyapp.wallet.v1.DebitGiftResponseR\taggregate\x12B\n" + - "\breceipts\x18\x02 \x03(\v2&.hyapp.wallet.v1.BatchDebitGiftReceiptR\breceipts\"\xb2\x01\n" + - "\fAssetBalance\x12\x1d\n" + - "\n" + - "asset_type\x18\x01 \x01(\tR\tassetType\x12)\n" + - "\x10available_amount\x18\x02 \x01(\x03R\x0favailableAmount\x12#\n" + - "\rfrozen_amount\x18\x03 \x01(\x03R\ffrozenAmount\x12\x18\n" + - "\aversion\x18\x04 \x01(\x03R\aversion\x12\x19\n" + - "\bapp_code\x18\x05 \x01(\tR\aappCode\"\x88\x01\n" + - "\x12GetBalancesRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12\x1f\n" + - "\vasset_types\x18\x03 \x03(\tR\n" + - "assetTypes\x12\x19\n" + - "\bapp_code\x18\x04 \x01(\tR\aappCode\"P\n" + - "\x13GetBalancesResponse\x129\n" + - "\bbalances\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\bbalances\"\xaa\x02\n" + - "\x15HostSalaryPolicyLevel\x12\x19\n" + - "\blevel_no\x18\x01 \x01(\x05R\alevelNo\x12+\n" + - "\x11required_diamonds\x18\x02 \x01(\x03R\x10requiredDiamonds\x121\n" + - "\x15host_salary_usd_minor\x18\x03 \x01(\x03R\x12hostSalaryUsdMinor\x12(\n" + - "\x10host_coin_reward\x18\x04 \x01(\x03R\x0ehostCoinReward\x125\n" + - "\x17agency_salary_usd_minor\x18\x05 \x01(\x03R\x14agencySalaryUsdMinor\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\"\xe9\x03\n" + - "\x10HostSalaryPolicy\x12\x1b\n" + - "\tpolicy_id\x18\x01 \x01(\x04R\bpolicyId\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x1b\n" + - "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12'\n" + - "\x0fsettlement_mode\x18\x05 \x01(\tR\x0esettlementMode\x126\n" + - "\x17settlement_trigger_mode\x18\x06 \x01(\tR\x15settlementTriggerMode\x12:\n" + - "\x1agift_coin_to_diamond_ratio\x18\a \x01(\tR\x16giftCoinToDiamondRatio\x12>\n" + - "\x1cresidual_diamond_to_usd_rate\x18\b \x01(\tR\x18residualDiamondToUsdRate\x12*\n" + - "\x11effective_from_ms\x18\t \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\n" + - " \x01(\x03R\reffectiveToMs\x12>\n" + - "\x06levels\x18\v \x03(\v2&.hyapp.wallet.v1.HostSalaryPolicyLevelR\x06levels\"\xf1\x01\n" + - " GetActiveHostSalaryPolicyRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + - "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12'\n" + - "\x0fsettlement_mode\x18\x04 \x01(\tR\x0esettlementMode\x126\n" + - "\x17settlement_trigger_mode\x18\x05 \x01(\tR\x15settlementTriggerMode\x12\x15\n" + - "\x06now_ms\x18\x06 \x01(\x03R\x05nowMs\"t\n" + - "!GetActiveHostSalaryPolicyResponse\x12\x14\n" + - "\x05found\x18\x01 \x01(\bR\x05found\x129\n" + - "\x06policy\x18\x02 \x01(\v2!.hyapp.wallet.v1.HostSalaryPolicyR\x06policy\"\x9a\x02\n" + - "\x12HostSalaryProgress\x12 \n" + - "\fhost_user_id\x18\x01 \x01(\x03R\n" + - "hostUserId\x12\x1b\n" + - "\tcycle_key\x18\x02 \x01(\tR\bcycleKey\x12\x1b\n" + - "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12/\n" + - "\x14agency_owner_user_id\x18\x04 \x01(\x03R\x11agencyOwnerUserId\x12%\n" + - "\x0etotal_diamonds\x18\x05 \x01(\x03R\rtotalDiamonds\x12,\n" + - "\x12gift_diamond_total\x18\x06 \x01(\x03R\x10giftDiamondTotal\x12\"\n" + - "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\"\xae\x01\n" + - "\x1cGetHostSalaryProgressRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12 \n" + - "\fhost_user_id\x18\x03 \x01(\x03R\n" + - "hostUserId\x12\x1b\n" + - "\tcycle_key\x18\x04 \x01(\tR\bcycleKey\x12\x15\n" + - "\x06now_ms\x18\x05 \x01(\x03R\x05nowMs\"`\n" + - "\x1dGetHostSalaryProgressResponse\x12?\n" + - "\bprogress\x18\x01 \x01(\v2#.hyapp.wallet.v1.HostSalaryProgressR\bprogress\"\x95\x02\n" + - "\x17AdminCreditAssetRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + - "\x0etarget_user_id\x18\x02 \x01(\x03R\ftargetUserId\x12\x1d\n" + - "\n" + - "asset_type\x18\x03 \x01(\tR\tassetType\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12(\n" + - "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + - "\x06reason\x18\x06 \x01(\tR\x06reason\x12!\n" + - "\fevidence_ref\x18\a \x01(\tR\vevidenceRef\x12\x19\n" + - "\bapp_code\x18\b \x01(\tR\aappCode\"z\n" + - "\x18AdminCreditAssetResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + - "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\"\xa3\x03\n" + - "!AdminCreditCoinSellerStockRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + - "\x0eseller_user_id\x18\x02 \x01(\x03R\fsellerUserId\x12\x1d\n" + - "\n" + - "stock_type\x18\x03 \x01(\tR\tstockType\x12\x1f\n" + - "\vcoin_amount\x18\x04 \x01(\x03R\n" + - "coinAmount\x12,\n" + - "\x12paid_currency_code\x18\x05 \x01(\tR\x10paidCurrencyCode\x12*\n" + - "\x11paid_amount_micro\x18\x06 \x01(\x03R\x0fpaidAmountMicro\x12\x1f\n" + - "\vpayment_ref\x18\a \x01(\tR\n" + - "paymentRef\x12!\n" + - "\fevidence_ref\x18\b \x01(\tR\vevidenceRef\x12(\n" + - "\x10operator_user_id\x18\t \x01(\x03R\x0eoperatorUserId\x12\x16\n" + - "\x06reason\x18\n" + - " \x01(\tR\x06reason\x12\x19\n" + - "\bapp_code\x18\v \x01(\tR\aappCode\"\x8f\x03\n" + - "\"AdminCreditCoinSellerStockResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12$\n" + - "\x0eseller_user_id\x18\x02 \x01(\x03R\fsellerUserId\x12\x1d\n" + - "\n" + - "stock_type\x18\x03 \x01(\tR\tstockType\x12\x1f\n" + - "\vcoin_amount\x18\x04 \x01(\x03R\n" + - "coinAmount\x12,\n" + - "\x12paid_currency_code\x18\x05 \x01(\tR\x10paidCurrencyCode\x12*\n" + - "\x11paid_amount_micro\x18\x06 \x01(\x03R\x0fpaidAmountMicro\x129\n" + - "\x19counts_as_seller_recharge\x18\a \x01(\bR\x16countsAsSellerRecharge\x12#\n" + - "\rbalance_after\x18\b \x01(\x03R\fbalanceAfter\x12\"\n" + - "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\"\xa9\x02\n" + - "\x1dTransferCoinFromSellerRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + - "\x0eseller_user_id\x18\x02 \x01(\x03R\fsellerUserId\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12\x16\n" + - "\x06reason\x18\x05 \x01(\tR\x06reason\x12\x19\n" + - "\bapp_code\x18\x06 \x01(\tR\aappCode\x12(\n" + - "\x10seller_region_id\x18\a \x01(\x03R\x0esellerRegionId\x12(\n" + - "\x10target_region_id\x18\b \x01(\x03R\x0etargetRegionId\"\x94\x04\n" + - "\x1eTransferCoinFromSellerResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x120\n" + - "\x14seller_balance_after\x18\x02 \x01(\x03R\x12sellerBalanceAfter\x120\n" + - "\x14target_balance_after\x18\x03 \x01(\x03R\x12targetBalanceAfter\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12,\n" + - "\x12recharge_usd_minor\x18\x05 \x01(\x03R\x10rechargeUsdMinor\x124\n" + - "\x16recharge_currency_code\x18\x06 \x01(\tR\x14rechargeCurrencyCode\x12,\n" + - "\x12recharge_policy_id\x18\a \x01(\x03R\x10rechargePolicyId\x126\n" + - "\x17recharge_policy_version\x18\b \x01(\tR\x15rechargePolicyVersion\x12=\n" + - "\x1brecharge_policy_coin_amount\x18\t \x01(\x03R\x18rechargePolicyCoinAmount\x12F\n" + - " recharge_policy_usd_minor_amount\x18\n" + - " \x01(\x03R\x1crechargePolicyUsdMinorAmount\"\x84\x02\n" + - " CoinSellerSalaryExchangeRateTier\x12\x1b\n" + - "\tregion_id\x18\x01 \x01(\x03R\bregionId\x12\"\n" + - "\rmin_usd_minor\x18\x02 \x01(\x03R\vminUsdMinor\x12\"\n" + - "\rmax_usd_minor\x18\x03 \x01(\x03R\vmaxUsdMinor\x12 \n" + - "\fcoin_per_usd\x18\x04 \x01(\x03R\n" + - "coinPerUsd\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "sort_order\x18\x06 \x01(\x05R\tsortOrder\x12\"\n" + - "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\"\xb0\x01\n" + - ",ListCoinSellerSalaryExchangeRateTiersRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + - "\tregion_id\x18\x03 \x01(\x03R\bregionId\x12)\n" + - "\x10include_disabled\x18\x04 \x01(\bR\x0fincludeDisabled\"x\n" + - "-ListCoinSellerSalaryExchangeRateTiersResponse\x12G\n" + - "\x05tiers\x18\x01 \x03(\v21.hyapp.wallet.v1.CoinSellerSalaryExchangeRateTierR\x05tiers\"\xde\x01\n" + - "\x1bExchangeSalaryToCoinRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x17\n" + - "\auser_id\x18\x02 \x01(\x03R\x06userId\x12*\n" + - "\x11salary_asset_type\x18\x03 \x01(\tR\x0fsalaryAssetType\x12(\n" + - "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x16\n" + - "\x06reason\x18\x05 \x01(\tR\x06reason\x12\x19\n" + - "\bapp_code\x18\x06 \x01(\tR\aappCode\"\x92\x02\n" + - "\x1cExchangeSalaryToCoinResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x120\n" + - "\x14salary_balance_after\x18\x02 \x01(\x03R\x12salaryBalanceAfter\x12,\n" + - "\x12coin_balance_after\x18\x03 \x01(\x03R\x10coinBalanceAfter\x12(\n" + - "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x1f\n" + - "\vcoin_amount\x18\x05 \x01(\x03R\n" + - "coinAmount\x12 \n" + - "\fcoin_per_usd\x18\x06 \x01(\x03R\n" + - "coinPerUsd\"\xb4\x02\n" + - "!TransferSalaryToCoinSellerRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12$\n" + - "\x0esource_user_id\x18\x02 \x01(\x03R\fsourceUserId\x12$\n" + - "\x0eseller_user_id\x18\x03 \x01(\x03R\fsellerUserId\x12*\n" + - "\x11salary_asset_type\x18\x04 \x01(\tR\x0fsalaryAssetType\x12(\n" + - "\x10salary_usd_minor\x18\x05 \x01(\x03R\x0esalaryUsdMinor\x12\x1b\n" + - "\tregion_id\x18\x06 \x01(\x03R\bregionId\x12\x16\n" + - "\x06reason\x18\a \x01(\tR\x06reason\x12\x19\n" + - "\bapp_code\x18\b \x01(\tR\aappCode\"\x83\x03\n" + - "\"TransferSalaryToCoinSellerResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12=\n" + - "\x1bsource_salary_balance_after\x18\x02 \x01(\x03R\x18sourceSalaryBalanceAfter\x120\n" + - "\x14seller_balance_after\x18\x03 \x01(\x03R\x12sellerBalanceAfter\x12(\n" + - "\x10salary_usd_minor\x18\x04 \x01(\x03R\x0esalaryUsdMinor\x12\x1f\n" + - "\vcoin_amount\x18\x05 \x01(\x03R\n" + - "coinAmount\x12 \n" + - "\fcoin_per_usd\x18\x06 \x01(\x03R\n" + - "coinPerUsd\x12+\n" + - "\x12rate_min_usd_minor\x18\a \x01(\x03R\x0frateMinUsdMinor\x12+\n" + - "\x12rate_max_usd_minor\x18\b \x01(\x03R\x0frateMaxUsdMinor\"\xe7\x06\n" + - "\bResource\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1f\n" + - "\vresource_id\x18\x02 \x01(\x03R\n" + - "resourceId\x12#\n" + - "\rresource_code\x18\x03 \x01(\tR\fresourceCode\x12#\n" + - "\rresource_type\x18\x04 \x01(\tR\fresourceType\x12\x12\n" + - "\x04name\x18\x05 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12\x1c\n" + - "\tgrantable\x18\a \x01(\bR\tgrantable\x12%\n" + - "\x0egrant_strategy\x18\b \x01(\tR\rgrantStrategy\x12*\n" + - "\x11wallet_asset_type\x18\t \x01(\tR\x0fwalletAssetType\x12.\n" + - "\x13wallet_asset_amount\x18\n" + - " \x01(\x03R\x11walletAssetAmount\x12!\n" + - "\fusage_scopes\x18\v \x03(\tR\vusageScopes\x12\x1b\n" + - "\tasset_url\x18\f \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\r \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\x0e \x01(\tR\fanimationUrl\x12#\n" + - "\rmetadata_json\x18\x0f \x01(\tR\fmetadataJson\x12\x1d\n" + - "\n" + - "sort_order\x18\x10 \x01(\x05R\tsortOrder\x12+\n" + - "\x12created_by_user_id\x18\x11 \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\x12 \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\x13 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x14 \x01(\x03R\vupdatedAtMs\x122\n" + - "\x15manager_grant_enabled\x18\x15 \x01(\bR\x13managerGrantEnabled\x12\x1d\n" + - "\n" + - "price_type\x18\x16 \x01(\tR\tpriceType\x12\x1d\n" + - "\n" + - "coin_price\x18\x17 \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\x18 \x01(\x03R\x0fgiftPointAmount\"\xc7\x03\n" + - "\x11ResourceGroupItem\x12\"\n" + - "\rgroup_item_id\x18\x01 \x01(\x03R\vgroupItemId\x12\x19\n" + - "\bgroup_id\x18\x02 \x01(\x03R\agroupId\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x125\n" + - "\bresource\x18\x04 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x12\x1a\n" + - "\bquantity\x18\x05 \x01(\x03R\bquantity\x12\x1f\n" + - "\vduration_ms\x18\x06 \x01(\x03R\n" + - "durationMs\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12\"\n" + - "\rcreated_at_ms\x18\b \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\t \x01(\x03R\vupdatedAtMs\x12\x1b\n" + - "\titem_type\x18\n" + - " \x01(\tR\bitemType\x12*\n" + - "\x11wallet_asset_type\x18\v \x01(\tR\x0fwalletAssetType\x12.\n" + - "\x13wallet_asset_amount\x18\f \x01(\x03R\x11walletAssetAmount\"\xad\x03\n" + - "\rResourceGroup\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x19\n" + - "\bgroup_id\x18\x02 \x01(\x03R\agroupId\x12\x1d\n" + - "\n" + - "group_code\x18\x03 \x01(\tR\tgroupCode\x12\x12\n" + - "\x04name\x18\x04 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12 \n" + - "\vdescription\x18\x06 \x01(\tR\vdescription\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x128\n" + - "\x05items\x18\b \x03(\v2\".hyapp.wallet.v1.ResourceGroupItemR\x05items\x12+\n" + - "\x12created_by_user_id\x18\t \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\n" + - " \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\f \x01(\x03R\vupdatedAtMs\"\xa9\x06\n" + - "\n" + - "GiftConfig\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x17\n" + - "\agift_id\x18\x02 \x01(\tR\x06giftId\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x125\n" + - "\bresource\x18\x04 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12\x12\n" + - "\x04name\x18\x06 \x01(\tR\x04name\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12+\n" + - "\x11presentation_json\x18\b \x01(\tR\x10presentationJson\x12#\n" + - "\rprice_version\x18\t \x01(\tR\fpriceVersion\x12\x1d\n" + - "\n" + - "coin_price\x18\n" + - " \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\v \x01(\x03R\x0fgiftPointAmount\x12\x1d\n" + - "\n" + - "heat_value\x18\f \x01(\x03R\theatValue\x12+\n" + - "\x12created_by_user_id\x18\r \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\x0e \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\x0f \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x10 \x01(\x03R\vupdatedAtMs\x12\x1d\n" + - "\n" + - "region_ids\x18\x11 \x03(\x03R\tregionIds\x12$\n" + - "\x0egift_type_code\x18\x12 \x01(\tR\fgiftTypeCode\x12*\n" + - "\x11charge_asset_type\x18\x13 \x01(\tR\x0fchargeAssetType\x12*\n" + - "\x11effective_from_ms\x18\x14 \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\x15 \x01(\x03R\reffectiveToMs\x12!\n" + - "\feffect_types\x18\x16 \x03(\tR\veffectTypes\"\xce\x02\n" + - "\x0eGiftTypeConfig\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1b\n" + - "\ttype_code\x18\x02 \x01(\tR\btypeCode\x12\x12\n" + - "\x04name\x18\x03 \x01(\tR\x04name\x12\x17\n" + - "\atab_key\x18\x04 \x01(\tR\x06tabKey\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "sort_order\x18\x06 \x01(\x05R\tsortOrder\x12+\n" + - "\x12created_by_user_id\x18\a \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\b \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\n" + - " \x01(\x03R\vupdatedAtMs\"\xb7\x04\n" + - "\x10ResourceShopItem\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12 \n" + - "\fshop_item_id\x18\x02 \x01(\x03R\n" + - "shopItemId\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x125\n" + - "\bresource\x18\x04 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12#\n" + - "\rduration_days\x18\x06 \x01(\x05R\fdurationDays\x12\x1d\n" + - "\n" + - "price_type\x18\a \x01(\tR\tpriceType\x12\x1d\n" + - "\n" + - "coin_price\x18\b \x01(\x03R\tcoinPrice\x12*\n" + - "\x11effective_from_ms\x18\t \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\n" + - " \x01(\x03R\reffectiveToMs\x12\x1d\n" + - "\n" + - "sort_order\x18\v \x01(\x05R\tsortOrder\x12+\n" + - "\x12created_by_user_id\x18\f \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\r \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\x0e \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x0f \x01(\x03R\vupdatedAtMs\"\x87\x04\n" + - "\x17UserResourceEntitlement\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12%\n" + - "\x0eentitlement_id\x18\x02 \x01(\tR\rentitlementId\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x1f\n" + - "\vresource_id\x18\x04 \x01(\x03R\n" + - "resourceId\x125\n" + - "\bresource\x18\x05 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12\x1a\n" + - "\bquantity\x18\a \x01(\x03R\bquantity\x12-\n" + - "\x12remaining_quantity\x18\b \x01(\x03R\x11remainingQuantity\x12&\n" + - "\x0feffective_at_ms\x18\t \x01(\x03R\reffectiveAtMs\x12\"\n" + - "\rexpires_at_ms\x18\n" + - " \x01(\x03R\vexpiresAtMs\x12&\n" + - "\x0fsource_grant_id\x18\v \x01(\tR\rsourceGrantId\x12\"\n" + - "\rcreated_at_ms\x18\f \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\r \x01(\x03R\vupdatedAtMs\x12\x1a\n" + - "\bequipped\x18\x0e \x01(\bR\bequipped\"\x86\x03\n" + - "\x11ResourceGrantItem\x12\"\n" + - "\rgrant_item_id\x18\x01 \x01(\x03R\vgrantItemId\x12\x19\n" + - "\bgrant_id\x18\x02 \x01(\tR\agrantId\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x124\n" + - "\x16resource_snapshot_json\x18\x04 \x01(\tR\x14resourceSnapshotJson\x12\x1a\n" + - "\bquantity\x18\x05 \x01(\x03R\bquantity\x12\x1f\n" + - "\vduration_ms\x18\x06 \x01(\x03R\n" + - "durationMs\x12\x1f\n" + - "\vresult_type\x18\a \x01(\tR\n" + - "resultType\x122\n" + - "\x15wallet_transaction_id\x18\b \x01(\tR\x13walletTransactionId\x12%\n" + - "\x0eentitlement_id\x18\t \x01(\tR\rentitlementId\x12\"\n" + - "\rcreated_at_ms\x18\n" + - " \x01(\x03R\vcreatedAtMs\"\xe1\x03\n" + - "\rResourceGrant\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x19\n" + - "\bgrant_id\x18\x02 \x01(\tR\agrantId\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12$\n" + - "\x0etarget_user_id\x18\x04 \x01(\x03R\ftargetUserId\x12!\n" + - "\fgrant_source\x18\x05 \x01(\tR\vgrantSource\x12,\n" + - "\x12grant_subject_type\x18\x06 \x01(\tR\x10grantSubjectType\x12(\n" + - "\x10grant_subject_id\x18\a \x01(\tR\x0egrantSubjectId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\x12\x16\n" + - "\x06reason\x18\t \x01(\tR\x06reason\x12(\n" + - "\x10operator_user_id\x18\n" + - " \x01(\x03R\x0eoperatorUserId\x128\n" + - "\x05items\x18\v \x03(\v2\".hyapp.wallet.v1.ResourceGrantItemR\x05items\x12\"\n" + - "\rcreated_at_ms\x18\f \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\r \x01(\x03R\vupdatedAtMs\"\x8e\x02\n" + - "\x16ResourceGroupItemInput\x12\x1f\n" + - "\vresource_id\x18\x01 \x01(\x03R\n" + - "resourceId\x12\x1a\n" + - "\bquantity\x18\x02 \x01(\x03R\bquantity\x12\x1f\n" + - "\vduration_ms\x18\x03 \x01(\x03R\n" + - "durationMs\x12\x1d\n" + - "\n" + - "sort_order\x18\x04 \x01(\x05R\tsortOrder\x12\x1b\n" + - "\titem_type\x18\x05 \x01(\tR\bitemType\x12*\n" + - "\x11wallet_asset_type\x18\x06 \x01(\tR\x0fwalletAssetType\x12.\n" + - "\x13wallet_asset_amount\x18\a \x01(\x03R\x11walletAssetAmount\"\xa7\x02\n" + - "\x14ListResourcesRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + - "\rresource_type\x18\x03 \x01(\tR\fresourceType\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12\x18\n" + - "\akeyword\x18\x05 \x01(\tR\akeyword\x12\x12\n" + - "\x04page\x18\x06 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\a \x01(\x05R\bpageSize\x12\x1f\n" + - "\vactive_only\x18\b \x01(\bR\n" + - "activeOnly\x12,\n" + - "\x12manager_grant_only\x18\t \x01(\bR\x10managerGrantOnly\"f\n" + - "\x15ListResourcesResponse\x127\n" + - "\tresources\x18\x01 \x03(\v2\x19.hyapp.wallet.v1.ResourceR\tresources\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"o\n" + - "\x12GetResourceRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\"L\n" + - "\x13GetResourceResponse\x125\n" + - "\bresource\x18\x01 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\"\x99\x06\n" + - "\x15CreateResourceRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + - "\rresource_code\x18\x03 \x01(\tR\fresourceCode\x12#\n" + - "\rresource_type\x18\x04 \x01(\tR\fresourceType\x12\x12\n" + - "\x04name\x18\x05 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12\x1c\n" + - "\tgrantable\x18\a \x01(\bR\tgrantable\x12%\n" + - "\x0egrant_strategy\x18\b \x01(\tR\rgrantStrategy\x12*\n" + - "\x11wallet_asset_type\x18\t \x01(\tR\x0fwalletAssetType\x12.\n" + - "\x13wallet_asset_amount\x18\n" + - " \x01(\x03R\x11walletAssetAmount\x12!\n" + - "\fusage_scopes\x18\v \x03(\tR\vusageScopes\x12\x1b\n" + - "\tasset_url\x18\f \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\r \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\x0e \x01(\tR\fanimationUrl\x12#\n" + - "\rmetadata_json\x18\x0f \x01(\tR\fmetadataJson\x12\x1d\n" + - "\n" + - "sort_order\x18\x10 \x01(\x05R\tsortOrder\x12(\n" + - "\x10operator_user_id\x18\x11 \x01(\x03R\x0eoperatorUserId\x127\n" + - "\x15manager_grant_enabled\x18\x12 \x01(\bH\x00R\x13managerGrantEnabled\x88\x01\x01\x12\x1d\n" + - "\n" + - "price_type\x18\x13 \x01(\tR\tpriceType\x12\x1d\n" + - "\n" + - "coin_price\x18\x14 \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\x15 \x01(\x03R\x0fgiftPointAmountB\x18\n" + - "\x16_manager_grant_enabled\"\xba\x06\n" + - "\x15UpdateResourceRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x12#\n" + - "\rresource_code\x18\x04 \x01(\tR\fresourceCode\x12#\n" + - "\rresource_type\x18\x05 \x01(\tR\fresourceType\x12\x12\n" + - "\x04name\x18\x06 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\x12\x1c\n" + - "\tgrantable\x18\b \x01(\bR\tgrantable\x12%\n" + - "\x0egrant_strategy\x18\t \x01(\tR\rgrantStrategy\x12*\n" + - "\x11wallet_asset_type\x18\n" + - " \x01(\tR\x0fwalletAssetType\x12.\n" + - "\x13wallet_asset_amount\x18\v \x01(\x03R\x11walletAssetAmount\x12!\n" + - "\fusage_scopes\x18\f \x03(\tR\vusageScopes\x12\x1b\n" + - "\tasset_url\x18\r \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\x0e \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\x0f \x01(\tR\fanimationUrl\x12#\n" + - "\rmetadata_json\x18\x10 \x01(\tR\fmetadataJson\x12\x1d\n" + - "\n" + - "sort_order\x18\x11 \x01(\x05R\tsortOrder\x12(\n" + - "\x10operator_user_id\x18\x12 \x01(\x03R\x0eoperatorUserId\x127\n" + - "\x15manager_grant_enabled\x18\x13 \x01(\bH\x00R\x13managerGrantEnabled\x88\x01\x01\x12\x1d\n" + - "\n" + - "price_type\x18\x14 \x01(\tR\tpriceType\x12\x1d\n" + - "\n" + - "coin_price\x18\x15 \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\x16 \x01(\x03R\x0fgiftPointAmountB\x18\n" + - "\x16_manager_grant_enabled\"\xb7\x01\n" + - "\x18SetResourceStatusRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12(\n" + - "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"I\n" + - "\x10ResourceResponse\x125\n" + - "\bresource\x18\x01 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\"\xd9\x01\n" + - "\x19ListResourceGroupsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x18\n" + - "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x12\n" + - "\x04page\x18\x05 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x06 \x01(\x05R\bpageSize\x12\x1f\n" + - "\vactive_only\x18\a \x01(\bR\n" + - "activeOnly\"j\n" + - "\x1aListResourceGroupsResponse\x126\n" + - "\x06groups\x18\x01 \x03(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x06groups\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"n\n" + - "\x17GetResourceGroupRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + - "\bgroup_id\x18\x03 \x01(\x03R\agroupId\"P\n" + - "\x18GetResourceGroupResponse\x124\n" + - "\x05group\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\"\xcb\x02\n" + - "\x1aCreateResourceGroupRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "group_code\x18\x03 \x01(\tR\tgroupCode\x12\x12\n" + - "\x04name\x18\x04 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12 \n" + - "\vdescription\x18\x06 \x01(\tR\vdescription\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12=\n" + - "\x05items\x18\b \x03(\v2'.hyapp.wallet.v1.ResourceGroupItemInputR\x05items\x12(\n" + - "\x10operator_user_id\x18\t \x01(\x03R\x0eoperatorUserId\"\xe6\x02\n" + - "\x1aUpdateResourceGroupRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + - "\bgroup_id\x18\x03 \x01(\x03R\agroupId\x12\x1d\n" + - "\n" + - "group_code\x18\x04 \x01(\tR\tgroupCode\x12\x12\n" + - "\x04name\x18\x05 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12 \n" + - "\vdescription\x18\a \x01(\tR\vdescription\x12\x1d\n" + - "\n" + - "sort_order\x18\b \x01(\x05R\tsortOrder\x12=\n" + - "\x05items\x18\t \x03(\v2'.hyapp.wallet.v1.ResourceGroupItemInputR\x05items\x12(\n" + - "\x10operator_user_id\x18\n" + - " \x01(\x03R\x0eoperatorUserId\"\xb6\x01\n" + - "\x1dSetResourceGroupStatusRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + - "\bgroup_id\x18\x03 \x01(\x03R\agroupId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12(\n" + - "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"M\n" + - "\x15ResourceGroupResponse\x124\n" + - "\x05group\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGroupR\x05group\"\xbe\x02\n" + - "\x16ListGiftConfigsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x18\n" + - "\akeyword\x18\x04 \x01(\tR\akeyword\x12\x12\n" + - "\x04page\x18\x05 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x06 \x01(\x05R\bpageSize\x12\x1f\n" + - "\vactive_only\x18\a \x01(\bR\n" + - "activeOnly\x12\x1b\n" + - "\tregion_id\x18\b \x01(\x03R\bregionId\x12#\n" + - "\rfilter_region\x18\t \x01(\bR\ffilterRegion\x12$\n" + - "\x0egift_type_code\x18\n" + - " \x01(\tR\fgiftTypeCode\"b\n" + - "\x17ListGiftConfigsResponse\x121\n" + - "\x05gifts\x18\x01 \x03(\v2\x1b.hyapp.wallet.v1.GiftConfigR\x05gifts\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\x8f\x01\n" + - "\x1aListGiftTypeConfigsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x1f\n" + - "\vactive_only\x18\x04 \x01(\bR\n" + - "activeOnly\"]\n" + - "\x1bListGiftTypeConfigsResponse\x12>\n" + - "\n" + - "gift_types\x18\x01 \x03(\v2\x1f.hyapp.wallet.v1.GiftTypeConfigR\tgiftTypes\"\x82\x02\n" + - "\x1bUpsertGiftTypeConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + - "\ttype_code\x18\x03 \x01(\tR\btypeCode\x12\x12\n" + - "\x04name\x18\x04 \x01(\tR\x04name\x12\x17\n" + - "\atab_key\x18\x05 \x01(\tR\x06tabKey\x12\x16\n" + - "\x06status\x18\x06 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12(\n" + - "\x10operator_user_id\x18\b \x01(\x03R\x0eoperatorUserId\"V\n" + - "\x16GiftTypeConfigResponse\x12<\n" + - "\tgift_type\x18\x01 \x01(\v2\x1f.hyapp.wallet.v1.GiftTypeConfigR\bgiftType\"\xce\x05\n" + - "\x17CreateGiftConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x1f\n" + - "\vresource_id\x18\x04 \x01(\x03R\n" + - "resourceId\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12\x12\n" + - "\x04name\x18\x06 \x01(\tR\x04name\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12+\n" + - "\x11presentation_json\x18\b \x01(\tR\x10presentationJson\x12#\n" + - "\rprice_version\x18\t \x01(\tR\fpriceVersion\x12\x1d\n" + - "\n" + - "coin_price\x18\n" + - " \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\v \x01(\x03R\x0fgiftPointAmount\x12\x1d\n" + - "\n" + - "heat_value\x18\f \x01(\x03R\theatValue\x12&\n" + - "\x0feffective_at_ms\x18\r \x01(\x03R\reffectiveAtMs\x12(\n" + - "\x10operator_user_id\x18\x0e \x01(\x03R\x0eoperatorUserId\x12\x1d\n" + - "\n" + - "region_ids\x18\x0f \x03(\x03R\tregionIds\x12$\n" + - "\x0egift_type_code\x18\x10 \x01(\tR\fgiftTypeCode\x12*\n" + - "\x11charge_asset_type\x18\x11 \x01(\tR\x0fchargeAssetType\x12*\n" + - "\x11effective_from_ms\x18\x12 \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\x13 \x01(\x03R\reffectiveToMs\x12!\n" + - "\feffect_types\x18\x14 \x03(\tR\veffectTypes\"\xce\x05\n" + - "\x17UpdateGiftConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x1f\n" + - "\vresource_id\x18\x04 \x01(\x03R\n" + - "resourceId\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12\x12\n" + - "\x04name\x18\x06 \x01(\tR\x04name\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12+\n" + - "\x11presentation_json\x18\b \x01(\tR\x10presentationJson\x12#\n" + - "\rprice_version\x18\t \x01(\tR\fpriceVersion\x12\x1d\n" + - "\n" + - "coin_price\x18\n" + - " \x01(\x03R\tcoinPrice\x12*\n" + - "\x11gift_point_amount\x18\v \x01(\x03R\x0fgiftPointAmount\x12\x1d\n" + - "\n" + - "heat_value\x18\f \x01(\x03R\theatValue\x12&\n" + - "\x0feffective_at_ms\x18\r \x01(\x03R\reffectiveAtMs\x12(\n" + - "\x10operator_user_id\x18\x0e \x01(\x03R\x0eoperatorUserId\x12\x1d\n" + - "\n" + - "region_ids\x18\x0f \x03(\x03R\tregionIds\x12$\n" + - "\x0egift_type_code\x18\x10 \x01(\tR\fgiftTypeCode\x12*\n" + - "\x11charge_asset_type\x18\x11 \x01(\tR\x0fchargeAssetType\x12*\n" + - "\x11effective_from_ms\x18\x12 \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\x13 \x01(\x03R\reffectiveToMs\x12!\n" + - "\feffect_types\x18\x14 \x03(\tR\veffectTypes\"\xb1\x01\n" + - "\x1aSetGiftConfigStatusRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\agift_id\x18\x03 \x01(\tR\x06giftId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12(\n" + - "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"E\n" + - "\x12GiftConfigResponse\x12/\n" + - "\x04gift\x18\x01 \x01(\v2\x1b.hyapp.wallet.v1.GiftConfigR\x04gift\"\xb9\x02\n" + - "\x14GrantResourceRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x1f\n" + - "\vresource_id\x18\x04 \x01(\x03R\n" + - "resourceId\x12\x1a\n" + - "\bquantity\x18\x05 \x01(\x03R\bquantity\x12\x1f\n" + - "\vduration_ms\x18\x06 \x01(\x03R\n" + - "durationMs\x12\x16\n" + - "\x06reason\x18\a \x01(\tR\x06reason\x12(\n" + - "\x10operator_user_id\x18\b \x01(\x03R\x0eoperatorUserId\x12!\n" + - "\fgrant_source\x18\t \x01(\tR\vgrantSource\"\xfb\x01\n" + - "\x19GrantResourceGroupRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x19\n" + - "\bgroup_id\x18\x04 \x01(\x03R\agroupId\x12\x16\n" + - "\x06reason\x18\x05 \x01(\tR\x06reason\x12(\n" + - "\x10operator_user_id\x18\x06 \x01(\x03R\x0eoperatorUserId\x12!\n" + - "\fgrant_source\x18\a \x01(\tR\vgrantSource\"M\n" + - "\x15ResourceGrantResponse\x124\n" + - "\x05grant\x18\x01 \x01(\v2\x1e.hyapp.wallet.v1.ResourceGrantR\x05grant\"\xb3\x01\n" + - "\x18ListUserResourcesRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12#\n" + - "\rresource_type\x18\x04 \x01(\tR\fresourceType\x12\x1f\n" + - "\vactive_only\x18\x05 \x01(\bR\n" + - "activeOnly\"c\n" + - "\x19ListUserResourcesResponse\x12F\n" + - "\tresources\x18\x01 \x03(\v2(.hyapp.wallet.v1.UserResourceEntitlementR\tresources\"\xb5\x01\n" + - "\x18EquipUserResourceRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x1f\n" + - "\vresource_id\x18\x04 \x01(\x03R\n" + - "resourceId\x12%\n" + - "\x0eentitlement_id\x18\x05 \x01(\tR\rentitlementId\"a\n" + - "\x19EquipUserResourceResponse\x12D\n" + - "\bresource\x18\x01 \x01(\v2(.hyapp.wallet.v1.UserResourceEntitlementR\bresource\"\x94\x01\n" + - "\x1aUnequipUserResourceRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12#\n" + - "\rresource_type\x18\x04 \x01(\tR\fresourceType\"\x86\x01\n" + - "\x1bUnequipUserResourceResponse\x12#\n" + - "\rresource_type\x18\x01 \x01(\tR\fresourceType\x12\x1e\n" + - "\n" + - "unequipped\x18\x02 \x01(\bR\n" + - "unequipped\x12\"\n" + - "\rupdated_at_ms\x18\x03 \x01(\x03R\vupdatedAtMs\"\xa2\x01\n" + - "$BatchGetUserEquippedResourcesRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x19\n" + - "\buser_ids\x18\x03 \x03(\x03R\auserIds\x12%\n" + - "\x0eresource_types\x18\x04 \x03(\tR\rresourceTypes\"x\n" + - "\x15UserEquippedResources\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12F\n" + - "\tresources\x18\x02 \x03(\v2(.hyapp.wallet.v1.UserResourceEntitlementR\tresources\"e\n" + - "%BatchGetUserEquippedResourcesResponse\x12<\n" + - "\x05users\x18\x01 \x03(\v2&.hyapp.wallet.v1.UserEquippedResourcesR\x05users\"\xc4\x01\n" + - "\x19ListResourceGrantsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12\x12\n" + - "\x04page\x18\x05 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x06 \x01(\x05R\bpageSize\"j\n" + - "\x1aListResourceGrantsResponse\x126\n" + - "\x06grants\x18\x01 \x03(\v2\x1e.hyapp.wallet.v1.ResourceGrantR\x06grants\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\x8a\x02\n" + - "\x15ResourceShopItemInput\x12 \n" + - "\fshop_item_id\x18\x01 \x01(\x03R\n" + - "shopItemId\x12\x1f\n" + - "\vresource_id\x18\x02 \x01(\x03R\n" + - "resourceId\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12#\n" + - "\rduration_days\x18\x04 \x01(\x05R\fdurationDays\x12*\n" + - "\x11effective_from_ms\x18\x05 \x01(\x03R\x0feffectiveFromMs\x12&\n" + - "\x0feffective_to_ms\x18\x06 \x01(\x03R\reffectiveToMs\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\"\x81\x02\n" + - "\x1cListResourceShopItemsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12#\n" + - "\rresource_type\x18\x03 \x01(\tR\fresourceType\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12\x18\n" + - "\akeyword\x18\x05 \x01(\tR\akeyword\x12\x12\n" + - "\x04page\x18\x06 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\a \x01(\x05R\bpageSize\x12\x1f\n" + - "\vactive_only\x18\b \x01(\bR\n" + - "activeOnly\"n\n" + - "\x1dListResourceShopItemsResponse\x127\n" + - "\x05items\x18\x01 \x03(\v2!.hyapp.wallet.v1.ResourceShopItemR\x05items\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\xc2\x01\n" + - "\x1eUpsertResourceShopItemsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12<\n" + - "\x05items\x18\x03 \x03(\v2&.hyapp.wallet.v1.ResourceShopItemInputR\x05items\x12(\n" + - "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"Z\n" + - "\x1fUpsertResourceShopItemsResponse\x127\n" + - "\x05items\x18\x01 \x03(\v2!.hyapp.wallet.v1.ResourceShopItemR\x05items\"\xc0\x01\n" + - " SetResourceShopItemStatusRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12 \n" + - "\fshop_item_id\x18\x03 \x01(\x03R\n" + - "shopItemId\x12\x16\n" + - "\x06status\x18\x04 \x01(\tR\x06status\x12(\n" + - "\x10operator_user_id\x18\x05 \x01(\x03R\x0eoperatorUserId\"Q\n" + - "\x18ResourceShopItemResponse\x125\n" + - "\x04item\x18\x01 \x01(\v2!.hyapp.wallet.v1.ResourceShopItemR\x04item\"\x96\x01\n" + - "\x1fPurchaseResourceShopItemRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12 \n" + - "\fshop_item_id\x18\x04 \x01(\x03R\n" + - "shopItemId\"\xee\x02\n" + - " PurchaseResourceShopItemResponse\x12\x19\n" + - "\border_id\x18\x01 \x01(\tR\aorderId\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12*\n" + - "\x11resource_grant_id\x18\x03 \x01(\tR\x0fresourceGrantId\x12>\n" + - "\tshop_item\x18\x04 \x01(\v2!.hyapp.wallet.v1.ResourceShopItemR\bshopItem\x12D\n" + - "\bresource\x18\x05 \x01(\v2(.hyapp.wallet.v1.UserResourceEntitlementR\bresource\x127\n" + - "\abalance\x18\x06 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x1d\n" + - "\n" + - "coin_spent\x18\a \x01(\x03R\tcoinSpent\"\xa7\x05\n" + - "\fRechargeBill\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12#\n" + - "\rrecharge_type\x18\x04 \x01(\tR\frechargeType\x12\x16\n" + - "\x06status\x18\x05 \x01(\tR\x06status\x12!\n" + - "\fexternal_ref\x18\x06 \x01(\tR\vexternalRef\x12\x17\n" + - "\auser_id\x18\a \x01(\x03R\x06userId\x12$\n" + - "\x0eseller_user_id\x18\b \x01(\x03R\fsellerUserId\x12(\n" + - "\x10seller_region_id\x18\t \x01(\x03R\x0esellerRegionId\x12(\n" + - "\x10target_region_id\x18\n" + - " \x01(\x03R\x0etargetRegionId\x12\x1b\n" + - "\tpolicy_id\x18\v \x01(\x03R\bpolicyId\x12%\n" + - "\x0epolicy_version\x18\f \x01(\tR\rpolicyVersion\x12#\n" + - "\rcurrency_code\x18\r \x01(\tR\fcurrencyCode\x12\x1f\n" + - "\vcoin_amount\x18\x0e \x01(\x03R\n" + - "coinAmount\x12(\n" + - "\x10usd_minor_amount\x18\x0f \x01(\x03R\x0eusdMinorAmount\x120\n" + - "\x14exchange_coin_amount\x18\x10 \x01(\x03R\x12exchangeCoinAmount\x129\n" + - "\x19exchange_usd_minor_amount\x18\x11 \x01(\x03R\x16exchangeUsdMinorAmount\x12\"\n" + - "\rcreated_at_ms\x18\x12 \x01(\x03R\vcreatedAtMs\"\xf4\x02\n" + - "\x18ListRechargeBillsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12$\n" + - "\x0eseller_user_id\x18\x04 \x01(\x03R\fsellerUserId\x12\x1b\n" + - "\tregion_id\x18\x05 \x01(\x03R\bregionId\x12#\n" + - "\rrecharge_type\x18\x06 \x01(\tR\frechargeType\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\x12\x18\n" + - "\akeyword\x18\b \x01(\tR\akeyword\x12\x1e\n" + - "\vstart_at_ms\x18\t \x01(\x03R\tstartAtMs\x12\x1a\n" + - "\tend_at_ms\x18\n" + - " \x01(\x03R\aendAtMs\x12\x12\n" + - "\x04page\x18\v \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\f \x01(\x05R\bpageSize\"f\n" + - "\x19ListRechargeBillsResponse\x123\n" + - "\x05bills\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.RechargeBillR\x05bills\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"y\n" + - "\x12WalletFeatureFlags\x12)\n" + - "\x10recharge_enabled\x18\x01 \x01(\bR\x0frechargeEnabled\x128\n" + - "\x18diamond_exchange_enabled\x18\x02 \x01(\bR\x16diamondExchangeEnabled\"m\n" + - "\x18GetWalletOverviewRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"\xa0\x01\n" + - "\x19GetWalletOverviewResponse\x129\n" + - "\bbalances\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\bbalances\x12H\n" + - "\rfeature_flags\x18\x02 \x01(\v2#.hyapp.wallet.v1.WalletFeatureFlagsR\ffeatureFlags\"Y\n" + - "\x12WalletValueSummary\x12\x1f\n" + - "\vcoin_amount\x18\x01 \x01(\x03R\n" + - "coinAmount\x12\"\n" + - "\rupdated_at_ms\x18\x02 \x01(\x03R\vupdatedAtMs\"q\n" + - "\x1cGetWalletValueSummaryRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"^\n" + - "\x1dGetWalletValueSummaryResponse\x12=\n" + - "\asummary\x18\x01 \x01(\v2#.hyapp.wallet.v1.WalletValueSummaryR\asummary\"\xec\x05\n" + - "\fGiftWallItem\x12\x17\n" + - "\agift_id\x18\x01 \x01(\tR\x06giftId\x12\x1b\n" + - "\tgift_name\x18\x02 \x01(\tR\bgiftName\x12\x1f\n" + - "\vresource_id\x18\x03 \x01(\x03R\n" + - "resourceId\x125\n" + - "\bresource\x18\x04 \x01(\v2\x19.hyapp.wallet.v1.ResourceR\bresource\x124\n" + - "\x16resource_snapshot_json\x18\x05 \x01(\tR\x14resourceSnapshotJson\x12$\n" + - "\x0egift_type_code\x18\x06 \x01(\tR\fgiftTypeCode\x12+\n" + - "\x11presentation_json\x18\a \x01(\tR\x10presentationJson\x12\x1d\n" + - "\n" + - "gift_count\x18\b \x01(\x03R\tgiftCount\x12\x1f\n" + - "\vtotal_value\x18\t \x01(\x03R\n" + - "totalValue\x12(\n" + - "\x10total_coin_value\x18\n" + - " \x01(\x03R\x0etotalCoinValue\x12.\n" + - "\x13total_diamond_value\x18\v \x01(\x03R\x11totalDiamondValue\x12(\n" + - "\x10total_gift_point\x18\f \x01(\x03R\x0etotalGiftPoint\x12(\n" + - "\x10total_heat_value\x18\r \x01(\x03R\x0etotalHeatValue\x12*\n" + - "\x11charge_asset_type\x18\x0e \x01(\tR\x0fchargeAssetType\x12,\n" + - "\x12last_price_version\x18\x0f \x01(\tR\x10lastPriceVersion\x12/\n" + - "\x14first_received_at_ms\x18\x10 \x01(\x03R\x11firstReceivedAtMs\x12-\n" + - "\x13last_received_at_ms\x18\x11 \x01(\x03R\x10lastReceivedAtMs\x12\x1d\n" + - "\n" + - "sort_order\x18\x12 \x01(\x05R\tsortOrder\"k\n" + - "\x16GetUserGiftWallRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"\xef\x02\n" + - "\x17GetUserGiftWallResponse\x123\n" + - "\x05items\x18\x01 \x03(\v2\x1d.hyapp.wallet.v1.GiftWallItemR\x05items\x12&\n" + - "\x0fgift_kind_count\x18\x02 \x01(\x03R\rgiftKindCount\x12(\n" + - "\x10gift_total_count\x18\x03 \x01(\x03R\x0egiftTotalCount\x12\x1f\n" + - "\vtotal_value\x18\x04 \x01(\x03R\n" + - "totalValue\x12(\n" + - "\x10total_coin_value\x18\x05 \x01(\x03R\x0etotalCoinValue\x12.\n" + - "\x13total_diamond_value\x18\x06 \x01(\x03R\x11totalDiamondValue\x12(\n" + - "\x10total_gift_point\x18\a \x01(\x03R\x0etotalGiftPoint\x12(\n" + - "\x10total_heat_value\x18\b \x01(\x03R\x0etotalHeatValue\"\xde\x05\n" + - "\x0fRechargeProduct\x12\x1d\n" + - "\n" + - "product_id\x18\x01 \x01(\x03R\tproductId\x12!\n" + - "\fproduct_code\x18\x02 \x01(\tR\vproductCode\x12\x18\n" + - "\achannel\x18\x03 \x01(\tR\achannel\x12#\n" + - "\rcurrency_code\x18\x04 \x01(\tR\fcurrencyCode\x12\x1f\n" + - "\vcoin_amount\x18\x05 \x01(\x03R\n" + - "coinAmount\x12!\n" + - "\famount_minor\x18\x06 \x01(\x03R\vamountMinor\x12%\n" + - "\x0epolicy_version\x18\a \x01(\tR\rpolicyVersion\x12\x18\n" + - "\aenabled\x18\b \x01(\bR\aenabled\x12\x1d\n" + - "\n" + - "sort_order\x18\t \x01(\x05R\tsortOrder\x12!\n" + - "\fproduct_name\x18\n" + - " \x01(\tR\vproductName\x12 \n" + - "\vdescription\x18\v \x01(\tR\vdescription\x12\x1a\n" + - "\bplatform\x18\f \x01(\tR\bplatform\x12\x1d\n" + - "\n" + - "region_ids\x18\r \x03(\x03R\tregionIds\x12.\n" + - "\x13resource_asset_type\x18\x0e \x01(\tR\x11resourceAssetType\x12!\n" + - "\famount_micro\x18\x0f \x01(\x03R\vamountMicro\x12+\n" + - "\x12created_by_user_id\x18\x10 \x01(\x03R\x0fcreatedByUserId\x12+\n" + - "\x12updated_by_user_id\x18\x11 \x01(\x03R\x0fupdatedByUserId\x12\"\n" + - "\rcreated_at_ms\x18\x12 \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x13 \x01(\x03R\vupdatedAtMs\x12\x19\n" + - "\bapp_code\x18\x14 \x01(\tR\aappCode\x12\x16\n" + - "\x06status\x18\x15 \x01(\tR\x06status\"\xa9\x01\n" + - "\x1bListRechargeProductsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x1b\n" + - "\tregion_id\x18\x04 \x01(\x03R\bregionId\x12\x1a\n" + - "\bplatform\x18\x05 \x01(\tR\bplatform\"x\n" + - "\x1cListRechargeProductsResponse\x12<\n" + - "\bproducts\x18\x01 \x03(\v2 .hyapp.wallet.v1.RechargeProductR\bproducts\x12\x1a\n" + - "\bchannels\x18\x02 \x03(\tR\bchannels\"\xfd\x02\n" + - "\x1bConfirmGooglePaymentRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12\x17\n" + - "\auser_id\x18\x04 \x01(\x03R\x06userId\x12\x1b\n" + - "\tregion_id\x18\x05 \x01(\x03R\bregionId\x12\x1d\n" + - "\n" + - "product_id\x18\x06 \x01(\x03R\tproductId\x12!\n" + - "\fproduct_code\x18\a \x01(\tR\vproductCode\x12!\n" + - "\fpackage_name\x18\b \x01(\tR\vpackageName\x12%\n" + - "\x0epurchase_token\x18\t \x01(\tR\rpurchaseToken\x12\x19\n" + - "\border_id\x18\n" + - " \x01(\tR\aorderId\x12(\n" + - "\x10purchase_time_ms\x18\v \x01(\x03R\x0epurchaseTimeMs\"\xf5\x02\n" + - "\x1cConfirmGooglePaymentResponse\x12(\n" + - "\x10payment_order_id\x18\x01 \x01(\tR\x0epaymentOrderId\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "product_id\x18\x04 \x01(\x03R\tproductId\x12!\n" + - "\fproduct_code\x18\x05 \x01(\tR\vproductCode\x12\x1f\n" + - "\vcoin_amount\x18\x06 \x01(\x03R\n" + - "coinAmount\x127\n" + - "\abalance\x18\a \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12+\n" + - "\x11idempotent_replay\x18\b \x01(\bR\x10idempotentReplay\x12#\n" + - "\rconsume_state\x18\t \x01(\tR\fconsumeState\"\xf8\x01\n" + - " ListAdminRechargeProductsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x1a\n" + - "\bplatform\x18\x04 \x01(\tR\bplatform\x12\x1b\n" + - "\tregion_id\x18\x05 \x01(\x03R\bregionId\x12\x18\n" + - "\akeyword\x18\x06 \x01(\tR\akeyword\x12\x12\n" + - "\x04page\x18\a \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\b \x01(\x05R\bpageSize\"w\n" + - "!ListAdminRechargeProductsResponse\x12<\n" + - "\bproducts\x18\x01 \x03(\v2 .hyapp.wallet.v1.RechargeProductR\bproducts\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\xe0\x02\n" + - "\x1cCreateRechargeProductRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12!\n" + - "\famount_micro\x18\x03 \x01(\x03R\vamountMicro\x12\x1f\n" + - "\vcoin_amount\x18\x04 \x01(\x03R\n" + - "coinAmount\x12!\n" + - "\fproduct_name\x18\x05 \x01(\tR\vproductName\x12 \n" + - "\vdescription\x18\x06 \x01(\tR\vdescription\x12\x1a\n" + - "\bplatform\x18\a \x01(\tR\bplatform\x12\x1d\n" + - "\n" + - "region_ids\x18\b \x03(\x03R\tregionIds\x12\x18\n" + - "\aenabled\x18\t \x01(\bR\aenabled\x12(\n" + - "\x10operator_user_id\x18\n" + - " \x01(\x03R\x0eoperatorUserId\"\xff\x02\n" + - "\x1cUpdateRechargeProductRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "product_id\x18\x03 \x01(\x03R\tproductId\x12!\n" + - "\famount_micro\x18\x04 \x01(\x03R\vamountMicro\x12\x1f\n" + - "\vcoin_amount\x18\x05 \x01(\x03R\n" + - "coinAmount\x12!\n" + - "\fproduct_name\x18\x06 \x01(\tR\vproductName\x12 \n" + - "\vdescription\x18\a \x01(\tR\vdescription\x12\x1a\n" + - "\bplatform\x18\b \x01(\tR\bplatform\x12\x1d\n" + - "\n" + - "region_ids\x18\t \x03(\x03R\tregionIds\x12\x18\n" + - "\aenabled\x18\n" + - " \x01(\bR\aenabled\x12(\n" + - "\x10operator_user_id\x18\v \x01(\x03R\x0eoperatorUserId\"\xa1\x01\n" + - "\x1cDeleteRechargeProductRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "product_id\x18\x03 \x01(\x03R\tproductId\x12(\n" + - "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"U\n" + - "\x17RechargeProductResponse\x12:\n" + - "\aproduct\x18\x01 \x01(\v2 .hyapp.wallet.v1.RechargeProductR\aproduct\"9\n" + - "\x1dDeleteRechargeProductResponse\x12\x18\n" + - "\adeleted\x18\x01 \x01(\bR\adeleted\"\xde\x01\n" + - "\x13DiamondExchangeRule\x12#\n" + - "\rexchange_type\x18\x01 \x01(\tR\fexchangeType\x12&\n" + - "\x0ffrom_asset_type\x18\x02 \x01(\tR\rfromAssetType\x12\"\n" + - "\rto_asset_type\x18\x03 \x01(\tR\vtoAssetType\x12\x1f\n" + - "\vfrom_amount\x18\x04 \x01(\x03R\n" + - "fromAmount\x12\x1b\n" + - "\tto_amount\x18\x05 \x01(\x03R\btoAmount\x12\x18\n" + - "\aenabled\x18\x06 \x01(\bR\aenabled\"t\n" + - "\x1fGetDiamondExchangeConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"^\n" + - " GetDiamondExchangeConfigResponse\x12:\n" + - "\x05rules\x18\x01 \x03(\v2$.hyapp.wallet.v1.DiamondExchangeRuleR\x05rules\"\x96\x03\n" + - "\x11WalletTransaction\x12\x19\n" + - "\bentry_id\x18\x01 \x01(\x03R\aentryId\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12\x19\n" + - "\bbiz_type\x18\x03 \x01(\tR\abizType\x12\x1d\n" + - "\n" + - "asset_type\x18\x04 \x01(\tR\tassetType\x12'\n" + - "\x0favailable_delta\x18\x05 \x01(\x03R\x0eavailableDelta\x12!\n" + - "\ffrozen_delta\x18\x06 \x01(\x03R\vfrozenDelta\x12'\n" + - "\x0favailable_after\x18\a \x01(\x03R\x0eavailableAfter\x12!\n" + - "\ffrozen_after\x18\b \x01(\x03R\vfrozenAfter\x120\n" + - "\x14counterparty_user_id\x18\t \x01(\x03R\x12counterpartyUserId\x12\x17\n" + - "\aroom_id\x18\n" + - " \x01(\tR\x06roomId\x12\"\n" + - "\rcreated_at_ms\x18\v \x01(\x03R\vcreatedAtMs\"\xc2\x01\n" + - "\x1dListWalletTransactionsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x1d\n" + - "\n" + - "asset_type\x18\x04 \x01(\tR\tassetType\x12\x12\n" + - "\x04page\x18\x05 \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\x06 \x01(\x05R\bpageSize\"~\n" + - "\x1eListWalletTransactionsResponse\x12F\n" + - "\ftransactions\x18\x01 \x03(\v2\".hyapp.wallet.v1.WalletTransactionR\ftransactions\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\"\xb1\x02\n" + - "\rVipRewardItem\x12\x1f\n" + - "\vresource_id\x18\x01 \x01(\x03R\n" + - "resourceId\x12#\n" + - "\rresource_code\x18\x02 \x01(\tR\fresourceCode\x12#\n" + - "\rresource_type\x18\x03 \x01(\tR\fresourceType\x12\x12\n" + - "\x04name\x18\x04 \x01(\tR\x04name\x12\x1a\n" + - "\bquantity\x18\x05 \x01(\x03R\bquantity\x12\"\n" + - "\rexpires_at_ms\x18\x06 \x01(\x03R\vexpiresAtMs\x12\x1b\n" + - "\tasset_url\x18\a \x01(\tR\bassetUrl\x12\x1f\n" + - "\vpreview_url\x18\b \x01(\tR\n" + - "previewUrl\x12#\n" + - "\ranimation_url\x18\t \x01(\tR\fanimationUrl\"\xfc\x04\n" + - "\bVipLevel\x12\x14\n" + - "\x05level\x18\x01 \x01(\x05R\x05level\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "price_coin\x18\x04 \x01(\x03R\tpriceCoin\x12\x1f\n" + - "\vduration_ms\x18\x05 \x01(\x03R\n" + - "durationMs\x127\n" + - "\x18reward_resource_group_id\x18\x06 \x01(\x03R\x15rewardResourceGroupId\x12A\n" + - "\freward_items\x18\a \x03(\v2\x1e.hyapp.wallet.v1.VipRewardItemR\vrewardItems\x12!\n" + - "\fcan_purchase\x18\b \x01(\bR\vcanPurchase\x12\x1d\n" + - "\n" + - "sort_order\x18\t \x01(\x05R\tsortOrder\x124\n" + - "\x16recharge_gate_required\x18\n" + - " \x01(\bR\x14rechargeGateRequired\x12A\n" + - "\x1drequired_recharge_coin_amount\x18\v \x01(\x03R\x1arequiredRechargeCoinAmount\x129\n" + - "\x19user_recharge_coin_amount\x18\f \x01(\x03R\x16userRechargeCoinAmount\x124\n" + - "\x16purchase_locked_reason\x18\r \x01(\tR\x14purchaseLockedReason\x12\"\n" + - "\rcreated_at_ms\x18\x0e \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x0f \x01(\x03R\vupdatedAtMs\"\xd0\x01\n" + - "\aUserVip\x12\x17\n" + - "\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x14\n" + - "\x05level\x18\x02 \x01(\x05R\x05level\x12\x12\n" + - "\x04name\x18\x03 \x01(\tR\x04name\x12\x16\n" + - "\x06active\x18\x04 \x01(\bR\x06active\x12\"\n" + - "\rstarted_at_ms\x18\x05 \x01(\x03R\vstartedAtMs\x12\"\n" + - "\rexpires_at_ms\x18\x06 \x01(\x03R\vexpiresAtMs\x12\"\n" + - "\rupdated_at_ms\x18\a \x01(\x03R\vupdatedAtMs\"k\n" + - "\x16ListVipPackagesRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\"\x8b\x01\n" + - "\x17ListVipPackagesResponse\x129\n" + - "\vcurrent_vip\x18\x01 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\n" + - "currentVip\x125\n" + - "\bpackages\x18\x02 \x03(\v2\x19.hyapp.wallet.v1.VipLevelR\bpackages\"d\n" + - "\x0fGetMyVipRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\">\n" + - "\x10GetMyVipResponse\x12*\n" + - "\x03vip\x18\x01 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\x03vip\"}\n" + - "\x12PurchaseVipRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\auser_id\x18\x03 \x01(\x03R\x06userId\x12\x14\n" + - "\x05level\x18\x04 \x01(\x05R\x05level\"\x93\x02\n" + - "\x13PurchaseVipResponse\x12\x19\n" + - "\border_id\x18\x01 \x01(\tR\aorderId\x12%\n" + - "\x0etransaction_id\x18\x02 \x01(\tR\rtransactionId\x12*\n" + - "\x03vip\x18\x03 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\x03vip\x12\x1d\n" + - "\n" + - "coin_spent\x18\x04 \x01(\x03R\tcoinSpent\x12,\n" + - "\x12coin_balance_after\x18\x05 \x01(\x03R\x10coinBalanceAfter\x12A\n" + - "\freward_items\x18\x06 \x03(\v2\x1e.hyapp.wallet.v1.VipRewardItemR\vrewardItems\"\xec\x01\n" + - "\x0fGrantVipRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x14\n" + - "\x05level\x18\x04 \x01(\x05R\x05level\x12!\n" + - "\fgrant_source\x18\x05 \x01(\tR\vgrantSource\x12(\n" + - "\x10operator_user_id\x18\x06 \x01(\x03R\x0eoperatorUserId\x12\x16\n" + - "\x06reason\x18\a \x01(\tR\x06reason\"\xce\x01\n" + - "\x10GrantVipResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x12*\n" + - "\x03vip\x18\x02 \x01(\v2\x18.hyapp.wallet.v1.UserVipR\x03vip\x12A\n" + - "\freward_items\x18\x03 \x03(\v2\x1e.hyapp.wallet.v1.VipRewardItemR\vrewardItems\x12$\n" + - "\x0eserver_time_ms\x18\x04 \x01(\x03R\fserverTimeMs\"\xb1\x02\n" + - "\x12AdminVipLevelInput\x12\x14\n" + - "\x05level\x18\x01 \x01(\x05R\x05level\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x16\n" + - "\x06status\x18\x03 \x01(\tR\x06status\x12\x1d\n" + - "\n" + - "price_coin\x18\x04 \x01(\x03R\tpriceCoin\x12\x1f\n" + - "\vduration_ms\x18\x05 \x01(\x03R\n" + - "durationMs\x127\n" + - "\x18reward_resource_group_id\x18\x06 \x01(\x03R\x15rewardResourceGroupId\x12\x1d\n" + - "\n" + - "sort_order\x18\a \x01(\x05R\tsortOrder\x12A\n" + - "\x1drequired_recharge_coin_amount\x18\b \x01(\x03R\x1arequiredRechargeCoinAmount\"U\n" + - "\x19ListAdminVipLevelsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\"u\n" + - "\x1aListAdminVipLevelsResponse\x121\n" + - "\x06levels\x18\x01 \x03(\v2\x19.hyapp.wallet.v1.VipLevelR\x06levels\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xbe\x01\n" + - "\x1bUpdateAdminVipLevelsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12;\n" + - "\x06levels\x18\x03 \x03(\v2#.hyapp.wallet.v1.AdminVipLevelInputR\x06levels\x12(\n" + - "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"w\n" + - "\x1cUpdateAdminVipLevelsResponse\x121\n" + - "\x06levels\x18\x01 \x03(\v2\x19.hyapp.wallet.v1.VipLevelR\x06levels\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xfc\x01\n" + - "\x17CreditTaskRewardRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12\x1b\n" + - "\ttask_type\x18\x05 \x01(\tR\btaskType\x12\x17\n" + - "\atask_id\x18\x06 \x01(\tR\x06taskId\x12\x1b\n" + - "\tcycle_key\x18\a \x01(\tR\bcycleKey\x12\x16\n" + - "\x06reason\x18\b \x01(\tR\x06reason\"\xb6\x01\n" + - "\x18CreditTaskRewardResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + - "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x16\n" + - "\x06amount\x18\x03 \x01(\x03R\x06amount\x12\"\n" + - "\rgranted_at_ms\x18\x04 \x01(\x03R\vgrantedAtMs\"\xbe\x02\n" + - "\x1cCreditLuckyGiftRewardRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12\x17\n" + - "\adraw_id\x18\x05 \x01(\tR\x06drawId\x12\x17\n" + - "\aroom_id\x18\x06 \x01(\tR\x06roomId\x12\x17\n" + - "\agift_id\x18\a \x01(\tR\x06giftId\x12\x17\n" + - "\apool_id\x18\b \x01(\tR\x06poolId\x12\x16\n" + - "\x06reason\x18\t \x01(\tR\x06reason\x12*\n" + - "\x11visible_region_id\x18\n" + - " \x01(\x03R\x0fvisibleRegionId\"\xbb\x01\n" + - "\x1dCreditLuckyGiftRewardResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + - "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x16\n" + - "\x06amount\x18\x03 \x01(\x03R\x06amount\x12\"\n" + - "\rgranted_at_ms\x18\x04 \x01(\x03R\vgrantedAtMs\"\x90\x03\n" + - "\x1fCreditRoomTurnoverRewardRequest\x12\x1d\n" + - "\n" + - "command_id\x18\x01 \x01(\tR\tcommandId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12$\n" + - "\x0etarget_user_id\x18\x03 \x01(\x03R\ftargetUserId\x12\x16\n" + - "\x06amount\x18\x04 \x01(\x03R\x06amount\x12#\n" + - "\rsettlement_id\x18\x05 \x01(\tR\fsettlementId\x12\x17\n" + - "\aroom_id\x18\x06 \x01(\tR\x06roomId\x12&\n" + - "\x0fperiod_start_ms\x18\a \x01(\x03R\rperiodStartMs\x12\"\n" + - "\rperiod_end_ms\x18\b \x01(\x03R\vperiodEndMs\x12\x1d\n" + - "\n" + - "coin_spent\x18\t \x01(\x03R\tcoinSpent\x12\x17\n" + - "\atier_id\x18\n" + - " \x01(\x03R\x06tierId\x12\x1b\n" + - "\ttier_code\x18\v \x01(\tR\btierCode\x12\x16\n" + - "\x06reason\x18\f \x01(\tR\x06reason\"\xbe\x01\n" + - " CreditRoomTurnoverRewardResponse\x12%\n" + - "\x0etransaction_id\x18\x01 \x01(\tR\rtransactionId\x127\n" + - "\abalance\x18\x02 \x01(\v2\x1d.hyapp.wallet.v1.AssetBalanceR\abalance\x12\x16\n" + - "\x06amount\x18\x03 \x01(\x03R\x06amount\x12\"\n" + - "\rgranted_at_ms\x18\x04 \x01(\x03R\vgrantedAtMs\"\x9a\x03\n" + - "\x1aApplyGameCoinChangeRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12\x17\n" + - "\auser_id\x18\x04 \x01(\x03R\x06userId\x12#\n" + - "\rplatform_code\x18\x05 \x01(\tR\fplatformCode\x12\x17\n" + - "\agame_id\x18\x06 \x01(\tR\x06gameId\x12*\n" + - "\x11provider_order_id\x18\a \x01(\tR\x0fproviderOrderId\x12*\n" + - "\x11provider_round_id\x18\b \x01(\tR\x0fproviderRoundId\x12\x17\n" + - "\aop_type\x18\t \x01(\tR\x06opType\x12\x1f\n" + - "\vcoin_amount\x18\n" + - " \x01(\x03R\n" + - "coinAmount\x12\x17\n" + - "\aroom_id\x18\v \x01(\tR\x06roomId\x12!\n" + - "\frequest_hash\x18\f \x01(\tR\vrequestHash\"\xa3\x01\n" + - "\x1bApplyGameCoinChangeResponse\x122\n" + - "\x15wallet_transaction_id\x18\x01 \x01(\tR\x13walletTransactionId\x12#\n" + - "\rbalance_after\x18\x02 \x01(\x03R\fbalanceAfter\x12+\n" + - "\x11idempotent_replay\x18\x03 \x01(\bR\x10idempotentReplay\"\x9f\x03\n" + - "\x0fRedPacketConfig\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x18\n" + - "\aenabled\x18\x02 \x01(\bR\aenabled\x12\x1f\n" + - "\vcount_tiers\x18\x03 \x03(\x05R\n" + - "countTiers\x12!\n" + - "\famount_tiers\x18\x04 \x03(\x03R\vamountTiers\x120\n" + - "\x14delayed_open_seconds\x18\x05 \x01(\x05R\x12delayedOpenSeconds\x12%\n" + - "\x0eexpire_seconds\x18\x06 \x01(\x05R\rexpireSeconds\x12(\n" + - "\x10daily_send_limit\x18\a \x01(\x05R\x0edailySendLimit\x12-\n" + - "\x13updated_by_admin_id\x18\b \x01(\x03R\x10updatedByAdminId\x12\"\n" + - "\rcreated_at_ms\x18\t \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\n" + - " \x01(\x03R\vupdatedAtMs\x12\x19\n" + - "\brule_url\x18\v \x01(\tR\aruleUrl\"\xee\x02\n" + - "\x0eRedPacketClaim\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x19\n" + - "\bclaim_id\x18\x02 \x01(\tR\aclaimId\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12\x1b\n" + - "\tpacket_id\x18\x04 \x01(\tR\bpacketId\x12\x17\n" + - "\auser_id\x18\x05 \x01(\x03R\x06userId\x12\x16\n" + - "\x06amount\x18\x06 \x01(\x03R\x06amount\x122\n" + - "\x15wallet_transaction_id\x18\a \x01(\tR\x13walletTransactionId\x12\x16\n" + - "\x06status\x18\b \x01(\tR\x06status\x12%\n" + - "\x0efailure_reason\x18\t \x01(\tR\rfailureReason\x12\"\n" + - "\rcreated_at_ms\x18\n" + - " \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\v \x01(\x03R\vupdatedAtMs\"\xa0\x06\n" + - "\tRedPacket\x12\x19\n" + - "\bapp_code\x18\x01 \x01(\tR\aappCode\x12\x1b\n" + - "\tpacket_id\x18\x02 \x01(\tR\bpacketId\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12$\n" + - "\x0esender_user_id\x18\x04 \x01(\x03R\fsenderUserId\x12\x17\n" + - "\aroom_id\x18\x05 \x01(\tR\x06roomId\x12\x1b\n" + - "\tregion_id\x18\x06 \x01(\x03R\bregionId\x12\x1f\n" + - "\vpacket_type\x18\a \x01(\tR\n" + - "packetType\x12!\n" + - "\ftotal_amount\x18\b \x01(\x03R\vtotalAmount\x12!\n" + - "\fpacket_count\x18\t \x01(\x05R\vpacketCount\x12)\n" + - "\x10remaining_amount\x18\n" + - " \x01(\x03R\x0fremainingAmount\x12'\n" + - "\x0fremaining_count\x18\v \x01(\x05R\x0eremainingCount\x12\x16\n" + - "\x06status\x18\f \x01(\tR\x06status\x12\x1c\n" + - "\n" + - "open_at_ms\x18\r \x01(\x03R\bopenAtMs\x12\"\n" + - "\rexpires_at_ms\x18\x0e \x01(\x03R\vexpiresAtMs\x12\"\n" + - "\rcreated_at_ms\x18\x0f \x01(\x03R\vcreatedAtMs\x12\"\n" + - "\rupdated_at_ms\x18\x10 \x01(\x03R\vupdatedAtMs\x12*\n" + - "\x11claimed_by_viewer\x18\x11 \x01(\bR\x0fclaimedByViewer\x12.\n" + - "\x13viewer_claim_amount\x18\x12 \x01(\x03R\x11viewerClaimAmount\x127\n" + - "\x06claims\x18\x13 \x03(\v2\x1f.hyapp.wallet.v1.RedPacketClaimR\x06claims\x12#\n" + - "\rrefund_amount\x18\x14 \x01(\x03R\frefundAmount\x12#\n" + - "\rrefund_status\x18\x15 \x01(\tR\frefundStatus\x12$\n" + - "\x0erefunded_at_ms\x18\x16 \x01(\x03R\frefundedAtMs\"U\n" + - "\x19GetRedPacketConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\"|\n" + - "\x1aGetRedPacketConfigResponse\x128\n" + - "\x06config\x18\x01 \x01(\v2 .hyapp.wallet.v1.RedPacketConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xfe\x02\n" + - "\x1cUpdateRedPacketConfigRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x18\n" + - "\aenabled\x18\x03 \x01(\bR\aenabled\x12\x1f\n" + - "\vcount_tiers\x18\x04 \x03(\x05R\n" + - "countTiers\x12!\n" + - "\famount_tiers\x18\x05 \x03(\x03R\vamountTiers\x120\n" + - "\x14delayed_open_seconds\x18\x06 \x01(\x05R\x12delayedOpenSeconds\x12%\n" + - "\x0eexpire_seconds\x18\a \x01(\x05R\rexpireSeconds\x12(\n" + - "\x10daily_send_limit\x18\b \x01(\x05R\x0edailySendLimit\x12(\n" + - "\x10operator_user_id\x18\t \x01(\x03R\x0eoperatorUserId\x12\x19\n" + - "\brule_url\x18\n" + - " \x01(\tR\aruleUrl\"\x7f\n" + - "\x1dUpdateRedPacketConfigResponse\x128\n" + - "\x06config\x18\x01 \x01(\v2 .hyapp.wallet.v1.RedPacketConfigR\x06config\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"\xb4\x02\n" + - "\x16CreateRedPacketRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12$\n" + - "\x0esender_user_id\x18\x04 \x01(\x03R\fsenderUserId\x12\x17\n" + - "\aroom_id\x18\x05 \x01(\tR\x06roomId\x12\x1b\n" + - "\tregion_id\x18\x06 \x01(\x03R\bregionId\x12\x1f\n" + - "\vpacket_type\x18\a \x01(\tR\n" + - "packetType\x12!\n" + - "\ftotal_amount\x18\b \x01(\x03R\vtotalAmount\x12!\n" + - "\fpacket_count\x18\t \x01(\x05R\vpacketCount\"\x98\x01\n" + - "\x17CreateRedPacketResponse\x122\n" + - "\x06packet\x18\x01 \x01(\v2\x1a.hyapp.wallet.v1.RedPacketR\x06packet\x12#\n" + - "\rbalance_after\x18\x02 \x01(\x03R\fbalanceAfter\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xa6\x01\n" + - "\x15ClaimRedPacketRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "command_id\x18\x03 \x01(\tR\tcommandId\x12\x1b\n" + - "\tpacket_id\x18\x04 \x01(\tR\bpacketId\x12\x17\n" + - "\auser_id\x18\x05 \x01(\x03R\x06userId\"\xce\x01\n" + - "\x16ClaimRedPacketResponse\x125\n" + - "\x05claim\x18\x01 \x01(\v2\x1f.hyapp.wallet.v1.RedPacketClaimR\x05claim\x12#\n" + - "\rbalance_after\x18\x02 \x01(\x03R\fbalanceAfter\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\x122\n" + - "\x06packet\x18\x04 \x01(\v2\x1a.hyapp.wallet.v1.RedPacketR\x06packet\"\xf9\x02\n" + - "\x15ListRedPacketsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x17\n" + - "\aroom_id\x18\x03 \x01(\tR\x06roomId\x12$\n" + - "\x0esender_user_id\x18\x04 \x01(\x03R\fsenderUserId\x12\x1b\n" + - "\tregion_id\x18\x05 \x01(\x03R\bregionId\x12\x1f\n" + - "\vpacket_type\x18\x06 \x01(\tR\n" + - "packetType\x12\x16\n" + - "\x06status\x18\a \x01(\tR\x06status\x12$\n" + - "\x0eviewer_user_id\x18\b \x01(\x03R\fviewerUserId\x12\x1e\n" + - "\vstart_at_ms\x18\t \x01(\x03R\tstartAtMs\x12\x1a\n" + - "\tend_at_ms\x18\n" + - " \x01(\x03R\aendAtMs\x12\x12\n" + - "\x04page\x18\v \x01(\x05R\x04page\x12\x1b\n" + - "\tpage_size\x18\f \x01(\x05R\bpageSize\"\x8a\x01\n" + - "\x16ListRedPacketsResponse\x124\n" + - "\apackets\x18\x01 \x03(\v2\x1a.hyapp.wallet.v1.RedPacketR\apackets\x12\x14\n" + - "\x05total\x18\x02 \x01(\x03R\x05total\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xb9\x01\n" + - "\x13GetRedPacketRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + - "\tpacket_id\x18\x03 \x01(\tR\bpacketId\x12$\n" + - "\x0eviewer_user_id\x18\x04 \x01(\x03R\fviewerUserId\x12%\n" + - "\x0einclude_claims\x18\x05 \x01(\bR\rincludeClaims\"p\n" + - "\x14GetRedPacketResponse\x122\n" + - "\x06packet\x18\x01 \x01(\v2\x1a.hyapp.wallet.v1.RedPacketR\x06packet\x12$\n" + - "\x0eserver_time_ms\x18\x02 \x01(\x03R\fserverTimeMs\"r\n" + - "\x17ExpireRedPacketsRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1d\n" + - "\n" + - "batch_size\x18\x03 \x01(\x05R\tbatchSize\"\x8e\x01\n" + - "\x18ExpireRedPacketsResponse\x12#\n" + - "\rexpired_count\x18\x01 \x01(\x05R\fexpiredCount\x12'\n" + - "\x0frefunded_amount\x18\x02 \x01(\x03R\x0erefundedAmount\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\x9e\x01\n" + - "\x1bRetryRedPacketRefundRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x1b\n" + - "\tpacket_id\x18\x03 \x01(\tR\bpacketId\x12(\n" + - "\x10operator_user_id\x18\x04 \x01(\x03R\x0eoperatorUserId\"\xa1\x01\n" + - "\x1cRetryRedPacketRefundResponse\x122\n" + - "\x06packet\x18\x01 \x01(\v2\x1a.hyapp.wallet.v1.RedPacketR\x06packet\x12'\n" + - "\x0frefunded_amount\x18\x02 \x01(\x03R\x0erefundedAmount\x12$\n" + - "\x0eserver_time_ms\x18\x03 \x01(\x03R\fserverTimeMs\"\xbf\x01\n" + - "\x10CronBatchRequest\x12\x1d\n" + - "\n" + - "request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" + - "\bapp_code\x18\x02 \x01(\tR\aappCode\x12\x15\n" + - "\x06run_id\x18\x03 \x01(\tR\x05runId\x12\x1b\n" + - "\tworker_id\x18\x04 \x01(\tR\bworkerId\x12\x1d\n" + - "\n" + - "batch_size\x18\x05 \x01(\x05R\tbatchSize\x12\x1e\n" + - "\vlock_ttl_ms\x18\x06 \x01(\x03R\tlockTtlMs\"\xc6\x01\n" + - "\x11CronBatchResponse\x12#\n" + - "\rclaimed_count\x18\x01 \x01(\x05R\fclaimedCount\x12'\n" + - "\x0fprocessed_count\x18\x02 \x01(\x05R\x0eprocessedCount\x12#\n" + - "\rsuccess_count\x18\x03 \x01(\x05R\fsuccessCount\x12#\n" + - "\rfailure_count\x18\x04 \x01(\x05R\ffailureCount\x12\x19\n" + - "\bhas_more\x18\x05 \x01(\bR\ahasMore2\xe0\x02\n" + - "\x11WalletCronService\x12n\n" + - "%ProcessHostSalaryDailySettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12r\n" + - ")ProcessHostSalaryHalfMonthSettlementBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse\x12g\n" + - "\x1eProcessHostSalaryMonthEndBatch\x12!.hyapp.wallet.v1.CronBatchRequest\x1a\".hyapp.wallet.v1.CronBatchResponse2\x89;\n" + - "\rWalletService\x12R\n" + - "\tDebitGift\x12!.hyapp.wallet.v1.DebitGiftRequest\x1a\".hyapp.wallet.v1.DebitGiftResponse\x12a\n" + - "\x0eBatchDebitGift\x12&.hyapp.wallet.v1.BatchDebitGiftRequest\x1a'.hyapp.wallet.v1.BatchDebitGiftResponse\x12X\n" + - "\vGetBalances\x12#.hyapp.wallet.v1.GetBalancesRequest\x1a$.hyapp.wallet.v1.GetBalancesResponse\x12\x82\x01\n" + - "\x19GetActiveHostSalaryPolicy\x121.hyapp.wallet.v1.GetActiveHostSalaryPolicyRequest\x1a2.hyapp.wallet.v1.GetActiveHostSalaryPolicyResponse\x12v\n" + - "\x15GetHostSalaryProgress\x12-.hyapp.wallet.v1.GetHostSalaryProgressRequest\x1a..hyapp.wallet.v1.GetHostSalaryProgressResponse\x12g\n" + - "\x10AdminCreditAsset\x12(.hyapp.wallet.v1.AdminCreditAssetRequest\x1a).hyapp.wallet.v1.AdminCreditAssetResponse\x12\x85\x01\n" + - "\x1aAdminCreditCoinSellerStock\x122.hyapp.wallet.v1.AdminCreditCoinSellerStockRequest\x1a3.hyapp.wallet.v1.AdminCreditCoinSellerStockResponse\x12y\n" + - "\x16TransferCoinFromSeller\x12..hyapp.wallet.v1.TransferCoinFromSellerRequest\x1a/.hyapp.wallet.v1.TransferCoinFromSellerResponse\x12\xa6\x01\n" + - "%ListCoinSellerSalaryExchangeRateTiers\x12=.hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersRequest\x1a>.hyapp.wallet.v1.ListCoinSellerSalaryExchangeRateTiersResponse\x12s\n" + - "\x14ExchangeSalaryToCoin\x12,.hyapp.wallet.v1.ExchangeSalaryToCoinRequest\x1a-.hyapp.wallet.v1.ExchangeSalaryToCoinResponse\x12\x85\x01\n" + - "\x1aTransferSalaryToCoinSeller\x122.hyapp.wallet.v1.TransferSalaryToCoinSellerRequest\x1a3.hyapp.wallet.v1.TransferSalaryToCoinSellerResponse\x12^\n" + - "\rListResources\x12%.hyapp.wallet.v1.ListResourcesRequest\x1a&.hyapp.wallet.v1.ListResourcesResponse\x12X\n" + - "\vGetResource\x12#.hyapp.wallet.v1.GetResourceRequest\x1a$.hyapp.wallet.v1.GetResourceResponse\x12[\n" + - "\x0eCreateResource\x12&.hyapp.wallet.v1.CreateResourceRequest\x1a!.hyapp.wallet.v1.ResourceResponse\x12[\n" + - "\x0eUpdateResource\x12&.hyapp.wallet.v1.UpdateResourceRequest\x1a!.hyapp.wallet.v1.ResourceResponse\x12a\n" + - "\x11SetResourceStatus\x12).hyapp.wallet.v1.SetResourceStatusRequest\x1a!.hyapp.wallet.v1.ResourceResponse\x12m\n" + - "\x12ListResourceGroups\x12*.hyapp.wallet.v1.ListResourceGroupsRequest\x1a+.hyapp.wallet.v1.ListResourceGroupsResponse\x12g\n" + - "\x10GetResourceGroup\x12(.hyapp.wallet.v1.GetResourceGroupRequest\x1a).hyapp.wallet.v1.GetResourceGroupResponse\x12j\n" + - "\x13CreateResourceGroup\x12+.hyapp.wallet.v1.CreateResourceGroupRequest\x1a&.hyapp.wallet.v1.ResourceGroupResponse\x12j\n" + - "\x13UpdateResourceGroup\x12+.hyapp.wallet.v1.UpdateResourceGroupRequest\x1a&.hyapp.wallet.v1.ResourceGroupResponse\x12p\n" + - "\x16SetResourceGroupStatus\x12..hyapp.wallet.v1.SetResourceGroupStatusRequest\x1a&.hyapp.wallet.v1.ResourceGroupResponse\x12d\n" + - "\x0fListGiftConfigs\x12'.hyapp.wallet.v1.ListGiftConfigsRequest\x1a(.hyapp.wallet.v1.ListGiftConfigsResponse\x12p\n" + - "\x13ListGiftTypeConfigs\x12+.hyapp.wallet.v1.ListGiftTypeConfigsRequest\x1a,.hyapp.wallet.v1.ListGiftTypeConfigsResponse\x12a\n" + - "\x10CreateGiftConfig\x12(.hyapp.wallet.v1.CreateGiftConfigRequest\x1a#.hyapp.wallet.v1.GiftConfigResponse\x12a\n" + - "\x10UpdateGiftConfig\x12(.hyapp.wallet.v1.UpdateGiftConfigRequest\x1a#.hyapp.wallet.v1.GiftConfigResponse\x12g\n" + - "\x13SetGiftConfigStatus\x12+.hyapp.wallet.v1.SetGiftConfigStatusRequest\x1a#.hyapp.wallet.v1.GiftConfigResponse\x12m\n" + - "\x14UpsertGiftTypeConfig\x12,.hyapp.wallet.v1.UpsertGiftTypeConfigRequest\x1a'.hyapp.wallet.v1.GiftTypeConfigResponse\x12^\n" + - "\rGrantResource\x12%.hyapp.wallet.v1.GrantResourceRequest\x1a&.hyapp.wallet.v1.ResourceGrantResponse\x12h\n" + - "\x12GrantResourceGroup\x12*.hyapp.wallet.v1.GrantResourceGroupRequest\x1a&.hyapp.wallet.v1.ResourceGrantResponse\x12j\n" + - "\x11ListUserResources\x12).hyapp.wallet.v1.ListUserResourcesRequest\x1a*.hyapp.wallet.v1.ListUserResourcesResponse\x12j\n" + - "\x11EquipUserResource\x12).hyapp.wallet.v1.EquipUserResourceRequest\x1a*.hyapp.wallet.v1.EquipUserResourceResponse\x12p\n" + - "\x13UnequipUserResource\x12+.hyapp.wallet.v1.UnequipUserResourceRequest\x1a,.hyapp.wallet.v1.UnequipUserResourceResponse\x12\x8e\x01\n" + - "\x1dBatchGetUserEquippedResources\x125.hyapp.wallet.v1.BatchGetUserEquippedResourcesRequest\x1a6.hyapp.wallet.v1.BatchGetUserEquippedResourcesResponse\x12m\n" + - "\x12ListResourceGrants\x12*.hyapp.wallet.v1.ListResourceGrantsRequest\x1a+.hyapp.wallet.v1.ListResourceGrantsResponse\x12v\n" + - "\x15ListResourceShopItems\x12-.hyapp.wallet.v1.ListResourceShopItemsRequest\x1a..hyapp.wallet.v1.ListResourceShopItemsResponse\x12|\n" + - "\x17UpsertResourceShopItems\x12/.hyapp.wallet.v1.UpsertResourceShopItemsRequest\x1a0.hyapp.wallet.v1.UpsertResourceShopItemsResponse\x12y\n" + - "\x19SetResourceShopItemStatus\x121.hyapp.wallet.v1.SetResourceShopItemStatusRequest\x1a).hyapp.wallet.v1.ResourceShopItemResponse\x12\x7f\n" + - "\x18PurchaseResourceShopItem\x120.hyapp.wallet.v1.PurchaseResourceShopItemRequest\x1a1.hyapp.wallet.v1.PurchaseResourceShopItemResponse\x12j\n" + - "\x11ListRechargeBills\x12).hyapp.wallet.v1.ListRechargeBillsRequest\x1a*.hyapp.wallet.v1.ListRechargeBillsResponse\x12j\n" + - "\x11GetWalletOverview\x12).hyapp.wallet.v1.GetWalletOverviewRequest\x1a*.hyapp.wallet.v1.GetWalletOverviewResponse\x12v\n" + - "\x15GetWalletValueSummary\x12-.hyapp.wallet.v1.GetWalletValueSummaryRequest\x1a..hyapp.wallet.v1.GetWalletValueSummaryResponse\x12d\n" + - "\x0fGetUserGiftWall\x12'.hyapp.wallet.v1.GetUserGiftWallRequest\x1a(.hyapp.wallet.v1.GetUserGiftWallResponse\x12s\n" + - "\x14ListRechargeProducts\x12,.hyapp.wallet.v1.ListRechargeProductsRequest\x1a-.hyapp.wallet.v1.ListRechargeProductsResponse\x12s\n" + - "\x14ConfirmGooglePayment\x12,.hyapp.wallet.v1.ConfirmGooglePaymentRequest\x1a-.hyapp.wallet.v1.ConfirmGooglePaymentResponse\x12\x82\x01\n" + - "\x19ListAdminRechargeProducts\x121.hyapp.wallet.v1.ListAdminRechargeProductsRequest\x1a2.hyapp.wallet.v1.ListAdminRechargeProductsResponse\x12p\n" + - "\x15CreateRechargeProduct\x12-.hyapp.wallet.v1.CreateRechargeProductRequest\x1a(.hyapp.wallet.v1.RechargeProductResponse\x12p\n" + - "\x15UpdateRechargeProduct\x12-.hyapp.wallet.v1.UpdateRechargeProductRequest\x1a(.hyapp.wallet.v1.RechargeProductResponse\x12v\n" + - "\x15DeleteRechargeProduct\x12-.hyapp.wallet.v1.DeleteRechargeProductRequest\x1a..hyapp.wallet.v1.DeleteRechargeProductResponse\x12\x7f\n" + - "\x18GetDiamondExchangeConfig\x120.hyapp.wallet.v1.GetDiamondExchangeConfigRequest\x1a1.hyapp.wallet.v1.GetDiamondExchangeConfigResponse\x12y\n" + - "\x16ListWalletTransactions\x12..hyapp.wallet.v1.ListWalletTransactionsRequest\x1a/.hyapp.wallet.v1.ListWalletTransactionsResponse\x12d\n" + - "\x0fListVipPackages\x12'.hyapp.wallet.v1.ListVipPackagesRequest\x1a(.hyapp.wallet.v1.ListVipPackagesResponse\x12O\n" + - "\bGetMyVip\x12 .hyapp.wallet.v1.GetMyVipRequest\x1a!.hyapp.wallet.v1.GetMyVipResponse\x12X\n" + - "\vPurchaseVip\x12#.hyapp.wallet.v1.PurchaseVipRequest\x1a$.hyapp.wallet.v1.PurchaseVipResponse\x12O\n" + - "\bGrantVip\x12 .hyapp.wallet.v1.GrantVipRequest\x1a!.hyapp.wallet.v1.GrantVipResponse\x12m\n" + - "\x12ListAdminVipLevels\x12*.hyapp.wallet.v1.ListAdminVipLevelsRequest\x1a+.hyapp.wallet.v1.ListAdminVipLevelsResponse\x12s\n" + - "\x14UpdateAdminVipLevels\x12,.hyapp.wallet.v1.UpdateAdminVipLevelsRequest\x1a-.hyapp.wallet.v1.UpdateAdminVipLevelsResponse\x12g\n" + - "\x10CreditTaskReward\x12(.hyapp.wallet.v1.CreditTaskRewardRequest\x1a).hyapp.wallet.v1.CreditTaskRewardResponse\x12v\n" + - "\x15CreditLuckyGiftReward\x12-.hyapp.wallet.v1.CreditLuckyGiftRewardRequest\x1a..hyapp.wallet.v1.CreditLuckyGiftRewardResponse\x12\x7f\n" + - "\x18CreditRoomTurnoverReward\x120.hyapp.wallet.v1.CreditRoomTurnoverRewardRequest\x1a1.hyapp.wallet.v1.CreditRoomTurnoverRewardResponse\x12p\n" + - "\x13ApplyGameCoinChange\x12+.hyapp.wallet.v1.ApplyGameCoinChangeRequest\x1a,.hyapp.wallet.v1.ApplyGameCoinChangeResponse\x12m\n" + - "\x12GetRedPacketConfig\x12*.hyapp.wallet.v1.GetRedPacketConfigRequest\x1a+.hyapp.wallet.v1.GetRedPacketConfigResponse\x12v\n" + - "\x15UpdateRedPacketConfig\x12-.hyapp.wallet.v1.UpdateRedPacketConfigRequest\x1a..hyapp.wallet.v1.UpdateRedPacketConfigResponse\x12d\n" + - "\x0fCreateRedPacket\x12'.hyapp.wallet.v1.CreateRedPacketRequest\x1a(.hyapp.wallet.v1.CreateRedPacketResponse\x12a\n" + - "\x0eClaimRedPacket\x12&.hyapp.wallet.v1.ClaimRedPacketRequest\x1a'.hyapp.wallet.v1.ClaimRedPacketResponse\x12a\n" + - "\x0eListRedPackets\x12&.hyapp.wallet.v1.ListRedPacketsRequest\x1a'.hyapp.wallet.v1.ListRedPacketsResponse\x12[\n" + - "\fGetRedPacket\x12$.hyapp.wallet.v1.GetRedPacketRequest\x1a%.hyapp.wallet.v1.GetRedPacketResponse\x12g\n" + - "\x10ExpireRedPackets\x12(.hyapp.wallet.v1.ExpireRedPacketsRequest\x1a).hyapp.wallet.v1.ExpireRedPacketsResponse\x12s\n" + - "\x14RetryRedPacketRefund\x12,.hyapp.wallet.v1.RetryRedPacketRefundRequest\x1a-.hyapp.wallet.v1.RetryRedPacketRefundResponseB*Z(hyapp.local/api/proto/wallet/v1;walletv1b\x06proto3" +var file_proto_wallet_v1_wallet_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x76, + 0x31, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x22, + 0xec, 0x03, 0x0a, 0x10, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x63, 0x65, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x73, 0x48, + 0x6f, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x6f, + 0x73, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x12, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x41, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xff, + 0x03, 0x0a, 0x11, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x10, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, + 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, + 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x64, 0x64, + 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x68, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x63, 0x65, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x11, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x39, 0x0a, 0x19, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, + 0x64, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x68, 0x6f, 0x73, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, + 0x64, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x65, 0x64, 0x12, 0x31, 0x0a, + 0x15, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x63, 0x79, 0x63, + 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x6f, + 0x73, 0x74, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x43, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, + 0x22, 0xed, 0x01, 0x0a, 0x0f, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x5f, 0x69, 0x73, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x12, + 0x31, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x1b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x61, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x17, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, + 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x22, 0xf0, 0x02, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, + 0x69, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, + 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, + 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, + 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, + 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x69, 0x63, 0x65, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, 0x0a, + 0x10, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x52, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3a, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, + 0x47, 0x69, 0x66, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x22, 0x9a, 0x01, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, + 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x49, 0x64, 0x12, 0x3c, 0x0a, 0x07, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x62, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, + 0x22, 0x9e, 0x01, 0x0a, 0x16, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, + 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x09, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x09, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x42, 0x0a, + 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, + 0x52, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x70, 0x74, + 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x0c, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, + 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, + 0x65, 0x22, 0x50, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x22, 0xaa, 0x02, 0x0a, 0x15, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, + 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x19, 0x0a, + 0x08, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x07, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x4e, 0x6f, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x44, 0x69, 0x61, + 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x73, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x68, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, + 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x73, 0x61, 0x6c, + 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x14, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x61, 0x6c, 0x61, 0x72, + 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x22, 0xe9, 0x03, 0x0a, 0x10, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x73, + 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x3a, 0x0a, 0x1a, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x69, 0x61, + 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x16, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x44, 0x69, 0x61, 0x6d, + 0x6f, 0x6e, 0x64, 0x52, 0x61, 0x74, 0x69, 0x6f, 0x12, 0x3e, 0x0a, 0x1c, 0x72, 0x65, 0x73, 0x69, + 0x64, 0x75, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x74, 0x6f, 0x5f, + 0x75, 0x73, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, + 0x72, 0x65, 0x73, 0x69, 0x64, 0x75, 0x61, 0x6c, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x54, + 0x6f, 0x55, 0x73, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, + 0x6f, 0x6d, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, 0x3e, 0x0a, 0x06, + 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x22, 0xf1, 0x01, 0x0a, + 0x20, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x74, 0x74, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x15, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x6e, 0x6f, 0x77, + 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, 0x6f, 0x77, 0x4d, 0x73, + 0x22, 0x74, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x39, 0x0a, 0x06, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, + 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x9a, 0x02, 0x0a, 0x12, 0x48, 0x6f, 0x73, 0x74, 0x53, + 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x20, 0x0a, + 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x1b, 0x0a, 0x09, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x61, 0x67, 0x65, + 0x6e, 0x63, 0x79, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x61, 0x67, 0x65, 0x6e, 0x63, 0x79, 0x4f, + 0x77, 0x6e, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, + 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, + 0x64, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x67, + 0x69, 0x66, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, + 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x22, 0xae, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, + 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x20, + 0x0a, 0x0c, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x15, 0x0a, + 0x06, 0x6e, 0x6f, 0x77, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x6e, + 0x6f, 0x77, 0x4d, 0x73, 0x22, 0x60, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, + 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x70, 0x72, + 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x22, 0x95, 0x02, 0x0a, 0x17, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, + 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, + 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x7a, + 0x0a, 0x18, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0xf9, 0x03, 0x0a, 0x21, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, + 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x63, 0x6b, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x69, 0x64, 0x5f, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x70, 0x61, 0x69, 0x64, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x61, 0x69, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, + 0x70, 0x61, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, + 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x66, + 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x65, 0x66, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x73, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, + 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x8f, 0x03, 0x0a, 0x22, 0x41, 0x64, 0x6d, 0x69, 0x6e, + 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, + 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x73, 0x74, 0x6f, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, + 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, + 0x69, 0x64, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, 0x69, 0x64, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x61, 0x69, 0x64, + 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x70, 0x61, 0x69, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, + 0x69, 0x63, 0x72, 0x6f, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5f, 0x61, + 0x73, 0x5f, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x41, + 0x73, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xd5, 0x02, 0x0a, 0x1d, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, + 0x22, 0x94, 0x04, 0x0a, 0x1e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, + 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, + 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x14, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, + 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x55, 0x73, 0x64, 0x4d, + 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x17, 0x72, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x72, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x3d, 0x0a, 0x1b, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x46, 0x0a, 0x20, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1c, 0x72, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, + 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x84, 0x02, 0x0a, 0x20, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x54, 0x69, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, + 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x22, 0x0a, + 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, + 0x72, 0x12, 0x20, 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x72, + 0x55, 0x73, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xb0, + 0x01, 0x0a, 0x2c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, + 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x61, 0x74, 0x65, 0x54, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x22, 0x78, 0x0a, 0x2d, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, + 0x6c, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x52, 0x61, 0x74, 0x65, 0x54, 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x47, 0x0a, 0x05, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, + 0x54, 0x69, 0x65, 0x72, 0x52, 0x05, 0x74, 0x69, 0x65, 0x72, 0x73, 0x22, 0xde, 0x01, 0x0a, 0x1b, + 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, + 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, + 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, + 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x92, 0x02, 0x0a, + 0x1c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, + 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x12, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, + 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x20, 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x65, 0x72, 0x55, 0x73, + 0x64, 0x22, 0xb4, 0x02, 0x0a, 0x21, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, + 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, + 0x61, 0x6c, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, + 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, + 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, + 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x19, 0x0a, + 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x83, 0x03, 0x0a, 0x22, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, + 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x1b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x14, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, + 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x12, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x61, 0x6c, 0x61, 0x72, + 0x79, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x73, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, + 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x65, + 0x72, 0x55, 0x73, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x69, 0x6e, + 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x69, 0x6e, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, + 0x72, 0x12, 0x2b, 0x0a, 0x12, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x73, + 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, + 0x61, 0x74, 0x65, 0x4d, 0x61, 0x78, 0x55, 0x73, 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x22, 0xe7, + 0x06, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, + 0x67, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2e, + 0x0a, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, + 0x0a, 0x0c, 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x73, 0x61, 0x67, 0x65, 0x53, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, + 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, 0x6c, 0x12, + 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, + 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x11, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x16, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, + 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc7, 0x03, 0x0a, 0x11, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x22, + 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x35, + 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x74, 0x65, + 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x74, + 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0xad, 0x03, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, + 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, + 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, + 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x4d, 0x73, 0x22, 0xa9, 0x06, 0x0a, 0x0a, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, + 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, + 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x73, + 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, + 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, + 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x68, 0x65, 0x61, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, + 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, + 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x14, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, + 0x6d, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x74, 0x6f, 0x5f, 0x6d, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xce, + 0x02, 0x0a, 0x0e, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, + 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x74, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x74, 0x61, 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x74, 0x61, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, + 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, + 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, + 0xb7, 0x04, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, + 0x49, 0x74, 0x65, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x20, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x49, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x64, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, + 0x79, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x44, 0x61, 0x79, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x50, + 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x6f, + 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, + 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, + 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x87, 0x04, 0x0a, 0x17, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x0a, 0x12, + 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, + 0x69, 0x6e, 0x67, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0f, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x71, 0x75, 0x69, 0x70, + 0x70, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x71, 0x75, 0x69, 0x70, + 0x70, 0x65, 0x64, 0x22, 0x86, 0x03, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x47, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x19, 0x0a, + 0x08, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x6a, + 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4a, 0x73, 0x6f, 0x6e, 0x12, + 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x1f, 0x0a, 0x0b, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, + 0x15, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xe1, 0x03, 0x0a, + 0x0d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x12, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x38, + 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, + 0x22, 0x8e, 0x02, 0x0a, 0x16, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, + 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, + 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x74, 0x65, 0x6d, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x74, 0x65, + 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, + 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x22, 0xa7, 0x02, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, + 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x2c, 0x0a, + 0x12, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x6f, + 0x6e, 0x6c, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x66, 0x0a, 0x15, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x22, 0x6f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x64, 0x22, 0x4c, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x22, 0x99, 0x06, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, + 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x0b, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0b, 0x75, 0x73, 0x61, 0x67, 0x65, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, + 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, + 0x0b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, 0x6c, 0x12, 0x23, + 0x0a, 0x0d, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, + 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, + 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, + 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x37, 0x0a, 0x15, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x13, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, + 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, + 0x6f, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x15, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, + 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xba, + 0x06, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x2a, + 0x0a, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x73, + 0x61, 0x67, 0x65, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x75, 0x73, 0x61, 0x67, 0x65, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x1b, 0x0a, + 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x61, + 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, + 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6a, 0x73, 0x6f, + 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x37, + 0x0a, 0x15, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x13, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x70, + 0x72, 0x69, 0x63, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x72, 0x5f, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xb7, 0x01, 0x0a, 0x18, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x49, 0x0a, 0x10, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x22, 0xd9, 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, + 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, + 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x6a, 0x0a, 0x1a, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x6e, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, + 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x22, 0x50, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xcb, 0x02, 0x0a, 0x1a, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, + 0x3d, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x74, + 0x65, 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x28, + 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xe6, 0x02, 0x0a, 0x1a, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, + 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, + 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, + 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x1d, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, + 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x4d, 0x0a, 0x15, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0xbe, 0x02, 0x0a, 0x16, 0x4c, 0x69, + 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, + 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x23, 0x0a, 0x0d, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, + 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x62, 0x0a, 0x17, 0x4c, 0x69, + 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x69, 0x66, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x05, 0x67, 0x69, 0x66, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x8f, + 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, + 0x22, 0x5d, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3e, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, + 0x82, 0x02, 0x0a, 0x1b, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, + 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, + 0x62, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x62, + 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x22, 0x56, 0x0a, 0x16, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, + 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xce, 0x05, 0x0a, + 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, + 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, + 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x73, 0x65, + 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, + 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, + 0x6f, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x68, 0x65, 0x61, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, + 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, 0x6d, + 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x74, 0x6f, 0x5f, 0x6d, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, 0x66, + 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xce, 0x05, + 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, + 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, + 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x73, + 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, + 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x63, 0x6f, 0x69, 0x6e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x67, 0x69, 0x66, + 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x68, 0x65, 0x61, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x28, 0x0a, 0x10, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, + 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x46, 0x72, 0x6f, + 0x6d, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, + 0x5f, 0x74, 0x6f, 0x5f, 0x6d, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x65, 0x66, + 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xb1, + 0x01, 0x0a, 0x1a, 0x53, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x22, 0x45, 0x0a, 0x12, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x67, 0x69, 0x66, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x04, 0x67, 0x69, 0x66, 0x74, 0x22, 0xb9, 0x02, 0x0a, 0x14, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xfb, 0x01, 0x0a, 0x19, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, + 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x22, 0x4d, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x05, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x05, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x22, 0xb3, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x63, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0xb5, 0x01, + 0x0a, 0x18, 0x45, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x61, 0x0a, 0x19, 0x45, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x44, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x55, 0x6e, 0x65, + 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, + 0x86, 0x01, 0x0a, 0x1b, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x75, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x70, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x6e, 0x65, 0x71, 0x75, 0x69, + 0x70, 0x70, 0x65, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x24, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, + 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x07, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x78, 0x0a, + 0x15, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x46, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x65, 0x0a, 0x25, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3c, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0xc4, + 0x01, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x6a, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x52, 0x06, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x22, 0x8a, 0x02, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, + 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x73, + 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x73, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x79, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x79, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x65, + 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x6d, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x4d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x65, 0x66, 0x66, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0d, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x54, 0x6f, 0x4d, 0x73, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x81, + 0x02, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, + 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, + 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4f, 0x6e, + 0x6c, 0x79, 0x22, 0x6e, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, + 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x22, 0xc2, 0x01, 0x0a, 0x1e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x3c, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, + 0x6d, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x28, 0x0a, + 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5a, 0x0a, 0x1f, 0x55, 0x70, 0x73, 0x65, 0x72, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, + 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x69, 0x74, + 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, + 0x65, 0x6d, 0x73, 0x22, 0xc0, 0x01, 0x0a, 0x20, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x68, 0x6f, 0x70, 0x49, 0x74, + 0x65, 0x6d, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, + 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x51, 0x0a, 0x18, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x96, 0x01, 0x0a, 0x1f, 0x50, 0x75, + 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, + 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x73, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, + 0x49, 0x64, 0x22, 0xee, 0x02, 0x0a, 0x20, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3e, 0x0a, 0x09, 0x73, 0x68, 0x6f, 0x70, 0x5f, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x08, 0x73, 0x68, 0x6f, + 0x70, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x44, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x62, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, + 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, + 0x65, 0x6e, 0x74, 0x22, 0xa7, 0x05, 0x0a, 0x0c, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x42, 0x69, 0x6c, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x72, + 0x65, 0x66, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x52, 0x65, 0x66, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, + 0x0a, 0x0e, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, + 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x28, + 0x0a, 0x10, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0d, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x64, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x75, 0x73, + 0x64, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x14, + 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x65, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x39, + 0x0a, 0x19, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x75, 0x73, 0x64, 0x5f, 0x6d, + 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x16, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x55, 0x73, 0x64, 0x4d, 0x69, + 0x6e, 0x6f, 0x72, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xf4, 0x02, + 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, + 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, + 0x0e, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, + 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, + 0x53, 0x69, 0x7a, 0x65, 0x22, 0x66, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x33, 0x0a, 0x05, 0x62, 0x69, 0x6c, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x52, + 0x05, 0x62, 0x69, 0x6c, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x79, 0x0a, 0x12, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, + 0x67, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x72, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x38, 0x0a, + 0x18, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x16, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x6d, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x57, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, + 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x57, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x48, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x46, + 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x52, 0x0c, 0x66, 0x65, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x59, 0x0a, 0x12, 0x57, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, + 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x73, 0x22, 0x71, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, + 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5e, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x57, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, + 0x61, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, + 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x22, 0xec, 0x05, 0x0a, 0x0c, 0x47, 0x69, 0x66, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x69, 0x66, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x35, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x4a, 0x73, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0e, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, + 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x73, 0x6f, 0x6e, 0x12, + 0x1d, 0x0a, 0x0a, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x67, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x43, 0x6f, 0x69, 0x6e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x61, + 0x6d, 0x6f, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, + 0x69, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x65, 0x61, + 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2a, 0x0a, + 0x11, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x50, 0x72, 0x69, 0x63, 0x65, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x14, 0x66, 0x69, 0x72, 0x73, 0x74, + 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x66, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, + 0x76, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x6b, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x47, 0x69, 0x66, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x64, 0x22, 0xef, 0x02, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, + 0x69, 0x66, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x33, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x69, 0x66, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x6b, 0x69, 0x6e, + 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x67, + 0x69, 0x66, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, + 0x67, 0x69, 0x66, 0x74, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x67, 0x69, 0x66, 0x74, 0x54, 0x6f, 0x74, 0x61, + 0x6c, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x69, 0x6e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x61, 0x6d, 0x6f, + 0x6e, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x67, 0x69, 0x66, 0x74, 0x5f, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x47, 0x69, 0x66, 0x74, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x68, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x48, 0x65, 0x61, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xde, 0x05, 0x0a, 0x0f, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, + 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, + 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, + 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x21, + 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, + 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0d, 0x20, + 0x03, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x2e, + 0x0a, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x0f, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x12, 0x2b, 0x0a, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2b, + 0x0a, 0x12, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x42, 0x79, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x22, 0x0a, 0x0d, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, + 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x13, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, + 0x72, 0x6d, 0x22, 0x78, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x73, 0x22, 0xfd, 0x02, 0x0a, + 0x1b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, + 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, + 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, + 0x73, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x70, 0x75, + 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xf5, 0x02, 0x0a, + 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, + 0x10, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, + 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, + 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, + 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, + 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x12, + 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x22, 0xf8, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, + 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, + 0x77, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xe0, 0x02, 0x0a, 0x1c, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6d, 0x69, + 0x63, 0x72, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, 0x6f, 0x69, + 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, + 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x67, 0x69, + 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xff, 0x02, 0x0a, 0x1c, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, + 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, + 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x63, + 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, + 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, + 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xa1, 0x01, + 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, + 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x70, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, + 0x64, 0x22, 0x55, 0x0a, 0x17, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, + 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x07, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, + 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x22, 0x39, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x64, 0x22, 0xde, 0x01, 0x0a, 0x13, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x26, 0x0a, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x74, 0x6f, 0x5f, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x74, 0x6f, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, + 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x74, 0x6f, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x08, 0x74, 0x6f, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x22, 0x74, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, + 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x5e, 0x0a, 0x20, 0x47, 0x65, + 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, + 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x96, 0x03, 0x0a, 0x11, 0x57, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x69, 0x7a, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x69, 0x7a, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x0f, + 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x5f, + 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x6f, + 0x7a, 0x65, 0x6e, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x5f, 0x61, 0x66, 0x74, 0x65, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x7a, 0x65, 0x6e, 0x41, + 0x66, 0x74, 0x65, 0x72, 0x12, 0x30, 0x0a, 0x14, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x61, 0x72, 0x74, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x12, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x61, 0x72, 0x74, 0x79, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, + 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, + 0x74, 0x4d, 0x73, 0x22, 0xc2, 0x01, 0x0a, 0x1d, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, + 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x7e, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0xb1, 0x02, 0x0a, 0x0d, 0x56, 0x69, 0x70, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x71, 0x75, 0x61, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, + 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, + 0x73, 0x65, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, + 0x76, 0x69, 0x65, 0x77, 0x55, 0x72, 0x6c, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6e, 0x69, 0x6d, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x61, 0x6e, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x22, 0xfc, 0x04, 0x0a, + 0x08, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, + 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, + 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x37, 0x0a, 0x18, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x15, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, + 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x61, 0x6e, 0x5f, 0x70, + 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x63, + 0x61, 0x6e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, + 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, + 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x47, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, + 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x19, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x75, 0x73, 0x65, 0x72, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, + 0x16, 0x70, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, + 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, + 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x07, + 0x55, 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, + 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, + 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x6b, + 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8b, 0x01, 0x0a, 0x17, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x5f, 0x76, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x52, 0x0a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x56, + 0x69, 0x70, 0x12, 0x35, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, + 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0f, 0x47, 0x65, 0x74, + 0x4d, 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, + 0x3e, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x03, 0x76, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x52, 0x03, 0x76, 0x69, 0x70, 0x22, + 0x7d, 0x0a, 0x12, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, + 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x93, + 0x02, 0x0a, 0x13, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x03, 0x76, 0x69, 0x70, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x52, + 0x03, 0x76, 0x69, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, + 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, + 0x65, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x10, 0x63, 0x6f, 0x69, 0x6e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x12, 0x41, 0x0a, 0x0c, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, + 0x74, 0x65, 0x6d, 0x73, 0x22, 0xec, 0x01, 0x0a, 0x0f, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, + 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x22, 0xce, 0x01, 0x0a, 0x10, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x2a, 0x0a, 0x03, 0x76, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x73, 0x65, 0x72, 0x56, 0x69, 0x70, 0x52, 0x03, 0x76, 0x69, 0x70, 0x12, 0x41, 0x0a, 0x0c, 0x72, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, + 0x6d, 0x52, 0x0b, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x24, + 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, + 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xb1, 0x02, 0x0a, 0x12, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, + 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, + 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, + 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, + 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x37, 0x0a, + 0x18, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x15, 0x72, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x64, 0x5f, 0x72, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x69, 0x6e, 0x5f, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x43, 0x6f, + 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, + 0x75, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, + 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, + 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, + 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x3b, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x28, 0x0a, + 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, + 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0x77, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x52, 0x06, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, + 0x22, 0xfc, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, + 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, + 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x73, 0x6b, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x79, + 0x63, 0x6c, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, + 0x79, 0x63, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, + 0xb6, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x67, 0x72, 0x61, + 0x6e, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0xbe, 0x02, 0x0a, 0x1c, 0x43, 0x72, 0x65, + 0x64, 0x69, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x73, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x61, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x64, 0x72, 0x61, 0x77, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, + 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, + 0x6d, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x66, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x66, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x70, 0x6f, 0x6f, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, + 0x6f, 0x6f, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, + 0x11, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0f, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, + 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xbb, 0x01, 0x0a, 0x1d, 0x43, 0x72, + 0x65, 0x64, 0x69, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x77, + 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x6e, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x90, 0x03, 0x0a, 0x1f, 0x43, 0x72, 0x65, 0x64, + 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, + 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, + 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x65, 0x74, 0x74, + 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, + 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0d, 0x70, 0x65, 0x72, 0x69, + 0x6f, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x70, 0x65, 0x72, + 0x69, 0x6f, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x45, 0x6e, 0x64, 0x4d, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x53, 0x70, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x74, + 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x65, 0x72, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x43, + 0x72, 0x65, 0x64, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x22, 0x0a, 0x0d, 0x67, 0x72, 0x61, 0x6e, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x67, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x22, 0x9a, 0x03, 0x0a, 0x1a, + 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, + 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x67, 0x61, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x6f, 0x75, 0x6e, 0x64, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6f, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x70, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x63, + 0x6f, 0x69, 0x6e, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x48, 0x61, 0x73, 0x68, 0x22, 0xa3, 0x01, 0x0a, 0x1b, 0x41, 0x70, 0x70, + 0x6c, 0x79, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, + 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x5f, + 0x72, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x64, + 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x79, 0x22, 0x9f, + 0x03, 0x0a, 0x0f, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x5f, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x54, 0x69, 0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x69, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x64, + 0x65, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x64, 0x65, 0x6c, 0x61, 0x79, + 0x65, 0x64, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, + 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x73, 0x65, + 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x64, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x65, 0x6e, 0x64, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2d, + 0x0a, 0x13, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x22, 0x0a, + 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, + 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, + 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x75, 0x72, + 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x55, 0x72, 0x6c, + 0x22, 0xee, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x63, + 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x16, + 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x65, + 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, + 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, + 0x73, 0x22, 0xa0, 0x06, 0x0a, 0x09, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, + 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, + 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6d, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6d, + 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0a, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x6d, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, + 0x67, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x72, + 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6f, 0x70, 0x65, 0x6e, 0x41, + 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, + 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x73, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x4d, 0x73, 0x12, + 0x2a, 0x0a, 0x11, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x63, 0x6c, 0x61, 0x69, + 0x6d, 0x65, 0x64, 0x42, 0x79, 0x56, 0x69, 0x65, 0x77, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x13, 0x76, + 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x61, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x03, 0x52, 0x11, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, + 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x06, 0x63, + 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x13, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x06, 0x63, 0x6c, + 0x61, 0x69, 0x6d, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x5f, 0x61, + 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x66, + 0x75, 0x6e, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x66, + 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, + 0x0a, 0x0e, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x5f, 0x6d, 0x73, + 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, + 0x41, 0x74, 0x4d, 0x73, 0x22, 0x55, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x7c, 0x0a, 0x1a, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xfe, 0x02, 0x0a, 0x1c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, + 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x69, 0x65, 0x72, 0x73, 0x12, + 0x21, 0x0a, 0x0c, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x69, 0x65, + 0x72, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x12, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x64, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x73, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x65, 0x78, + 0x70, 0x69, 0x72, 0x65, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x64, + 0x61, 0x69, 0x6c, 0x79, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x64, 0x61, 0x69, 0x6c, 0x79, 0x53, 0x65, 0x6e, 0x64, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, + 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x55, 0x72, 0x6c, 0x22, 0x7f, 0x0a, 0x1d, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xb4, 0x02, 0x0a, 0x16, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x12, + 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x1b, + 0x0a, 0x09, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x22, 0x98, 0x01, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, + 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, + 0x65, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, + 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xa6, 0x01, + 0x0a, 0x15, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, + 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x22, 0xce, 0x01, 0x0a, 0x16, 0x43, 0x6c, 0x61, 0x69, 0x6d, + 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x52, 0x05, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, + 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, + 0x65, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0xf9, 0x02, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, + 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x72, + 0x6f, 0x6f, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, + 0x6f, 0x6d, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, + 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, + 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, + 0x55, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1e, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x61, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x41, 0x74, 0x4d, 0x73, 0x12, 0x1a, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x74, + 0x5f, 0x6d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x41, 0x74, + 0x4d, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, + 0x69, 0x7a, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, + 0x69, 0x7a, 0x65, 0x22, 0x8a, 0x01, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, + 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x07, 0x70, 0x61, 0x63, + 0x6b, 0x65, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, + 0x22, 0xb9, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, + 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, + 0x24, 0x0a, 0x0e, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x55, + 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x22, 0x70, 0x0a, 0x14, + 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0x72, + 0x0a, 0x17, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, + 0x7a, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x18, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, + 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, + 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x24, 0x0a, + 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x69, 0x6d, + 0x65, 0x4d, 0x73, 0x22, 0x9e, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, + 0x09, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x55, 0x73, + 0x65, 0x72, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x66, + 0x75, 0x6e, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x0e, 0x72, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x6f, + 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, + 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, + 0x61, 0x70, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x61, 0x70, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x15, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x1b, + 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x62, 0x61, 0x74, 0x63, 0x68, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x0a, 0x0b, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x74, 0x74, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x6c, 0x6f, 0x63, 0x6b, 0x54, 0x74, 0x6c, 0x4d, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x11, 0x43, + 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x65, 0x64, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, + 0x0a, 0x0d, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x66, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x68, 0x61, 0x73, 0x5f, + 0x6d, 0x6f, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x68, 0x61, 0x73, 0x4d, + 0x6f, 0x72, 0x65, 0x32, 0xe0, 0x02, 0x0a, 0x11, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x43, 0x72, + 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6e, 0x0a, 0x25, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x44, 0x61, + 0x69, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x29, 0x50, 0x72, 0x6f, + 0x63, 0x65, 0x73, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x48, 0x61, + 0x6c, 0x66, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, + 0x1e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, + 0x72, 0x79, 0x4d, 0x6f, 0x6e, 0x74, 0x68, 0x45, 0x6e, 0x64, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, + 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x6e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x89, 0x3b, 0x0a, 0x0d, 0x57, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x09, 0x44, 0x65, 0x62, 0x69, + 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x69, 0x74, + 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x0e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x12, 0x26, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x65, + 0x62, 0x69, 0x74, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x58, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x23, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x19, 0x47, 0x65, + 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, + 0x79, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, + 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, + 0x74, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x10, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, + 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, + 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, + 0x69, 0x74, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x85, 0x01, 0x0a, 0x1a, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x43, + 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x12, 0x32, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x69, 0x6e, + 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, + 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x74, 0x6f, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x6c, 0x6c, 0x65, + 0x72, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, + 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x6f, 0x69, 0x6e, + 0x46, 0x72, 0x6f, 0x6d, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x54, 0x69, 0x65, 0x72, 0x73, 0x12, 0x3d, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x61, 0x6c, + 0x61, 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x54, + 0x69, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, + 0x72, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x61, 0x74, 0x65, 0x54, 0x69, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, + 0x6f, 0x69, 0x6e, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x61, 0x6c, 0x61, + 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x85, 0x01, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x61, 0x6c, + 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x12, + 0x32, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x61, 0x6c, 0x61, 0x72, 0x79, + 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x53, 0x61, + 0x6c, 0x61, 0x72, 0x79, 0x54, 0x6f, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x65, 0x6c, 0x6c, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5b, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x11, + 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x6d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x70, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x64, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x47, + 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x10, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x10, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x67, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x69, 0x66, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x66, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x69, 0x66, 0x74, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x0d, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x25, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x12, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2a, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6a, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, + 0x11, 0x45, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x13, 0x55, 0x6e, 0x65, + 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x6e, 0x65, 0x71, 0x75, 0x69, 0x70, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8e, 0x01, 0x0a, 0x1d, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, + 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x35, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, + 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x45, 0x71, 0x75, 0x69, 0x70, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x12, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x72, 0x61, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, + 0x74, 0x65, 0x6d, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x17, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x2f, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, + 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x79, 0x0a, 0x19, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x31, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x53, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, + 0x49, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, + 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x18, + 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x53, 0x68, 0x6f, 0x70, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, + 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, 0x70, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x72, + 0x63, 0x68, 0x61, 0x73, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x68, 0x6f, + 0x70, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, + 0x11, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, + 0x6c, 0x73, 0x12, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, + 0x65, 0x42, 0x69, 0x6c, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x42, 0x69, 0x6c, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x11, 0x47, 0x65, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x12, 0x29, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, + 0x65, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x2d, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x53, 0x75, + 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x69, 0x66, 0x74, 0x57, 0x61, 0x6c, 0x6c, + 0x12, 0x27, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x69, 0x66, 0x74, 0x57, 0x61, + 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x47, 0x69, 0x66, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x72, 0x6d, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, + 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, 0x61, + 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x31, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, + 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x70, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, + 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x2d, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, + 0x75, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x63, + 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x2d, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, + 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, + 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x63, 0x68, 0x61, 0x72, 0x67, 0x65, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, + 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x30, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x44, 0x69, 0x61, 0x6d, 0x6f, 0x6e, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x79, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x57, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x0f, 0x4c, 0x69, + 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x27, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x69, 0x70, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4f, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x12, 0x20, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x79, 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, + 0x12, 0x23, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, 0x56, 0x69, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x72, 0x63, 0x68, 0x61, 0x73, 0x65, + 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x08, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x56, 0x69, 0x70, 0x12, 0x20, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x56, + 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x56, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x12, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x73, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, + 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, + 0x65, 0x6c, 0x73, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x56, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x56, + 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x67, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, + 0x77, 0x61, 0x72, 0x64, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, + 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x54, 0x61, 0x73, + 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x77, 0x61, 0x72, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x43, 0x72, 0x65, + 0x64, 0x69, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x77, 0x61, + 0x72, 0x64, 0x12, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, + 0x47, 0x69, 0x66, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x4c, 0x75, 0x63, 0x6b, 0x79, 0x47, + 0x69, 0x66, 0x74, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7f, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, + 0x75, 0x72, 0x6e, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x12, 0x30, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, 0x6f, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x31, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x54, 0x75, 0x72, 0x6e, + 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x77, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x70, 0x0a, 0x13, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x61, 0x6d, 0x65, 0x43, + 0x6f, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, + 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, + 0x79, 0x47, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x47, 0x61, + 0x6d, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2a, 0x2e, 0x68, 0x79, 0x61, + 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x2e, 0x68, + 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x0f, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x27, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, + 0x6b, 0x65, 0x74, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x52, 0x65, 0x64, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x68, 0x79, + 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, + 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x24, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, + 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x52, 0x65, + 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x28, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, + 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, + 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x52, 0x65, 0x64, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, + 0x14, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, + 0x65, 0x66, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, + 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x65, 0x64, + 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x74, 0x72, 0x79, 0x52, 0x65, 0x64, 0x50, 0x61, + 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x66, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x42, 0x2a, 0x5a, 0x28, 0x68, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x77, 0x61, 0x6c, 0x6c, + 0x65, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x76, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} var ( file_proto_wallet_v1_wallet_proto_rawDescOnce sync.Once - file_proto_wallet_v1_wallet_proto_rawDescData []byte + file_proto_wallet_v1_wallet_proto_rawDescData = file_proto_wallet_v1_wallet_proto_rawDesc ) func file_proto_wallet_v1_wallet_proto_rawDescGZIP() []byte { file_proto_wallet_v1_wallet_proto_rawDescOnce.Do(func() { - file_proto_wallet_v1_wallet_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc))) + file_proto_wallet_v1_wallet_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_wallet_v1_wallet_proto_rawDescData) }) return file_proto_wallet_v1_wallet_proto_rawDescData } @@ -16181,7 +17939,7 @@ func file_proto_wallet_v1_wallet_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_wallet_v1_wallet_proto_rawDesc), len(file_proto_wallet_v1_wallet_proto_rawDesc)), + RawDescriptor: file_proto_wallet_v1_wallet_proto_rawDesc, NumEnums: 0, NumMessages: 163, NumExtensions: 0, @@ -16192,6 +17950,7 @@ func file_proto_wallet_v1_wallet_proto_init() { MessageInfos: file_proto_wallet_v1_wallet_proto_msgTypes, }.Build() File_proto_wallet_v1_wallet_proto = out.File + file_proto_wallet_v1_wallet_proto_rawDesc = nil file_proto_wallet_v1_wallet_proto_goTypes = nil file_proto_wallet_v1_wallet_proto_depIdxs = nil } diff --git a/api/proto/wallet/v1/wallet.proto b/api/proto/wallet/v1/wallet.proto index 24e24c98..41731662 100644 --- a/api/proto/wallet/v1/wallet.proto +++ b/api/proto/wallet/v1/wallet.proto @@ -196,6 +196,8 @@ message AdminCreditCoinSellerStockRequest { int64 operator_user_id = 9; string reason = 10; string app_code = 11; + int64 seller_country_id = 12; + int64 seller_region_id = 13; } message AdminCreditCoinSellerStockResponse { @@ -218,9 +220,10 @@ message TransferCoinFromSellerRequest { int64 amount = 4; string reason = 5; string app_code = 6; - // seller_region_id 和 target_region_id 由 gateway 从 user-service 查询,不接受客户端提交。 + // seller_region_id、target_region_id 和 target_country_id 由 gateway 从 user-service 查询,不接受客户端提交。 int64 seller_region_id = 7; int64 target_region_id = 8; + int64 target_country_id = 9; } // TransferCoinFromSellerResponse 同时返回金币到账结果和本次转账对应的充值金额口径。 diff --git a/api/proto/wallet/v1/wallet_grpc.pb.go b/api/proto/wallet/v1/wallet_grpc.pb.go index 91ff44d8..92fead0f 100644 --- a/api/proto/wallet/v1/wallet_grpc.pb.go +++ b/api/proto/wallet/v1/wallet_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.6.2 +// - protoc-gen-go-grpc v1.5.1 // - protoc v7.35.0 // source: proto/wallet/v1/wallet.proto @@ -93,13 +93,13 @@ type WalletCronServiceServer interface { type UnimplementedWalletCronServiceServer struct{} func (UnimplementedWalletCronServiceServer) ProcessHostSalaryDailySettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryDailySettlementBatch not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryDailySettlementBatch not implemented") } func (UnimplementedWalletCronServiceServer) ProcessHostSalaryHalfMonthSettlementBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryHalfMonthSettlementBatch not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryHalfMonthSettlementBatch not implemented") } func (UnimplementedWalletCronServiceServer) ProcessHostSalaryMonthEndBatch(context.Context, *CronBatchRequest) (*CronBatchResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ProcessHostSalaryMonthEndBatch not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ProcessHostSalaryMonthEndBatch not implemented") } func (UnimplementedWalletCronServiceServer) mustEmbedUnimplementedWalletCronServiceServer() {} func (UnimplementedWalletCronServiceServer) testEmbeddedByValue() {} @@ -112,7 +112,7 @@ type UnsafeWalletCronServiceServer interface { } func RegisterWalletCronServiceServer(s grpc.ServiceRegistrar, srv WalletCronServiceServer) { - // If the following call panics, it indicates UnimplementedWalletCronServiceServer was + // If the following call pancis, it indicates UnimplementedWalletCronServiceServer 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. @@ -1120,208 +1120,208 @@ type WalletServiceServer interface { type UnimplementedWalletServiceServer struct{} func (UnimplementedWalletServiceServer) DebitGift(context.Context, *DebitGiftRequest) (*DebitGiftResponse, error) { - return nil, status.Error(codes.Unimplemented, "method DebitGift not implemented") + return nil, status.Errorf(codes.Unimplemented, "method DebitGift not implemented") } func (UnimplementedWalletServiceServer) BatchDebitGift(context.Context, *BatchDebitGiftRequest) (*BatchDebitGiftResponse, error) { - return nil, status.Error(codes.Unimplemented, "method BatchDebitGift not implemented") + return nil, status.Errorf(codes.Unimplemented, "method BatchDebitGift not implemented") } func (UnimplementedWalletServiceServer) GetBalances(context.Context, *GetBalancesRequest) (*GetBalancesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetBalances not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetBalances not implemented") } func (UnimplementedWalletServiceServer) GetActiveHostSalaryPolicy(context.Context, *GetActiveHostSalaryPolicyRequest) (*GetActiveHostSalaryPolicyResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetActiveHostSalaryPolicy not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetActiveHostSalaryPolicy not implemented") } func (UnimplementedWalletServiceServer) GetHostSalaryProgress(context.Context, *GetHostSalaryProgressRequest) (*GetHostSalaryProgressResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetHostSalaryProgress not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetHostSalaryProgress not implemented") } func (UnimplementedWalletServiceServer) AdminCreditAsset(context.Context, *AdminCreditAssetRequest) (*AdminCreditAssetResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminCreditAsset not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminCreditAsset not implemented") } func (UnimplementedWalletServiceServer) AdminCreditCoinSellerStock(context.Context, *AdminCreditCoinSellerStockRequest) (*AdminCreditCoinSellerStockResponse, error) { - return nil, status.Error(codes.Unimplemented, "method AdminCreditCoinSellerStock not implemented") + return nil, status.Errorf(codes.Unimplemented, "method AdminCreditCoinSellerStock not implemented") } func (UnimplementedWalletServiceServer) TransferCoinFromSeller(context.Context, *TransferCoinFromSellerRequest) (*TransferCoinFromSellerResponse, error) { - return nil, status.Error(codes.Unimplemented, "method TransferCoinFromSeller not implemented") + return nil, status.Errorf(codes.Unimplemented, "method TransferCoinFromSeller not implemented") } func (UnimplementedWalletServiceServer) ListCoinSellerSalaryExchangeRateTiers(context.Context, *ListCoinSellerSalaryExchangeRateTiersRequest) (*ListCoinSellerSalaryExchangeRateTiersResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListCoinSellerSalaryExchangeRateTiers not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListCoinSellerSalaryExchangeRateTiers not implemented") } func (UnimplementedWalletServiceServer) ExchangeSalaryToCoin(context.Context, *ExchangeSalaryToCoinRequest) (*ExchangeSalaryToCoinResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ExchangeSalaryToCoin not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ExchangeSalaryToCoin not implemented") } func (UnimplementedWalletServiceServer) TransferSalaryToCoinSeller(context.Context, *TransferSalaryToCoinSellerRequest) (*TransferSalaryToCoinSellerResponse, error) { - return nil, status.Error(codes.Unimplemented, "method TransferSalaryToCoinSeller not implemented") + return nil, status.Errorf(codes.Unimplemented, "method TransferSalaryToCoinSeller not implemented") } func (UnimplementedWalletServiceServer) ListResources(context.Context, *ListResourcesRequest) (*ListResourcesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListResources not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListResources not implemented") } func (UnimplementedWalletServiceServer) GetResource(context.Context, *GetResourceRequest) (*GetResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetResource not implemented") } func (UnimplementedWalletServiceServer) CreateResource(context.Context, *CreateResourceRequest) (*ResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateResource not implemented") } func (UnimplementedWalletServiceServer) UpdateResource(context.Context, *UpdateResourceRequest) (*ResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateResource not implemented") } func (UnimplementedWalletServiceServer) SetResourceStatus(context.Context, *SetResourceStatusRequest) (*ResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetResourceStatus not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetResourceStatus not implemented") } func (UnimplementedWalletServiceServer) ListResourceGroups(context.Context, *ListResourceGroupsRequest) (*ListResourceGroupsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListResourceGroups not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListResourceGroups not implemented") } func (UnimplementedWalletServiceServer) GetResourceGroup(context.Context, *GetResourceGroupRequest) (*GetResourceGroupResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetResourceGroup not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetResourceGroup not implemented") } func (UnimplementedWalletServiceServer) CreateResourceGroup(context.Context, *CreateResourceGroupRequest) (*ResourceGroupResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateResourceGroup not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateResourceGroup not implemented") } func (UnimplementedWalletServiceServer) UpdateResourceGroup(context.Context, *UpdateResourceGroupRequest) (*ResourceGroupResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateResourceGroup not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateResourceGroup not implemented") } func (UnimplementedWalletServiceServer) SetResourceGroupStatus(context.Context, *SetResourceGroupStatusRequest) (*ResourceGroupResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetResourceGroupStatus not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetResourceGroupStatus not implemented") } func (UnimplementedWalletServiceServer) ListGiftConfigs(context.Context, *ListGiftConfigsRequest) (*ListGiftConfigsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListGiftConfigs not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListGiftConfigs not implemented") } func (UnimplementedWalletServiceServer) ListGiftTypeConfigs(context.Context, *ListGiftTypeConfigsRequest) (*ListGiftTypeConfigsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListGiftTypeConfigs not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListGiftTypeConfigs not implemented") } func (UnimplementedWalletServiceServer) CreateGiftConfig(context.Context, *CreateGiftConfigRequest) (*GiftConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateGiftConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateGiftConfig not implemented") } func (UnimplementedWalletServiceServer) UpdateGiftConfig(context.Context, *UpdateGiftConfigRequest) (*GiftConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateGiftConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateGiftConfig not implemented") } func (UnimplementedWalletServiceServer) SetGiftConfigStatus(context.Context, *SetGiftConfigStatusRequest) (*GiftConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetGiftConfigStatus not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetGiftConfigStatus not implemented") } func (UnimplementedWalletServiceServer) UpsertGiftTypeConfig(context.Context, *UpsertGiftTypeConfigRequest) (*GiftTypeConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpsertGiftTypeConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpsertGiftTypeConfig not implemented") } func (UnimplementedWalletServiceServer) GrantResource(context.Context, *GrantResourceRequest) (*ResourceGrantResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GrantResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GrantResource not implemented") } func (UnimplementedWalletServiceServer) GrantResourceGroup(context.Context, *GrantResourceGroupRequest) (*ResourceGrantResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GrantResourceGroup not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GrantResourceGroup not implemented") } func (UnimplementedWalletServiceServer) ListUserResources(context.Context, *ListUserResourcesRequest) (*ListUserResourcesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListUserResources not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListUserResources not implemented") } func (UnimplementedWalletServiceServer) EquipUserResource(context.Context, *EquipUserResourceRequest) (*EquipUserResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method EquipUserResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method EquipUserResource not implemented") } func (UnimplementedWalletServiceServer) UnequipUserResource(context.Context, *UnequipUserResourceRequest) (*UnequipUserResourceResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UnequipUserResource not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UnequipUserResource not implemented") } func (UnimplementedWalletServiceServer) BatchGetUserEquippedResources(context.Context, *BatchGetUserEquippedResourcesRequest) (*BatchGetUserEquippedResourcesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method BatchGetUserEquippedResources not implemented") + return nil, status.Errorf(codes.Unimplemented, "method BatchGetUserEquippedResources not implemented") } func (UnimplementedWalletServiceServer) ListResourceGrants(context.Context, *ListResourceGrantsRequest) (*ListResourceGrantsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListResourceGrants not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListResourceGrants not implemented") } func (UnimplementedWalletServiceServer) ListResourceShopItems(context.Context, *ListResourceShopItemsRequest) (*ListResourceShopItemsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListResourceShopItems not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListResourceShopItems not implemented") } func (UnimplementedWalletServiceServer) UpsertResourceShopItems(context.Context, *UpsertResourceShopItemsRequest) (*UpsertResourceShopItemsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpsertResourceShopItems not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpsertResourceShopItems not implemented") } func (UnimplementedWalletServiceServer) SetResourceShopItemStatus(context.Context, *SetResourceShopItemStatusRequest) (*ResourceShopItemResponse, error) { - return nil, status.Error(codes.Unimplemented, "method SetResourceShopItemStatus not implemented") + return nil, status.Errorf(codes.Unimplemented, "method SetResourceShopItemStatus not implemented") } func (UnimplementedWalletServiceServer) PurchaseResourceShopItem(context.Context, *PurchaseResourceShopItemRequest) (*PurchaseResourceShopItemResponse, error) { - return nil, status.Error(codes.Unimplemented, "method PurchaseResourceShopItem not implemented") + return nil, status.Errorf(codes.Unimplemented, "method PurchaseResourceShopItem not implemented") } func (UnimplementedWalletServiceServer) ListRechargeBills(context.Context, *ListRechargeBillsRequest) (*ListRechargeBillsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRechargeBills not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRechargeBills not implemented") } func (UnimplementedWalletServiceServer) GetWalletOverview(context.Context, *GetWalletOverviewRequest) (*GetWalletOverviewResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetWalletOverview not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetWalletOverview not implemented") } func (UnimplementedWalletServiceServer) GetWalletValueSummary(context.Context, *GetWalletValueSummaryRequest) (*GetWalletValueSummaryResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetWalletValueSummary not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetWalletValueSummary not implemented") } func (UnimplementedWalletServiceServer) GetUserGiftWall(context.Context, *GetUserGiftWallRequest) (*GetUserGiftWallResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetUserGiftWall not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetUserGiftWall not implemented") } func (UnimplementedWalletServiceServer) ListRechargeProducts(context.Context, *ListRechargeProductsRequest) (*ListRechargeProductsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRechargeProducts not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRechargeProducts not implemented") } func (UnimplementedWalletServiceServer) ConfirmGooglePayment(context.Context, *ConfirmGooglePaymentRequest) (*ConfirmGooglePaymentResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ConfirmGooglePayment not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ConfirmGooglePayment not implemented") } func (UnimplementedWalletServiceServer) ListAdminRechargeProducts(context.Context, *ListAdminRechargeProductsRequest) (*ListAdminRechargeProductsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListAdminRechargeProducts not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListAdminRechargeProducts not implemented") } func (UnimplementedWalletServiceServer) CreateRechargeProduct(context.Context, *CreateRechargeProductRequest) (*RechargeProductResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateRechargeProduct not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateRechargeProduct not implemented") } func (UnimplementedWalletServiceServer) UpdateRechargeProduct(context.Context, *UpdateRechargeProductRequest) (*RechargeProductResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateRechargeProduct not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateRechargeProduct not implemented") } func (UnimplementedWalletServiceServer) DeleteRechargeProduct(context.Context, *DeleteRechargeProductRequest) (*DeleteRechargeProductResponse, error) { - return nil, status.Error(codes.Unimplemented, "method DeleteRechargeProduct not implemented") + return nil, status.Errorf(codes.Unimplemented, "method DeleteRechargeProduct not implemented") } func (UnimplementedWalletServiceServer) GetDiamondExchangeConfig(context.Context, *GetDiamondExchangeConfigRequest) (*GetDiamondExchangeConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetDiamondExchangeConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetDiamondExchangeConfig not implemented") } func (UnimplementedWalletServiceServer) ListWalletTransactions(context.Context, *ListWalletTransactionsRequest) (*ListWalletTransactionsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListWalletTransactions not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListWalletTransactions not implemented") } func (UnimplementedWalletServiceServer) ListVipPackages(context.Context, *ListVipPackagesRequest) (*ListVipPackagesResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListVipPackages not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListVipPackages not implemented") } func (UnimplementedWalletServiceServer) GetMyVip(context.Context, *GetMyVipRequest) (*GetMyVipResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetMyVip not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetMyVip not implemented") } func (UnimplementedWalletServiceServer) PurchaseVip(context.Context, *PurchaseVipRequest) (*PurchaseVipResponse, error) { - return nil, status.Error(codes.Unimplemented, "method PurchaseVip not implemented") + return nil, status.Errorf(codes.Unimplemented, "method PurchaseVip not implemented") } func (UnimplementedWalletServiceServer) GrantVip(context.Context, *GrantVipRequest) (*GrantVipResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GrantVip not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GrantVip not implemented") } func (UnimplementedWalletServiceServer) ListAdminVipLevels(context.Context, *ListAdminVipLevelsRequest) (*ListAdminVipLevelsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListAdminVipLevels not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListAdminVipLevels not implemented") } func (UnimplementedWalletServiceServer) UpdateAdminVipLevels(context.Context, *UpdateAdminVipLevelsRequest) (*UpdateAdminVipLevelsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateAdminVipLevels not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateAdminVipLevels not implemented") } func (UnimplementedWalletServiceServer) CreditTaskReward(context.Context, *CreditTaskRewardRequest) (*CreditTaskRewardResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreditTaskReward not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreditTaskReward not implemented") } func (UnimplementedWalletServiceServer) CreditLuckyGiftReward(context.Context, *CreditLuckyGiftRewardRequest) (*CreditLuckyGiftRewardResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreditLuckyGiftReward not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreditLuckyGiftReward not implemented") } func (UnimplementedWalletServiceServer) CreditRoomTurnoverReward(context.Context, *CreditRoomTurnoverRewardRequest) (*CreditRoomTurnoverRewardResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreditRoomTurnoverReward not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreditRoomTurnoverReward not implemented") } func (UnimplementedWalletServiceServer) ApplyGameCoinChange(context.Context, *ApplyGameCoinChangeRequest) (*ApplyGameCoinChangeResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ApplyGameCoinChange not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ApplyGameCoinChange not implemented") } func (UnimplementedWalletServiceServer) GetRedPacketConfig(context.Context, *GetRedPacketConfigRequest) (*GetRedPacketConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRedPacketConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetRedPacketConfig not implemented") } func (UnimplementedWalletServiceServer) UpdateRedPacketConfig(context.Context, *UpdateRedPacketConfigRequest) (*UpdateRedPacketConfigResponse, error) { - return nil, status.Error(codes.Unimplemented, "method UpdateRedPacketConfig not implemented") + return nil, status.Errorf(codes.Unimplemented, "method UpdateRedPacketConfig not implemented") } func (UnimplementedWalletServiceServer) CreateRedPacket(context.Context, *CreateRedPacketRequest) (*CreateRedPacketResponse, error) { - return nil, status.Error(codes.Unimplemented, "method CreateRedPacket not implemented") + return nil, status.Errorf(codes.Unimplemented, "method CreateRedPacket not implemented") } func (UnimplementedWalletServiceServer) ClaimRedPacket(context.Context, *ClaimRedPacketRequest) (*ClaimRedPacketResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ClaimRedPacket not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ClaimRedPacket not implemented") } func (UnimplementedWalletServiceServer) ListRedPackets(context.Context, *ListRedPacketsRequest) (*ListRedPacketsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ListRedPackets not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ListRedPackets not implemented") } func (UnimplementedWalletServiceServer) GetRedPacket(context.Context, *GetRedPacketRequest) (*GetRedPacketResponse, error) { - return nil, status.Error(codes.Unimplemented, "method GetRedPacket not implemented") + return nil, status.Errorf(codes.Unimplemented, "method GetRedPacket not implemented") } func (UnimplementedWalletServiceServer) ExpireRedPackets(context.Context, *ExpireRedPacketsRequest) (*ExpireRedPacketsResponse, error) { - return nil, status.Error(codes.Unimplemented, "method ExpireRedPackets not implemented") + return nil, status.Errorf(codes.Unimplemented, "method ExpireRedPackets not implemented") } func (UnimplementedWalletServiceServer) RetryRedPacketRefund(context.Context, *RetryRedPacketRefundRequest) (*RetryRedPacketRefundResponse, error) { - return nil, status.Error(codes.Unimplemented, "method RetryRedPacketRefund not implemented") + return nil, status.Errorf(codes.Unimplemented, "method RetryRedPacketRefund not implemented") } func (UnimplementedWalletServiceServer) mustEmbedUnimplementedWalletServiceServer() {} func (UnimplementedWalletServiceServer) testEmbeddedByValue() {} @@ -1334,7 +1334,7 @@ type UnsafeWalletServiceServer interface { } func RegisterWalletServiceServer(s grpc.ServiceRegistrar, srv WalletServiceServer) { - // If the following call panics, it indicates UnimplementedWalletServiceServer was + // If the following call pancis, it indicates UnimplementedWalletServiceServer 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. diff --git a/server/admin/internal/modules/hostorg/service.go b/server/admin/internal/modules/hostorg/service.go index da1af390..60e9f418 100644 --- a/server/admin/internal/modules/hostorg/service.go +++ b/server/admin/internal/modules/hostorg/service.go @@ -303,10 +303,23 @@ func (s *Service) CreditCoinSellerStock(ctx context.Context, actorID int64, sell if profile == nil || profile.Status != coinSellerStatusActive || profile.MerchantAssetType != coinSellerMerchantAssetType { return nil, fmt.Errorf("target user is not an active coin seller") } + seller, err := s.userClient.GetUser(ctx, userclient.GetUserRequest{ + RequestID: requestID, + Caller: "hyapp-admin-server", + UserID: sellerUserID, + }) + if err != nil { + return nil, err + } + if seller == nil || seller.CountryID <= 0 || seller.RegionID <= 0 { + return nil, fmt.Errorf("coin seller country and region are required") + } return s.walletClient.AdminCreditCoinSellerStock(ctx, &walletv1.AdminCreditCoinSellerStockRequest{ CommandId: commandID, SellerUserId: sellerUserID, + SellerCountryId: seller.CountryID, + SellerRegionId: seller.RegionID, StockType: stockType, CoinAmount: req.CoinAmount, PaidCurrencyCode: paidCurrencyCode, diff --git a/services/gateway-service/internal/transport/http/roomapi/room_handler.go b/services/gateway-service/internal/transport/http/roomapi/room_handler.go index 3405fac5..d38acdd8 100644 --- a/services/gateway-service/internal/transport/http/roomapi/room_handler.go +++ b/services/gateway-service/internal/transport/http/roomapi/room_handler.go @@ -836,11 +836,18 @@ func (h *Handler) joinRoom(writer http.ResponseWriter, request *http.Request) { if !httpkit.Decode(writer, request, &body) { return } + actorCountryID, actorRegionID, err := h.resolveRoomActorCountryRegion(request) + if err != nil { + httpkit.WriteRPCError(writer, request, err) + return + } resp, err := h.roomClient.JoinRoom(request.Context(), &roomv1.JoinRoomRequest{ - Meta: httpkit.RoomMeta(request, body.RoomID, body.CommandID), - Role: body.Role, - Password: body.Password, + Meta: httpkit.RoomMeta(request, body.RoomID, body.CommandID), + Role: body.Role, + Password: body.Password, + ActorCountryId: actorCountryID, + ActorRegionId: actorRegionID, // 座驾快照在进房命令提交前生成;room-service 只保存快照,不回查 wallet。 EntryVehicle: h.joinRoomEntryVehicleSnapshot(request), }) @@ -1307,7 +1314,7 @@ func (h *Handler) sendGift(writer http.ResponseWriter, request *http.Request) { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") return } - senderRegionID, err := h.resolveGiftSenderRegionID(request) + senderCountryID, senderRegionID, err := h.resolveRoomActorCountryRegion(request) if err != nil { httpkit.WriteRPCError(writer, request, err) return @@ -1326,6 +1333,7 @@ func (h *Handler) sendGift(writer http.ResponseWriter, request *http.Request) { GiftId: body.GiftID, GiftCount: body.GiftCount, PoolId: body.PoolID, + SenderCountryId: senderCountryID, SenderRegionId: senderRegionID, TargetIsHost: targetIsHost, TargetHostRegionId: targetHostRegionID, @@ -1334,21 +1342,25 @@ func (h *Handler) sendGift(writer http.ResponseWriter, request *http.Request) { httpkit.Write(writer, request, resp, err) } -func (h *Handler) resolveGiftSenderRegionID(request *http.Request) (int64, error) { +func (h *Handler) resolveRoomActorCountryRegion(request *http.Request) (int64, int64, error) { if h.userProfileClient == nil { - return 0, xerr.New(xerr.Unavailable, "user service is not configured") + return 0, 0, xerr.New(xerr.Unavailable, "user service is not configured") } resp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ Meta: httpkit.UserMeta(request, ""), UserId: auth.UserIDFromContext(request.Context()), }) if err != nil { - return 0, err + return 0, 0, err } if resp.GetUser() == nil { - return 0, xerr.New(xerr.NotFound, "sender not found") + return 0, 0, xerr.New(xerr.NotFound, "user not found") } - return resp.GetUser().GetRegionId(), nil + if resp.GetUser().GetCountryId() <= 0 || resp.GetUser().GetRegionId() <= 0 { + return 0, 0, xerr.New(xerr.InvalidArgument, "user country and region are required") + } + // room-service 事件必须携带用户真实国家和区域;房间 visible_region_id 只表达房间列表归属。 + return resp.GetUser().GetCountryId(), resp.GetUser().GetRegionId(), nil } func (h *Handler) resolveGiftTargetHostScope(request *http.Request, targetUserID int64) (bool, int64, int64, error) { diff --git a/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go b/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go index d25db04f..3e99358b 100644 --- a/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go +++ b/services/gateway-service/internal/transport/http/walletapi/wallet_handler.go @@ -133,20 +133,21 @@ func (h *Handler) transferCoinFromSeller(writer http.ResponseWriter, request *ht if !ok { return } - sellerRegionID, targetRegionID, ok := h.coinSellerTransferRegions(writer, request, sellerUserID, targetUserID) + sellerRegionID, targetRegionID, targetCountryID, ok := h.coinSellerTransferRegions(writer, request, sellerUserID, targetUserID) if !ok { return } resp, err := h.walletClient.TransferCoinFromSeller(request.Context(), &walletv1.TransferCoinFromSellerRequest{ - CommandId: commandID, - SellerUserId: sellerUserID, - TargetUserId: targetUserID, - SellerRegionId: sellerRegionID, - TargetRegionId: targetRegionID, - Amount: body.Amount, - Reason: reason, - AppCode: appcode.FromContext(request.Context()), + CommandId: commandID, + SellerUserId: sellerUserID, + TargetUserId: targetUserID, + SellerRegionId: sellerRegionID, + TargetRegionId: targetRegionID, + TargetCountryId: targetCountryID, + Amount: body.Amount, + Reason: reason, + AppCode: appcode.FromContext(request.Context()), }) if err != nil { httpkit.WriteRPCError(writer, request, err) @@ -184,22 +185,24 @@ func (h *Handler) resolveCoinSellerTransferTargetUserID(writer http.ResponseWrit return targetUserID, true } -func (h *Handler) coinSellerTransferRegions(writer http.ResponseWriter, request *http.Request, sellerUserID int64, targetUserID int64) (int64, int64, bool) { +func (h *Handler) coinSellerTransferRegions(writer http.ResponseWriter, request *http.Request, sellerUserID int64, targetUserID int64) (int64, int64, int64, bool) { sellerResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ Meta: httpkit.UserMeta(request, ""), UserId: sellerUserID, }) if err != nil { httpkit.WriteRPCError(writer, request, err) - return 0, 0, false + return 0, 0, 0, false } - sellerRegionID := sellerResp.GetUser().GetRegionId() + seller := sellerResp.GetUser() + sellerCountryID := seller.GetCountryId() + sellerRegionID := seller.GetRegionId() if sellerUserID == targetUserID { - if sellerRegionID <= 0 { + if sellerCountryID <= 0 || sellerRegionID <= 0 { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") - return 0, 0, false + return 0, 0, 0, false } - return sellerRegionID, sellerRegionID, true + return sellerRegionID, sellerRegionID, sellerCountryID, true } targetResp, err := h.userProfileClient.GetUser(request.Context(), &userv1.GetUserRequest{ Meta: httpkit.UserMeta(request, ""), @@ -207,19 +210,21 @@ func (h *Handler) coinSellerTransferRegions(writer http.ResponseWriter, request }) if err != nil { httpkit.WriteRPCError(writer, request, err) - return 0, 0, false + return 0, 0, 0, false } - targetRegionID := targetResp.GetUser().GetRegionId() - if sellerRegionID <= 0 || targetRegionID <= 0 { + target := targetResp.GetUser() + targetCountryID := target.GetCountryId() + targetRegionID := target.GetRegionId() + if sellerRegionID <= 0 || targetCountryID <= 0 || targetRegionID <= 0 { httpkit.WriteError(writer, request, http.StatusBadRequest, httpkit.CodeInvalidArgument, "invalid argument") - return 0, 0, false + return 0, 0, 0, false } if sellerRegionID != targetRegionID { // 充值政策当前按单一区域生效;跨区转账必须先设计明确的结算区域,不能静默套用任意一方政策。 httpkit.WriteError(writer, request, http.StatusConflict, string(xerr.Conflict), "conflict") - return 0, 0, false + return 0, 0, 0, false } - return sellerRegionID, targetRegionID, true + return sellerRegionID, targetRegionID, targetCountryID, true } func walletAssetTypes(request *http.Request) []string { diff --git a/services/room-service/internal/room/command/command.go b/services/room-service/internal/room/command/command.go index 328c78b7..55213078 100644 --- a/services/room-service/internal/room/command/command.go +++ b/services/room-service/internal/room/command/command.go @@ -121,6 +121,10 @@ type JoinRoom struct { Base // Role 是用户在房间内的轻量角色,默认 audience。 Role string `json:"role"` + // ActorCountryID 是 gateway 从 user-service 注入的真实国家,用于统计进房活跃国家维度。 + ActorCountryID int64 `json:"actor_country_id,omitempty"` + // ActorRegionID 是 gateway 从 user-service 注入的真实区域;房间 visible_region_id 不能代替用户国家。 + ActorRegionID int64 `json:"actor_region_id,omitempty"` // EntryVehicle 是 gateway 在进房时解析出的当前有效佩戴座驾快照,用于进房 IM。 EntryVehicle EntryVehicleSnapshot `json:"entry_vehicle,omitempty"` } @@ -396,6 +400,8 @@ type SendGift struct { GiftCount int32 `json:"gift_count"` // SenderRegionID 是送礼用户所属区域,由 gateway 从 user-service 注入。 SenderRegionID int64 `json:"sender_region_id,omitempty"` + // SenderCountryID 是送礼用户所属国家,由 gateway 从 user-service 注入,统计服务不能用房间区域反推。 + SenderCountryID int64 `json:"sender_country_id,omitempty"` // TargetIsHost 是 gateway 从 user-service active host profile 注入的工资入账开关。 TargetIsHost bool `json:"target_is_host,omitempty"` // TargetHostRegionID 是工资政策匹配区域;room-service 不自行推导主播身份或区域。 diff --git a/services/room-service/internal/room/service/gift.go b/services/room-service/internal/room/service/gift.go index 7cdb77aa..3bfd1907 100644 --- a/services/room-service/internal/room/service/gift.go +++ b/services/room-service/internal/room/service/gift.go @@ -26,14 +26,15 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r ctx = contextFromMeta(ctx, req.GetMeta()) // SendGift 的账务不在 room-service 内结算,但房间表现、热度和榜单由 Room Cell 同步更新。 cmd := command.SendGift{ - Base: baseFromMeta(req.GetMeta()), - TargetType: normalizeGiftTargetType(req.GetTargetType()), - TargetUserIDs: normalizeGiftTargetUserIDs(req.GetTargetUserId(), req.GetTargetUserIds()), - GiftID: req.GetGiftId(), - PoolID: strings.TrimSpace(req.GetPoolId()), - GiftCount: req.GetGiftCount(), - SenderRegionID: req.GetSenderRegionId(), - TargetIsHost: req.GetTargetIsHost(), + Base: baseFromMeta(req.GetMeta()), + TargetType: normalizeGiftTargetType(req.GetTargetType()), + TargetUserIDs: normalizeGiftTargetUserIDs(req.GetTargetUserId(), req.GetTargetUserIds()), + GiftID: req.GetGiftId(), + PoolID: strings.TrimSpace(req.GetPoolId()), + GiftCount: req.GetGiftCount(), + SenderCountryID: req.GetSenderCountryId(), + SenderRegionID: req.GetSenderRegionId(), + TargetIsHost: req.GetTargetIsHost(), // 工资区域由 gateway 从 user-service host profile 注入;房间 visible_region_id 只用于房间/礼物可见性。 TargetHostRegionID: req.GetTargetHostRegionId(), TargetAgencyOwnerUserID: req.GetTargetAgencyOwnerUserId(), @@ -175,6 +176,8 @@ func (s *Service) SendGift(ctx context.Context, req *roomv1.SendGiftRequest) (*r CoinSpent: targetBilling.Billing.GetCoinSpent(), BillingReceiptId: targetBilling.Billing.GetBillingReceiptId(), VisibleRegionId: roomMeta.VisibleRegionID, + CountryId: cmd.SenderCountryID, + RegionId: firstNonZeroInt64(cmd.SenderRegionID, roomMeta.VisibleRegionID), CommandId: targetBilling.CommandID, }) if err != nil { diff --git a/services/room-service/internal/room/service/helpers.go b/services/room-service/internal/room/service/helpers.go index 8e0dc79b..4bd11a5b 100644 --- a/services/room-service/internal/room/service/helpers.go +++ b/services/room-service/internal/room/service/helpers.go @@ -98,6 +98,15 @@ func runtimeRoomRef(key string) loadedRoomRef { return loadedRoomRef{AppCode: "", RoomID: key} } +func firstNonZeroInt64(values ...int64) int64 { + for _, value := range values { + if value != 0 { + return value + } + } + return 0 +} + func commandResult(applied bool, roomVersion int64, now time.Time) *roomv1.CommandResult { // 所有命令响应统一带 applied、room_version 和服务端时间,便于客户端处理幂等结果。 return &roomv1.CommandResult{ diff --git a/services/room-service/internal/room/service/presence.go b/services/room-service/internal/room/service/presence.go index dead1003..d8115bc1 100644 --- a/services/room-service/internal/room/service/presence.go +++ b/services/room-service/internal/room/service/presence.go @@ -25,8 +25,10 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r password := strings.TrimSpace(req.GetPassword()) // JoinRoom 只维护 room-service presence,不创建任何本地长连接订阅。 cmd := command.JoinRoom{ - Base: baseFromMeta(req.GetMeta()), - Role: req.GetRole(), + Base: baseFromMeta(req.GetMeta()), + Role: req.GetRole(), + ActorCountryID: req.GetActorCountryId(), + ActorRegionID: req.GetActorRegionId(), // entry_vehicle 来自 gateway 入房瞬间的 wallet 快照,写入 command log 后可稳定重放。 EntryVehicle: entryVehicleSnapshotFromProto(req.GetEntryVehicle()), } @@ -78,6 +80,8 @@ func (s *Service) JoinRoom(ctx context.Context, req *roomv1.JoinRoomRequest) (*r UserId: cmd.ActorUserID(), Role: cmd.Role, VisibleRegionId: current.VisibleRegionID, + CountryId: cmd.ActorCountryID, + RegionId: firstNonZeroInt64(cmd.ActorRegionID, current.VisibleRegionID), // outbox 事件必须带座驾快照;否则异步补偿投递 IM 时会丢失入场座驾。 EntryVehicle: eventEntryVehicleFromCommand(cmd.EntryVehicle), }) diff --git a/services/statistics-service/cmd/backfill-last7/main.go b/services/statistics-service/cmd/backfill-last7/main.go new file mode 100644 index 00000000..784a9c6c --- /dev/null +++ b/services/statistics-service/cmd/backfill-last7/main.go @@ -0,0 +1,647 @@ +package main + +import ( + "context" + "database/sql" + "flag" + "fmt" + "log" + "os" + "sort" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" + "hyapp/pkg/appcode" +) + +type countryRegion struct { + countryID int64 + regionID int64 +} + +type appDayKey struct { + day string + countryID int64 + regionID int64 +} + +type appDayAgg struct { + newUsers int64 + activeUsers int64 + paidUsers int64 + rechargeUSDMinor int64 + newUserRechargeUSDMinor int64 + coinSellerRechargeUSDMinor int64 + googleRechargeUSDMinor int64 + coinSellerTransferCoin int64 +} + +type userRegistrationRow struct { + userID int64 + registeredDay string + dim countryRegion + createdAtMS int64 +} + +type payerRow struct { + day string + userID int64 + dim countryRegion + firstMS int64 +} + +type activeRow struct { + day string + userID int64 + dim countryRegion + firstMS int64 +} + +type rebuildState struct { + appDays map[appDayKey]*appDayAgg + registrations []userRegistrationRow + registeredByUserDay map[string]struct{} + payersByKey map[string]payerRow + activeByKey map[string]activeRow + userIDs map[int64]struct{} + userDims map[int64]countryRegion +} + +func main() { + ctx := context.Background() + var ( + appFlag = flag.String("app", envDefault("APP_CODE", "lalu"), "app_code to backfill") + tzFlag = flag.String("timezone", envDefault("BACKFILL_TIMEZONE", "UTC"), "day boundary timezone, e.g. UTC or Asia/Shanghai") + startFlag = flag.String("start-day", os.Getenv("START_DAY"), "inclusive yyyy-mm-dd in timezone; defaults to last 7 days") + endFlag = flag.String("end-day", os.Getenv("END_DAY"), "inclusive yyyy-mm-dd in timezone; defaults to today") + statsDSNFlag = flag.String("statistics-dsn", firstNonEmpty(os.Getenv("STATISTICS_MYSQL_DSN"), os.Getenv("MYSQL_DSN")), "statistics mysql dsn") + userDSNFlag = flag.String("user-dsn", os.Getenv("USER_MYSQL_DSN"), "user-service mysql dsn") + walletDSNFlag = flag.String("wallet-dsn", os.Getenv("WALLET_MYSQL_DSN"), "wallet-service mysql dsn") + applyFlag = flag.Bool("apply", envBool("APPLY"), "apply replacement; default dry-run") + ) + flag.Parse() + + if strings.TrimSpace(*statsDSNFlag) == "" || strings.TrimSpace(*userDSNFlag) == "" || strings.TrimSpace(*walletDSNFlag) == "" { + log.Fatal("statistics-dsn, user-dsn and wallet-dsn are required") + } + loc, err := time.LoadLocation(strings.TrimSpace(*tzFlag)) + if err != nil { + log.Fatalf("load timezone: %v", err) + } + startDay, endDay, windowStartMS, windowEndMS, err := resolveWindow(*startFlag, *endFlag, loc) + if err != nil { + log.Fatal(err) + } + app := appcode.Normalize(*appFlag) + + statsDB := mustOpen(ctx, *statsDSNFlag) + defer statsDB.Close() + userDB := mustOpen(ctx, *userDSNFlag) + defer userDB.Close() + walletDB := mustOpen(ctx, *walletDSNFlag) + defer walletDB.Close() + + state := &rebuildState{ + appDays: map[appDayKey]*appDayAgg{}, + registeredByUserDay: map[string]struct{}{}, + payersByKey: map[string]payerRow{}, + activeByKey: map[string]activeRow{}, + userIDs: map[int64]struct{}{}, + userDims: map[int64]countryRegion{}, + } + // 第一阶段只收集窗口内会参与重算的 user_id,后续统一批量加载用户国家和区域,避免按充值/活跃记录逐条访问 user-service 数据库。 + if err := collectRegistrationUsers(ctx, userDB, state, app, windowStartMS, windowEndMS); err != nil { + log.Fatalf("collect registrations: %v", err) + } + if err := collectActiveUserIDs(ctx, statsDB, state, app, startDay, endDay); err != nil { + log.Fatalf("collect active ids: %v", err) + } + if err := collectRechargeUserIDs(ctx, walletDB, state, app, windowStartMS, windowEndMS); err != nil { + log.Fatalf("collect recharge ids: %v", err) + } + if err := loadUserDims(ctx, userDB, state, app); err != nil { + log.Fatalf("load user dims: %v", err) + } + if err := rebuildRegistrations(ctx, userDB, state, app, windowStartMS, windowEndMS, loc); err != nil { + log.Fatalf("rebuild registrations: %v", err) + } + if err := rebuildActive(ctx, statsDB, state, app, startDay, endDay); err != nil { + log.Fatalf("rebuild active: %v", err) + } + if err := rebuildWalletRecharge(ctx, walletDB, state, app, windowStartMS, windowEndMS, loc); err != nil { + log.Fatalf("rebuild wallet recharge: %v", err) + } + if err := rebuildCoinSellerStock(ctx, walletDB, state, app, windowStartMS, windowEndMS, loc); err != nil { + log.Fatalf("rebuild coin seller stock: %v", err) + } + + if err := stageAndMaybeApply(ctx, statsDB, state, app, startDay, endDay, *applyFlag); err != nil { + log.Fatalf("stage/apply: %v", err) + } + mode := "dry-run" + if *applyFlag { + mode = "applied" + } + fmt.Printf("%s app=%s timezone=%s window=%s..%s app_day_rows=%d registrations=%d active=%d payers=%d\n", + mode, app, loc.String(), startDay, endDay, len(state.appDays), len(state.registrations), len(state.activeByKey), len(state.payersByKey)) +} + +func envDefault(key string, fallback string) string { + if value := strings.TrimSpace(os.Getenv(key)); value != "" { + return value + } + return fallback +} + +func envBool(key string) bool { + switch strings.ToLower(strings.TrimSpace(os.Getenv(key))) { + case "1", "true", "yes", "y": + return true + default: + return false + } +} + +func firstNonEmpty(values ...string) string { + for _, value := range values { + if strings.TrimSpace(value) != "" { + return strings.TrimSpace(value) + } + } + return "" +} + +func mustOpen(ctx context.Context, dsn string) *sql.DB { + db, err := sql.Open("mysql", strings.TrimSpace(dsn)) + if err != nil { + log.Fatal(err) + } + if err := db.PingContext(ctx); err != nil { + log.Fatal(err) + } + return db +} + +func resolveWindow(rawStart, rawEnd string, loc *time.Location) (string, string, int64, int64, error) { + now := time.Now().In(loc) + endDayTime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc) + startDayTime := endDayTime.AddDate(0, 0, -6) + var err error + if strings.TrimSpace(rawEnd) != "" { + endDayTime, err = parseDay(rawEnd, loc) + if err != nil { + return "", "", 0, 0, err + } + } + if strings.TrimSpace(rawStart) != "" { + startDayTime, err = parseDay(rawStart, loc) + if err != nil { + return "", "", 0, 0, err + } + } + if startDayTime.After(endDayTime) { + return "", "", 0, 0, fmt.Errorf("start-day must not be after end-day") + } + windowEnd := endDayTime.AddDate(0, 0, 1) + return formatDay(startDayTime), formatDay(endDayTime), startDayTime.UTC().UnixMilli(), windowEnd.UTC().UnixMilli(), nil +} + +func parseDay(value string, loc *time.Location) (time.Time, error) { + parsed, err := time.ParseInLocation("2006-01-02", strings.TrimSpace(value), loc) + if err != nil { + return time.Time{}, err + } + return time.Date(parsed.Year(), parsed.Month(), parsed.Day(), 0, 0, 0, 0, loc), nil +} + +func dayFromMS(ms int64, loc *time.Location) string { + return formatDay(time.UnixMilli(ms).In(loc)) +} + +func formatDay(value time.Time) string { + return value.Format("2006-01-02") +} + +func collectRegistrationUsers(ctx context.Context, db *sql.DB, state *rebuildState, app string, startMS, endMS int64) error { + rows, err := db.QueryContext(ctx, ` + SELECT u.user_id + FROM users u + WHERE u.app_code = ? AND u.created_at_ms >= ? AND u.created_at_ms < ?`, + app, startMS, endMS) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID int64 + if err := rows.Scan(&userID); err != nil { + return err + } + state.userIDs[userID] = struct{}{} + } + return rows.Err() +} + +func collectActiveUserIDs(ctx context.Context, db *sql.DB, state *rebuildState, app, startDay, endDay string) error { + rows, err := db.QueryContext(ctx, ` + SELECT DISTINCT user_id + FROM stat_user_day_activity + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`, + app, startDay, endDay) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID int64 + if err := rows.Scan(&userID); err != nil { + return err + } + state.userIDs[userID] = struct{}{} + } + return rows.Err() +} + +func collectRechargeUserIDs(ctx context.Context, db *sql.DB, state *rebuildState, app string, startMS, endMS int64) error { + for _, query := range []string{ + `SELECT DISTINCT user_id FROM wallet_recharge_records WHERE app_code = ? AND created_at_ms >= ? AND created_at_ms < ?`, + `SELECT DISTINCT seller_user_id FROM coin_seller_stock_records WHERE app_code = ? AND counts_as_seller_recharge = 1 AND created_at_ms >= ? AND created_at_ms < ?`, + } { + rows, err := db.QueryContext(ctx, query, app, startMS, endMS) + if err != nil { + return err + } + for rows.Next() { + var userID int64 + if err := rows.Scan(&userID); err != nil { + rows.Close() + return err + } + state.userIDs[userID] = struct{}{} + } + if err := rows.Close(); err != nil { + return err + } + } + return nil +} + +func loadUserDims(ctx context.Context, db *sql.DB, state *rebuildState, app string) error { + userIDs := make([]int64, 0, len(state.userIDs)) + for userID := range state.userIDs { + userIDs = append(userIDs, userID) + } + sort.Slice(userIDs, func(i, j int) bool { return userIDs[i] < userIDs[j] }) + for start := 0; start < len(userIDs); start += 500 { + end := start + 500 + if end > len(userIDs) { + end = len(userIDs) + } + placeholders := strings.TrimRight(strings.Repeat("?,", end-start), ",") + args := []any{app} + for _, userID := range userIDs[start:end] { + args = append(args, userID) + } + rows, err := db.QueryContext(ctx, ` + SELECT u.user_id, COALESCE(c.country_id, 0), COALESCE(u.region_id, 0) + FROM users u + LEFT JOIN countries c ON c.app_code = u.app_code AND c.country_code = u.country + WHERE u.app_code = ? AND u.user_id IN (`+placeholders+`)`, args...) + if err != nil { + return err + } + for rows.Next() { + var userID int64 + var dim countryRegion + if err := rows.Scan(&userID, &dim.countryID, &dim.regionID); err != nil { + rows.Close() + return err + } + state.userDims[userID] = dim + } + if err := rows.Close(); err != nil { + return err + } + } + return nil +} + +func rebuildRegistrations(ctx context.Context, db *sql.DB, state *rebuildState, app string, startMS, endMS int64, loc *time.Location) error { + // 注册国家以 users.country 映射出的真实 country_id 为准;region_id 只作为独立维度写入,不能再兜底成国家。 + rows, err := db.QueryContext(ctx, ` + SELECT u.user_id, COALESCE(c.country_id, 0), COALESCE(u.region_id, 0), u.created_at_ms + FROM users u + LEFT JOIN countries c ON c.app_code = u.app_code AND c.country_code = u.country + WHERE u.app_code = ? AND u.created_at_ms >= ? AND u.created_at_ms < ?`, + app, startMS, endMS) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var row userRegistrationRow + if err := rows.Scan(&row.userID, &row.dim.countryID, &row.dim.regionID, &row.createdAtMS); err != nil { + return err + } + row.registeredDay = dayFromMS(row.createdAtMS, loc) + state.registrations = append(state.registrations, row) + state.registeredByUserDay[userDayKey(row.registeredDay, row.userID)] = struct{}{} + agg := state.ensureAgg(row.registeredDay, row.dim) + agg.newUsers++ + } + return rows.Err() +} + +func rebuildActive(ctx context.Context, db *sql.DB, state *rebuildState, app, startDay, endDay string) error { + // 活跃的原始房间事件已经被实时消费进 stat_user_day_activity;离线回填只重刷该表的国家/区域快照,避免在大窗口内扫描房间流水。 + rows, err := db.QueryContext(ctx, ` + SELECT stat_day, user_id, MIN(first_active_at_ms) + FROM stat_user_day_activity + WHERE app_code = ? AND stat_day BETWEEN ? AND ? + GROUP BY stat_day, user_id`, + app, startDay, endDay) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var day string + var userID, firstMS int64 + if err := rows.Scan(&day, &userID, &firstMS); err != nil { + return err + } + dim := state.userDims[userID] + key := fmt.Sprintf("%s:%d", day, userID) + if _, exists := state.activeByKey[key]; exists { + continue + } + state.activeByKey[key] = activeRow{day: day, userID: userID, dim: dim, firstMS: firstMS} + state.ensureAgg(day, dim).activeUsers++ + } + return rows.Err() +} + +func rebuildWalletRecharge(ctx context.Context, db *sql.DB, state *rebuildState, app string, startMS, endMS int64, loc *time.Location) error { + // wallet_recharge_records 是到账事实表;Google 也会写入该表,payment_orders 只是 provider 审计,不能在回填里再扫一次导致双算。 + // 币商向用户转账只代表金币充值用户,不产生用户 USDT 充值;Google Play 则按记录里的 usd_minor_amount 计入用户充值。 + rows, err := db.QueryContext(ctx, ` + SELECT rr.user_id, rr.recharge_sequence, rr.coin_amount, rr.usd_minor_amount, rr.created_at_ms, wt.biz_type + FROM wallet_recharge_records rr + JOIN wallet_transactions wt ON wt.app_code = rr.app_code AND wt.transaction_id = rr.transaction_id + WHERE rr.app_code = ? AND rr.created_at_ms >= ? AND rr.created_at_ms < ?`, + app, startMS, endMS) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var userID, sequence, coinAmount, usdMinor, createdAtMS int64 + var bizType string + if err := rows.Scan(&userID, &sequence, &coinAmount, &usdMinor, &createdAtMS, &bizType); err != nil { + return err + } + day := dayFromMS(createdAtMS, loc) + dim := state.userDims[userID] + state.addPayer(day, userID, dim, createdAtMS) + agg := state.ensureAgg(day, dim) + switch strings.ToLower(strings.TrimSpace(bizType)) { + case "coin_seller_transfer": + agg.coinSellerTransferCoin += coinAmount + case "google_play_recharge": + agg.rechargeUSDMinor += usdMinor + agg.googleRechargeUSDMinor += usdMinor + default: + if usdMinor > 0 { + agg.rechargeUSDMinor += usdMinor + } + } + if sequence == 1 && usdMinor > 0 { + agg.newUserRechargeUSDMinor += usdMinor + } + } + return rows.Err() +} + +func rebuildCoinSellerStock(ctx context.Context, db *sql.DB, state *rebuildState, app string, startMS, endMS int64, loc *time.Location) error { + // 币商进货是平台收到的 USDT 充值,按 seller 的国家/区域进入总充值,但不写入用户金币转账金额。 + rows, err := db.QueryContext(ctx, ` + SELECT seller_user_id, paid_amount_micro, created_at_ms + FROM coin_seller_stock_records + WHERE app_code = ? AND counts_as_seller_recharge = 1 AND paid_amount_micro > 0 AND created_at_ms >= ? AND created_at_ms < ?`, + app, startMS, endMS) + if err != nil { + return err + } + defer rows.Close() + for rows.Next() { + var sellerUserID, amountMicro, createdAtMS int64 + if err := rows.Scan(&sellerUserID, &amountMicro, &createdAtMS); err != nil { + return err + } + usdMinor := amountMicro / 10_000 + day := dayFromMS(createdAtMS, loc) + dim := state.userDims[sellerUserID] + agg := state.ensureAgg(day, dim) + agg.rechargeUSDMinor += usdMinor + agg.coinSellerRechargeUSDMinor += usdMinor + } + return rows.Err() +} + +func (s *rebuildState) ensureAgg(day string, dim countryRegion) *appDayAgg { + key := appDayKey{day: day, countryID: dim.countryID, regionID: dim.regionID} + if s.appDays[key] == nil { + s.appDays[key] = &appDayAgg{} + } + return s.appDays[key] +} + +func (s *rebuildState) addPayer(day string, userID int64, dim countryRegion, firstMS int64) { + key := fmt.Sprintf("%s:%d", day, userID) + if existing, exists := s.payersByKey[key]; exists && existing.firstMS <= firstMS { + return + } + if _, exists := s.payersByKey[key]; !exists { + s.ensureAgg(day, dim).paidUsers++ + } + s.payersByKey[key] = payerRow{day: day, userID: userID, dim: dim, firstMS: firstMS} +} + +func (s *rebuildState) userRegisteredOn(userID int64, day string) bool { + _, ok := s.registeredByUserDay[userDayKey(day, userID)] + return ok +} + +func userDayKey(day string, userID int64) string { + return fmt.Sprintf("%s:%d", day, userID) +} + +func stageAndMaybeApply(ctx context.Context, db *sql.DB, state *rebuildState, app, startDay, endDay string, apply bool) error { + conn, err := db.Conn(ctx) + if err != nil { + return err + } + defer conn.Close() + tx, err := conn.BeginTx(ctx, nil) + if err != nil { + return err + } + defer tx.Rollback() + if err := createTempTables(ctx, tx); err != nil { + return err + } + if err := insertStageRows(ctx, tx, state, app); err != nil { + return err + } + if err := validateStage(ctx, tx); err != nil { + return err + } + if !apply { + return tx.Rollback() + } + nowMS := time.Now().UTC().UnixMilli() + // 本 job 只覆盖能从当前源表确定的近 7 天列;礼物、游戏、MifaPay 等不在本次源表范围内的指标保留原值,避免修国家维度时误删其他业务数据。 + if _, err := tx.ExecContext(ctx, ` + UPDATE stat_app_day_country + SET new_users = 0, active_users = 0, paid_users = 0, + recharge_usd_minor = 0, new_user_recharge_usd_minor = 0, + coin_seller_recharge_usd_minor = 0, + google_recharge_usd_minor = 0, coin_seller_transfer_coin = 0, + updated_at_ms = ? + WHERE app_code = ? AND stat_day BETWEEN ? AND ?`, + nowMS, app, startDay, endDay); err != nil { + return err + } + for _, statement := range []string{ + `DELETE FROM stat_user_registration WHERE app_code = ? AND registered_day BETWEEN ? AND ?`, + `DELETE FROM stat_user_day_activity WHERE app_code = ? AND stat_day BETWEEN ? AND ?`, + `DELETE FROM stat_recharge_day_payers WHERE app_code = ? AND stat_day BETWEEN ? AND ?`, + } { + if _, err := tx.ExecContext(ctx, statement, app, startDay, endDay); err != nil { + return err + } + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_app_day_country ( + app_code, stat_day, country_id, region_id, new_users, active_users, paid_users, + recharge_usd_minor, new_user_recharge_usd_minor, coin_seller_recharge_usd_minor, + google_recharge_usd_minor, coin_seller_transfer_coin, updated_at_ms + ) + SELECT app_code, stat_day, country_id, region_id, new_users, active_users, paid_users, + recharge_usd_minor, new_user_recharge_usd_minor, coin_seller_recharge_usd_minor, + google_recharge_usd_minor, coin_seller_transfer_coin, ? + FROM tmp_stat_backfill_app_day + ON DUPLICATE KEY UPDATE + new_users = VALUES(new_users), active_users = VALUES(active_users), paid_users = VALUES(paid_users), + recharge_usd_minor = VALUES(recharge_usd_minor), + new_user_recharge_usd_minor = VALUES(new_user_recharge_usd_minor), + coin_seller_recharge_usd_minor = VALUES(coin_seller_recharge_usd_minor), + google_recharge_usd_minor = VALUES(google_recharge_usd_minor), + coin_seller_transfer_coin = VALUES(coin_seller_transfer_coin), + updated_at_ms = VALUES(updated_at_ms)`, nowMS); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_user_registration (app_code, user_id, registered_day, country_id, region_id, registered_at_ms) + SELECT app_code, user_id, registered_day, country_id, region_id, registered_at_ms FROM tmp_stat_backfill_registration`); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_user_day_activity (app_code, stat_day, country_id, region_id, user_id, first_active_at_ms) + SELECT app_code, stat_day, country_id, region_id, user_id, first_active_at_ms FROM tmp_stat_backfill_active`); err != nil { + return err + } + if _, err := tx.ExecContext(ctx, ` + INSERT INTO stat_recharge_day_payers (app_code, stat_day, country_id, region_id, user_id, first_paid_at_ms) + SELECT app_code, stat_day, country_id, region_id, user_id, first_paid_at_ms FROM tmp_stat_backfill_payers`); err != nil { + return err + } + return tx.Commit() +} + +func createTempTables(ctx context.Context, tx *sql.Tx) error { + statements := []string{ + `CREATE TEMPORARY TABLE tmp_stat_backfill_app_day ( + app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL, region_id BIGINT NOT NULL, + new_users BIGINT NOT NULL, active_users BIGINT NOT NULL, paid_users BIGINT NOT NULL, + recharge_usd_minor BIGINT NOT NULL, new_user_recharge_usd_minor BIGINT NOT NULL, + coin_seller_recharge_usd_minor BIGINT NOT NULL, google_recharge_usd_minor BIGINT NOT NULL, + coin_seller_transfer_coin BIGINT NOT NULL, + PRIMARY KEY(app_code, stat_day, country_id, region_id) + )`, + `CREATE TEMPORARY TABLE tmp_stat_backfill_registration ( + app_code VARCHAR(32) NOT NULL, user_id BIGINT NOT NULL, registered_day DATE NOT NULL, + country_id BIGINT NOT NULL, region_id BIGINT NOT NULL, registered_at_ms BIGINT NOT NULL, + PRIMARY KEY(app_code, user_id) + )`, + `CREATE TEMPORARY TABLE tmp_stat_backfill_active ( + app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL, + region_id BIGINT NOT NULL, user_id BIGINT NOT NULL, first_active_at_ms BIGINT NOT NULL, + PRIMARY KEY(app_code, stat_day, user_id) + )`, + `CREATE TEMPORARY TABLE tmp_stat_backfill_payers ( + app_code VARCHAR(32) NOT NULL, stat_day DATE NOT NULL, country_id BIGINT NOT NULL, + region_id BIGINT NOT NULL, user_id BIGINT NOT NULL, first_paid_at_ms BIGINT NOT NULL, + PRIMARY KEY(app_code, stat_day, user_id) + )`, + } + for _, statement := range statements { + if _, err := tx.ExecContext(ctx, statement); err != nil { + return err + } + } + return nil +} + +func insertStageRows(ctx context.Context, tx *sql.Tx, state *rebuildState, app string) error { + for key, agg := range state.appDays { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO tmp_stat_backfill_app_day ( + app_code, stat_day, country_id, region_id, new_users, active_users, paid_users, + recharge_usd_minor, new_user_recharge_usd_minor, coin_seller_recharge_usd_minor, + google_recharge_usd_minor, coin_seller_transfer_coin + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + app, key.day, key.countryID, key.regionID, agg.newUsers, agg.activeUsers, agg.paidUsers, + agg.rechargeUSDMinor, agg.newUserRechargeUSDMinor, agg.coinSellerRechargeUSDMinor, + agg.googleRechargeUSDMinor, agg.coinSellerTransferCoin); err != nil { + return err + } + } + for _, row := range state.registrations { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO tmp_stat_backfill_registration (app_code, user_id, registered_day, country_id, region_id, registered_at_ms) + VALUES (?, ?, ?, ?, ?, ?)`, app, row.userID, row.registeredDay, row.dim.countryID, row.dim.regionID, row.createdAtMS); err != nil { + return err + } + } + for _, row := range state.activeByKey { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO tmp_stat_backfill_active (app_code, stat_day, country_id, region_id, user_id, first_active_at_ms) + VALUES (?, ?, ?, ?, ?, ?)`, app, row.day, row.dim.countryID, row.dim.regionID, row.userID, row.firstMS); err != nil { + return err + } + } + for _, row := range state.payersByKey { + if _, err := tx.ExecContext(ctx, ` + INSERT INTO tmp_stat_backfill_payers (app_code, stat_day, country_id, region_id, user_id, first_paid_at_ms) + VALUES (?, ?, ?, ?, ?, ?)`, app, row.day, row.dim.countryID, row.dim.regionID, row.userID, row.firstMS); err != nil { + return err + } + } + return nil +} + +func validateStage(ctx context.Context, tx *sql.Tx) error { + var negativeCount int64 + if err := tx.QueryRowContext(ctx, ` + SELECT COUNT(*) + FROM tmp_stat_backfill_app_day + WHERE new_users < 0 OR active_users < 0 OR paid_users < 0 OR recharge_usd_minor < 0 OR coin_seller_transfer_coin < 0`).Scan(&negativeCount); err != nil { + return err + } + if negativeCount > 0 { + return fmt.Errorf("stage contains negative counters") + } + return nil +} diff --git a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql index f8a1ac2c..b4b707e6 100644 --- a/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql +++ b/services/statistics-service/deploy/mysql/initdb/001_statistics_service.sql @@ -40,7 +40,7 @@ CREATE TABLE IF NOT EXISTS stat_app_day_country ( game_payout BIGINT NOT NULL DEFAULT 0 COMMENT '游戏返奖', game_refund BIGINT NOT NULL DEFAULT 0 COMMENT '游戏退款', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', - PRIMARY KEY (app_code, stat_day, country_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id), KEY idx_stat_app_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='App 国家日统计聚合表'; @@ -101,7 +101,7 @@ CREATE TABLE IF NOT EXISTS stat_lucky_gift_pool_day_country ( turnover_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物流水金币', payout_coin BIGINT NOT NULL DEFAULT 0 COMMENT '奖池幸运礼物返奖金币', updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms', - PRIMARY KEY (app_code, stat_day, country_id, pool_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id, pool_id), KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id), KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='幸运礼物奖池国家日统计聚合表'; @@ -118,7 +118,7 @@ CREATE TABLE IF NOT EXISTS stat_game_day_country ( refund_coin BIGINT NOT NULL DEFAULT 0, player_count BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id, platform_code, game_id), KEY idx_stat_game_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游戏国家日统计聚合表'; diff --git a/services/statistics-service/internal/app/app.go b/services/statistics-service/internal/app/app.go index 336c5718..83a5f2c3 100644 --- a/services/statistics-service/internal/app/app.go +++ b/services/statistics-service/internal/app/app.go @@ -365,8 +365,8 @@ func roomGiftEvent(body []byte) (mysqlstorage.RoomGiftEvent, bool, error) { AppCode: envelope.GetAppCode(), EventID: envelope.GetEventId(), SenderUserID: gift.GetSenderUserId(), - CountryID: 0, - VisibleRegionID: gift.GetVisibleRegionId(), + CountryID: gift.GetCountryId(), + VisibleRegionID: firstNonZeroInt64(gift.GetRegionId(), gift.GetVisibleRegionId()), GiftValue: gift.GetGiftValue(), CoinSpent: roomGiftCoinSpent(&gift), PoolID: gift.GetPoolId(), @@ -402,8 +402,8 @@ func roomJoinActiveEvent(body []byte) (mysqlstorage.UserActiveEvent, bool, error EventID: envelope.GetEventId(), EventType: envelope.GetEventType(), UserID: joined.GetUserId(), - CountryID: 0, - RegionID: joined.GetVisibleRegionId(), + CountryID: joined.GetCountryId(), + RegionID: firstNonZeroInt64(joined.GetRegionId(), joined.GetVisibleRegionId()), OccurredAtMS: envelope.GetOccurredAtMs(), }, true, nil } diff --git a/services/statistics-service/internal/storage/mysql/query.go b/services/statistics-service/internal/storage/mysql/query.go index 09b5259d..7544bc03 100644 --- a/services/statistics-service/internal/storage/mysql/query.go +++ b/services/statistics-service/internal/storage/mysql/query.go @@ -241,9 +241,8 @@ func (r *Repository) queryAppDayOverviewTotals(ctx context.Context, app, startDa args = append(args, countryID) } if regionID > 0 { - // 旧统计行曾把 region_id 写入 country_id;兼容分支只服务历史读数,新事件写入后会走显式 region_id。 - filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND region_id = ?" + args = append(args, regionID) } row := r.db.QueryRowContext(ctx, ` SELECT COALESCE(SUM(new_users),0), COALESCE(SUM(active_users),0), COALESCE(SUM(paid_users),0), @@ -272,8 +271,8 @@ func (r *Repository) queryNewPaidUsers(ctx context.Context, app, startDay, endDa } if regionID > 0 { // p 表和 r 表都已经是统计小表,这里只按充值发生地过滤,保证新增付费用户口径和付费用户卡片一致。 - filter += " AND (p.region_id = ? OR (p.region_id = 0 AND p.country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND p.region_id = ?" + args = append(args, regionID) } row := r.db.QueryRowContext(ctx, ` SELECT COUNT(DISTINCT p.user_id) @@ -296,9 +295,8 @@ func (r *Repository) queryDailySeries(ctx context.Context, app, startDay, endDay args = append(args, countryID) } if regionID > 0 { - // 和总览一致兼容历史 region_id 写到 country_id 的聚合行;新数据优先读显式 region_id。 - filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND region_id = ?" + args = append(args, regionID) } rows, err := r.db.QueryContext(ctx, ` SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), @@ -355,8 +353,8 @@ func (r *Repository) queryDailyNewPaidUsers(ctx context.Context, app, startDay, args = append(args, countryID) } if regionID > 0 { - filter += " AND (p.region_id = ? OR (p.region_id = 0 AND p.country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND p.region_id = ?" + args = append(args, regionID) } rows, err := r.db.QueryContext(ctx, ` SELECT DATE_FORMAT(p.stat_day, '%Y-%m-%d'), COUNT(DISTINCT p.user_id) @@ -442,8 +440,8 @@ func (r *Repository) queryRetention(ctx context.Context, app, startDay, endDay s args = append(args, countryID) } if regionID > 0 { - filter += " AND (r.region_id = ? OR (r.region_id = 0 AND r.country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND r.region_id = ?" + args = append(args, regionID) } row := r.db.QueryRowContext(ctx, ` SELECT COUNT(*), @@ -470,8 +468,8 @@ func (r *Repository) queryGameRanking(ctx context.Context, app, startDay, endDay args = append(args, countryID) } if regionID > 0 { - filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND region_id = ?" + args = append(args, regionID) } rows, err := r.db.QueryContext(ctx, ` SELECT platform_code, game_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0), @@ -502,8 +500,8 @@ func (r *Repository) queryCountryBreakdown(ctx context.Context, app, startDay, e args := []any{app, startDay, endDay} filter := "" if regionID > 0 { - filter = " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" - args = append(args, regionID, regionID) + filter = " AND region_id = ?" + args = append(args, regionID) } rows, err := r.db.QueryContext(ctx, ` SELECT country_id, COALESCE(MAX(region_id),0), @@ -561,8 +559,8 @@ func (r *Repository) queryLuckyGiftPools(ctx context.Context, app, startDay, end args = append(args, countryID) } if regionID > 0 { - filter += " AND (region_id = ? OR (region_id = 0 AND country_id = ?))" - args = append(args, regionID, regionID) + filter += " AND region_id = ?" + args = append(args, regionID) } rows, err := r.db.QueryContext(ctx, ` SELECT pool_id, COALESCE(SUM(turnover_coin),0), COALESCE(SUM(payout_coin),0) diff --git a/services/statistics-service/internal/storage/mysql/repository.go b/services/statistics-service/internal/storage/mysql/repository.go index 9b0ca68b..3c10b6a9 100644 --- a/services/statistics-service/internal/storage/mysql/repository.go +++ b/services/statistics-service/internal/storage/mysql/repository.go @@ -113,7 +113,7 @@ func (r *Repository) Migrate(ctx context.Context) error { lucky_gift_turnover BIGINT NOT NULL DEFAULT 0, lucky_gift_payout BIGINT NOT NULL DEFAULT 0, lucky_gift_payers BIGINT NOT NULL DEFAULT 0, game_turnover BIGINT NOT NULL DEFAULT 0, game_players BIGINT NOT NULL DEFAULT 0, game_payout BIGINT NOT NULL DEFAULT 0, game_refund BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id), KEY idx_stat_app_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_user_day_activity ( @@ -150,7 +150,7 @@ func (r *Repository) Migrate(ctx context.Context) error { region_id BIGINT NOT NULL DEFAULT 0, pool_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, payout_coin BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, pool_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id, pool_id), KEY idx_stat_lucky_pool_overview (app_code, stat_day, pool_id), KEY idx_stat_lucky_pool_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, @@ -160,7 +160,7 @@ func (r *Repository) Migrate(ctx context.Context) error { platform_code VARCHAR(64) NOT NULL DEFAULT '', game_id VARCHAR(96) NOT NULL, turnover_coin BIGINT NOT NULL DEFAULT 0, payout_coin BIGINT NOT NULL DEFAULT 0, refund_coin BIGINT NOT NULL DEFAULT 0, player_count BIGINT NOT NULL DEFAULT 0, updated_at_ms BIGINT NOT NULL, - PRIMARY KEY (app_code, stat_day, country_id, platform_code, game_id), + PRIMARY KEY (app_code, stat_day, country_id, region_id, platform_code, game_id), KEY idx_stat_game_day_region (app_code, stat_day, region_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci`, `CREATE TABLE IF NOT EXISTS stat_game_day_players ( @@ -205,9 +205,60 @@ func (r *Repository) Migrate(ctx context.Context) error { return err } } + for table, columns := range map[string][]string{ + "stat_app_day_country": {"app_code", "stat_day", "country_id", "region_id"}, + "stat_lucky_gift_pool_day_country": {"app_code", "stat_day", "country_id", "region_id", "pool_id"}, + "stat_game_day_country": {"app_code", "stat_day", "country_id", "region_id", "platform_code", "game_id"}, + } { + if err := r.ensurePrimaryKeyColumns(ctx, table, columns); err != nil { + return err + } + } return nil } +func (r *Repository) ensurePrimaryKeyColumns(ctx context.Context, table string, expected []string) error { + rows, err := r.db.QueryContext(ctx, ` + SELECT COLUMN_NAME + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND CONSTRAINT_NAME = 'PRIMARY' + ORDER BY ORDINAL_POSITION`, table) + if err != nil { + return err + } + defer rows.Close() + + actual := make([]string, 0, len(expected)) + for rows.Next() { + var column string + if err := rows.Scan(&column); err != nil { + return err + } + actual = append(actual, column) + } + if err := rows.Err(); err != nil { + return err + } + if sameStringSlice(actual, expected) { + return nil + } + // 统计聚合表必须同时以国家和区域做主键;否则区域筛选和国家筛选会写入同一行,导致阿富汗这类历史错位国家继续污染榜单。 + _, err = r.db.ExecContext(ctx, "ALTER TABLE "+table+" DROP PRIMARY KEY, ADD PRIMARY KEY ("+strings.Join(expected, ", ")+")") + return err +} + +func sameStringSlice(left, right []string) bool { + if len(left) != len(right) { + return false + } + for index := range left { + if left[index] != right[index] { + return false + } + } + return true +} + type UserRegisteredEvent struct { AppCode string EventID string @@ -305,8 +356,8 @@ func (r *Repository) ConsumeUserRegistered(ctx context.Context, event UserRegist _, err := tx.ExecContext(ctx, ` UPDATE stat_app_day_country SET new_users = new_users + 1, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -350,8 +401,8 @@ func (r *Repository) ConsumeRecharge(ctx context.Context, event RechargeEvent) e coin_seller_transfer_coin = coin_seller_transfer_coin + ?, paid_users = paid_users + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.USDMinor, newUserUSD, coinSellerUSD, mifapayUSD, googleUSD, coinSellerTransferCoin, paidUsers, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, event.USDMinor, newUserUSD, coinSellerUSD, mifapayUSD, googleUSD, coinSellerTransferCoin, paidUsers, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -369,8 +420,8 @@ func (r *Repository) ConsumeCoinSellerStock(ctx context.Context, event CoinSelle SET recharge_usd_minor = recharge_usd_minor + ?, coin_seller_recharge_usd_minor = coin_seller_recharge_usd_minor + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.USDMinor, event.USDMinor, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, event.USDMinor, event.USDMinor, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -401,8 +452,8 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e if _, err := tx.ExecContext(ctx, ` UPDATE stat_lucky_gift_pool_day_country SET turnover_coin = turnover_coin + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? AND pool_id = ? - `, luckyTurnover, nowMS, appcode.Normalize(event.AppCode), day, countryID, poolID); err != nil { + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? AND pool_id = ? + `, luckyTurnover, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID, poolID); err != nil { return err } } @@ -410,8 +461,8 @@ func (r *Repository) ConsumeRoomGift(ctx context.Context, event RoomGiftEvent) e UPDATE stat_app_day_country SET gift_coin_spent = gift_coin_spent + ?, lucky_gift_turnover = lucky_gift_turnover + ?, lucky_gift_payers = lucky_gift_payers + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.CoinSpent, luckyTurnover, luckyPayers, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, event.CoinSpent, luckyTurnover, luckyPayers, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -432,16 +483,16 @@ func (r *Repository) ConsumeLuckyGiftReward(ctx context.Context, event LuckyGift if _, err := tx.ExecContext(ctx, ` UPDATE stat_lucky_gift_pool_day_country SET payout_coin = payout_coin + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? AND pool_id = ? - `, event.Amount, nowMS, appcode.Normalize(event.AppCode), day, countryID, poolID); err != nil { + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? AND pool_id = ? + `, event.Amount, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID, poolID); err != nil { return err } } _, err := tx.ExecContext(ctx, ` UPDATE stat_app_day_country SET lucky_gift_payout = lucky_gift_payout + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, event.Amount, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, event.Amount, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -490,16 +541,16 @@ func (r *Repository) ConsumeGameOrder(ctx context.Context, event GameOrderEvent) UPDATE stat_game_day_country SET turnover_coin = turnover_coin + ?, payout_coin = payout_coin + ?, refund_coin = refund_coin + ?, player_count = player_count + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? AND platform_code = ? AND game_id = ? - `, turnover, payout, refund, playerDelta, nowMS, appcode.Normalize(event.AppCode), day, countryID, event.PlatformCode, event.GameID); err != nil { + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? AND platform_code = ? AND game_id = ? + `, turnover, payout, refund, playerDelta, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID, event.PlatformCode, event.GameID); err != nil { return err } _, err := tx.ExecContext(ctx, ` UPDATE stat_app_day_country SET game_turnover = game_turnover + ?, game_payout = game_payout + ?, game_refund = game_refund + ?, game_players = game_players + ?, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, turnover, payout, refund, playerDelta, nowMS, appcode.Normalize(event.AppCode), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, turnover, payout, refund, playerDelta, nowMS, appcode.Normalize(event.AppCode), day, countryID, regionID) return err }) } @@ -596,8 +647,8 @@ func applyActive(ctx context.Context, tx *sql.Tx, app string, day string, countr _, err = tx.ExecContext(ctx, ` UPDATE stat_app_day_country SET active_users = active_users + 1, updated_at_ms = ? - WHERE app_code = ? AND stat_day = ? AND country_id = ? - `, nowMS, appcode.Normalize(app), day, countryID) + WHERE app_code = ? AND stat_day = ? AND country_id = ? AND region_id = ? + `, nowMS, appcode.Normalize(app), day, countryID, regionID) return err } @@ -606,7 +657,6 @@ func ensureAppDay(ctx context.Context, tx *sql.Tx, app string, day string, count INSERT INTO stat_app_day_country (app_code, stat_day, country_id, region_id, updated_at_ms) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), updated_at_ms = VALUES(updated_at_ms) `, appcode.Normalize(app), day, countryID, regionID, nowMS) return err @@ -617,7 +667,6 @@ func ensureGameDay(ctx context.Context, tx *sql.Tx, app string, day string, coun INSERT INTO stat_game_day_country (app_code, stat_day, country_id, region_id, platform_code, game_id, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), updated_at_ms = VALUES(updated_at_ms) `, appcode.Normalize(app), day, countryID, regionID, platformCode, gameID, nowMS) return err @@ -628,7 +677,6 @@ func ensureLuckyGiftPoolDay(ctx context.Context, tx *sql.Tx, app string, day str INSERT INTO stat_lucky_gift_pool_day_country (app_code, stat_day, country_id, region_id, pool_id, updated_at_ms) VALUES (?, ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE - region_id = IF(region_id = 0 AND VALUES(region_id) > 0, VALUES(region_id), region_id), updated_at_ms = VALUES(updated_at_ms) `, appcode.Normalize(app), day, countryID, regionID, strings.TrimSpace(poolID), nowMS) return err diff --git a/services/wallet-service/internal/domain/ledger/ledger.go b/services/wallet-service/internal/domain/ledger/ledger.go index 36e675a7..7f48c84e 100644 --- a/services/wallet-service/internal/domain/ledger/ledger.go +++ b/services/wallet-service/internal/domain/ledger/ledger.go @@ -243,14 +243,15 @@ type HostSalaryProgress struct { // CoinSellerTransferCommand 是币商给玩家转普通金币的账务命令。 type CoinSellerTransferCommand struct { - AppCode string - CommandID string - SellerUserID int64 - TargetUserID int64 - SellerRegionID int64 - TargetRegionID int64 - Amount int64 - Reason string + AppCode string + CommandID string + SellerUserID int64 + TargetUserID int64 + TargetCountryID int64 + SellerRegionID int64 + TargetRegionID int64 + Amount int64 + Reason string } // CoinSellerTransferReceipt 是币商转账完成后的稳定回执。 @@ -335,6 +336,8 @@ type CoinSellerStockCreditCommand struct { AppCode string CommandID string SellerUserID int64 + SellerCountryID int64 + SellerRegionID int64 StockType string CoinAmount int64 PaidCurrencyCode string @@ -349,6 +352,8 @@ type CoinSellerStockCreditCommand struct { type CoinSellerStockCreditReceipt struct { TransactionID string SellerUserID int64 + SellerCountryID int64 + SellerRegionID int64 StockType string CoinAmount int64 PaidCurrencyCode string diff --git a/services/wallet-service/internal/service/wallet/service.go b/services/wallet-service/internal/service/wallet/service.go index 58a1841b..b9f5a6b3 100644 --- a/services/wallet-service/internal/service/wallet/service.go +++ b/services/wallet-service/internal/service/wallet/service.go @@ -315,6 +315,9 @@ func (s *Service) AdminCreditCoinSellerStock(ctx context.Context, command ledger if command.CommandID == "" || command.SellerUserID <= 0 || command.OperatorUserID <= 0 { return ledger.CoinSellerStockCreditReceipt{}, xerr.New(xerr.InvalidArgument, "coin seller stock command is incomplete") } + if command.SellerCountryID <= 0 || command.SellerRegionID <= 0 { + return ledger.CoinSellerStockCreditReceipt{}, xerr.New(xerr.InvalidArgument, "seller country and region are required") + } if len(command.CommandID) > 128 { return ledger.CoinSellerStockCreditReceipt{}, xerr.New(xerr.InvalidArgument, "command_id is too long") } @@ -364,6 +367,9 @@ func (s *Service) TransferCoinFromSeller(ctx context.Context, command ledger.Coi if command.SellerRegionID <= 0 || command.TargetRegionID <= 0 { return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.InvalidArgument, "seller and target region are required") } + if command.TargetCountryID <= 0 { + return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.InvalidArgument, "target country is required") + } if command.SellerRegionID != command.TargetRegionID { return ledger.CoinSellerTransferReceipt{}, xerr.New(xerr.Conflict, "seller and target region must match") } diff --git a/services/wallet-service/internal/service/wallet/service_test.go b/services/wallet-service/internal/service/wallet/service_test.go index b9a6c32b..da858a91 100644 --- a/services/wallet-service/internal/service/wallet/service_test.go +++ b/services/wallet-service/internal/service/wallet/service_test.go @@ -1448,14 +1448,15 @@ func TestWalletOutboxClaimUsesRealMySQLStatusFlow(t *testing.T) { ctx := appcode.WithContext(context.Background(), "lalu") receipt, err := svc.TransferCoinFromSeller(ctx, ledger.CoinSellerTransferCommand{ - AppCode: "lalu", - CommandID: "cmd-real-outbox-transfer", - SellerUserID: 30001, - TargetUserID: 30002, - SellerRegionID: 86, - TargetRegionID: 86, - Amount: 200, - Reason: "real outbox claim test", + AppCode: "lalu", + CommandID: "cmd-real-outbox-transfer", + SellerUserID: 30001, + TargetUserID: 30002, + TargetCountryID: 63, + SellerRegionID: 86, + TargetRegionID: 86, + Amount: 200, + Reason: "real outbox claim test", }) if err != nil { t.Fatalf("TransferCoinFromSeller failed: %v", err) @@ -1593,13 +1594,14 @@ func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { } command := ledger.CoinSellerTransferCommand{ - CommandID: "cmd-seller-transfer", - SellerUserID: 30001, - TargetUserID: 30002, - SellerRegionID: 1001, - TargetRegionID: 1001, - Amount: 80000, - Reason: "player recharge", + CommandID: "cmd-seller-transfer", + SellerUserID: 30001, + TargetUserID: 30002, + TargetCountryID: 63, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 80000, + Reason: "player recharge", } first, err := svc.TransferCoinFromSeller(context.Background(), command) if err != nil { @@ -1639,6 +1641,9 @@ func TestTransferCoinFromSellerMovesDedicatedAssetToPlayerCoin(t *testing.T) { if got := repository.CountRows("wallet_outbox", "transaction_id = ?", first.TransactionID); got != 4 { t.Fatalf("seller transfer should write two balance events, one transfer event and one recharge event, got %d", got) } + if got := repository.CountRows("wallet_outbox", "transaction_id = ? AND event_type = ? AND JSON_EXTRACT(payload_json, '$.target_country_id') = 63 AND JSON_EXTRACT(payload_json, '$.country_id') = 63 AND JSON_EXTRACT(payload_json, '$.target_region_id') = 1001", first.TransactionID, "WalletRechargeRecorded"); got != 1 { + t.Fatalf("seller transfer recharge event must carry target country/region for statistics, got %d", got) + } } // TestTransferCoinFromSellerAllowsSelfTransfer 验证币商可以把自己的专用库存转入自己的普通金币账户。 @@ -1659,13 +1664,14 @@ func TestTransferCoinFromSellerAllowsSelfTransfer(t *testing.T) { } command := ledger.CoinSellerTransferCommand{ - CommandID: "cmd-seller-self-transfer", - SellerUserID: 30003, - TargetUserID: 30003, - SellerRegionID: 1001, - TargetRegionID: 1001, - Amount: 30000, - Reason: "self recharge", + CommandID: "cmd-seller-self-transfer", + SellerUserID: 30003, + TargetUserID: 30003, + TargetCountryID: 63, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 30000, + Reason: "self recharge", } first, err := svc.TransferCoinFromSeller(context.Background(), command) if err != nil { @@ -1718,13 +1724,14 @@ func TestTransferCoinFromSellerRecordsCoinsWithoutUSDConversion(t *testing.T) { } receipt, err := svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ - CommandID: "cmd-seller-small-transfer", - SellerUserID: 30004, - TargetUserID: 30004, - SellerRegionID: 1001, - TargetRegionID: 1001, - Amount: 1, - Reason: "self recharge", + CommandID: "cmd-seller-small-transfer", + SellerUserID: 30004, + TargetUserID: 30004, + TargetCountryID: 63, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 1, + Reason: "self recharge", }) if err != nil { t.Fatalf("TransferCoinFromSeller small amount failed: %v", err) @@ -1750,13 +1757,14 @@ func TestTransferCoinFromSellerInsufficientBalance(t *testing.T) { svc := walletservice.New(repository) _, err := svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ - CommandID: "cmd-seller-low", - SellerUserID: 31001, - TargetUserID: 31002, - SellerRegionID: 1001, - TargetRegionID: 1001, - Amount: 1, - Reason: "player recharge", + CommandID: "cmd-seller-low", + SellerUserID: 31001, + TargetUserID: 31002, + TargetCountryID: 63, + SellerRegionID: 1001, + TargetRegionID: 1001, + Amount: 1, + Reason: "player recharge", }) if !xerr.IsCode(err, xerr.InsufficientBalance) { t.Fatalf("expected INSUFFICIENT_BALANCE, got %v", err) @@ -1784,13 +1792,14 @@ func TestTransferCoinFromSellerDoesNotRequireRechargePolicy(t *testing.T) { } receipt, err := svc.TransferCoinFromSeller(context.Background(), ledger.CoinSellerTransferCommand{ - CommandID: "cmd-seller-no-policy", - SellerUserID: 32001, - TargetUserID: 32002, - SellerRegionID: 2001, - TargetRegionID: 2001, - Amount: 80000, - Reason: "player recharge", + CommandID: "cmd-seller-no-policy", + SellerUserID: 32001, + TargetUserID: 32002, + TargetCountryID: 63, + SellerRegionID: 2001, + TargetRegionID: 2001, + Amount: 80000, + Reason: "player recharge", }) if err != nil { t.Fatalf("TransferCoinFromSeller without recharge policy failed: %v", err) @@ -1945,6 +1954,8 @@ func TestAdminCreditCoinSellerStockPurchaseCreditsDedicatedBalance(t *testing.T) command := ledger.CoinSellerStockCreditCommand{ CommandID: "cmd-stock-usdt", SellerUserID: 33001, + SellerCountryID: 63, + SellerRegionID: 7, StockType: ledger.StockTypeUSDTPurchase, CoinAmount: 8000000, PaidAmountMicro: 100000000, @@ -1982,6 +1993,9 @@ func TestAdminCreditCoinSellerStockPurchaseCreditsDedicatedBalance(t *testing.T) if got := repository.CountRows("wallet_outbox", "transaction_id = ?", first.TransactionID); got != 2 { t.Fatalf("stock purchase should write balance and stock outbox events, got %d", got) } + if got := repository.CountRows("wallet_outbox", "transaction_id = ? AND event_type = ? AND JSON_EXTRACT(payload_json, '$.seller_country_id') = 63 AND JSON_EXTRACT(payload_json, '$.seller_region_id') = 7 AND JSON_EXTRACT(payload_json, '$.country_id') = 63 AND JSON_EXTRACT(payload_json, '$.region_id') = 7", first.TransactionID, "WalletCoinSellerStockPurchased"); got != 1 { + t.Fatalf("stock outbox must carry seller country/region for statistics, got %d", got) + } } // TestAdminCreditCoinSellerStockCompensationRejectsPaidAmount 锁定补偿不能携带充值金额的边界。 @@ -1991,6 +2005,8 @@ func TestAdminCreditCoinSellerStockCompensationRejectsPaidAmount(t *testing.T) { _, err := svc.AdminCreditCoinSellerStock(context.Background(), ledger.CoinSellerStockCreditCommand{ CommandID: "cmd-stock-comp-invalid", SellerUserID: 34001, + SellerCountryID: 63, + SellerRegionID: 7, StockType: ledger.StockTypeCoinCompensation, CoinAmount: 50000, PaidCurrencyCode: ledger.PaidCurrencyUSDT, @@ -2010,11 +2026,13 @@ func TestAdminCreditCoinSellerStockCompensationCreditsWithoutRechargeAmount(t *t repository := mysqltest.NewRepository(t) svc := walletservice.New(repository) receipt, err := svc.AdminCreditCoinSellerStock(context.Background(), ledger.CoinSellerStockCreditCommand{ - CommandID: "cmd-stock-comp", - SellerUserID: 35001, - StockType: ledger.StockTypeCoinCompensation, - CoinAmount: 50000, - OperatorUserID: 90001, + CommandID: "cmd-stock-comp", + SellerUserID: 35001, + SellerCountryID: 63, + SellerRegionID: 7, + StockType: ledger.StockTypeCoinCompensation, + CoinAmount: 50000, + OperatorUserID: 90001, }) if err != nil { t.Fatalf("AdminCreditCoinSellerStock compensation failed: %v", err) @@ -2034,6 +2052,8 @@ func TestAdminCreditCoinSellerStockRejectsDuplicatePaymentRef(t *testing.T) { command := ledger.CoinSellerStockCreditCommand{ CommandID: "cmd-stock-ref-1", SellerUserID: 36001, + SellerCountryID: 63, + SellerRegionID: 7, StockType: ledger.StockTypeUSDTPurchase, CoinAmount: 100, PaidAmountMicro: 1000000, @@ -2047,6 +2067,8 @@ func TestAdminCreditCoinSellerStockRejectsDuplicatePaymentRef(t *testing.T) { } command.CommandID = "cmd-stock-ref-2" command.SellerUserID = 36002 + command.SellerCountryID = 971 + command.SellerRegionID = 8 command.EvidenceRef = "oss://receipt-dup-2" _, err := svc.AdminCreditCoinSellerStock(context.Background(), command) if !xerr.IsCode(err, xerr.CoinSellerPaymentRefDuplicated) { @@ -2064,6 +2086,8 @@ func TestAdminCreditCoinSellerStockRejectsIdempotencyConflict(t *testing.T) { command := ledger.CoinSellerStockCreditCommand{ CommandID: "cmd-stock-conflict", SellerUserID: 37001, + SellerCountryID: 63, + SellerRegionID: 7, StockType: ledger.StockTypeUSDTPurchase, CoinAmount: 100, PaidAmountMicro: 1000000, diff --git a/services/wallet-service/internal/storage/mysql/repository.go b/services/wallet-service/internal/storage/mysql/repository.go index 0fa8e925..f826050f 100644 --- a/services/wallet-service/internal/storage/mysql/repository.go +++ b/services/wallet-service/internal/storage/mysql/repository.go @@ -1142,6 +1142,8 @@ func (r *Repository) AdminCreditCoinSellerStock(ctx context.Context, command led metadata := coinSellerStockMetadata{ AppCode: command.AppCode, SellerUserID: command.SellerUserID, + SellerCountryID: command.SellerCountryID, + SellerRegionID: command.SellerRegionID, StockType: command.StockType, CoinAmount: command.CoinAmount, PaidCurrencyCode: command.PaidCurrencyCode, @@ -1241,6 +1243,7 @@ func (r *Repository) TransferCoinFromSeller(ctx context.Context, command ledger. AppCode: command.AppCode, SellerUserID: command.SellerUserID, TargetUserID: command.TargetUserID, + TargetCountryID: command.TargetCountryID, SellerRegionID: command.SellerRegionID, TargetRegionID: command.TargetRegionID, Amount: command.Amount, @@ -2676,6 +2679,7 @@ type coinSellerTransferMetadata struct { AppCode string `json:"app_code"` SellerUserID int64 `json:"seller_user_id"` TargetUserID int64 `json:"target_user_id"` + TargetCountryID int64 `json:"target_country_id"` SellerRegionID int64 `json:"seller_region_id"` TargetRegionID int64 `json:"target_region_id"` Amount int64 `json:"amount"` @@ -2728,6 +2732,8 @@ type salaryTransferToCoinSellerMetadata struct { type coinSellerStockMetadata struct { AppCode string `json:"app_code"` SellerUserID int64 `json:"seller_user_id"` + SellerCountryID int64 `json:"seller_country_id"` + SellerRegionID int64 `json:"seller_region_id"` StockType string `json:"stock_type"` CoinAmount int64 `json:"coin_amount"` PaidCurrencyCode string `json:"paid_currency_code"` @@ -2889,13 +2895,14 @@ func receiptFromGameMetadata(transactionID string, metadata gameCoinMetadata, id func (r *Repository) receiptForCoinSellerStockTransaction(ctx context.Context, tx *sql.Tx, transactionID string) (ledger.CoinSellerStockCreditReceipt, error) { row := tx.QueryRowContext(ctx, `SELECT seller_user_id, stock_type, coin_amount, paid_currency_code, paid_amount_micro, - counts_as_seller_recharge, balance_after, created_at_ms + counts_as_seller_recharge, balance_after, metadata_json, created_at_ms FROM coin_seller_stock_records WHERE app_code = ? AND transaction_id = ?`, appcode.FromContext(ctx), transactionID, ) var receipt ledger.CoinSellerStockCreditReceipt + var metadataJSON string if err := row.Scan( &receipt.SellerUserID, &receipt.StockType, @@ -2904,10 +2911,18 @@ func (r *Repository) receiptForCoinSellerStockTransaction(ctx context.Context, t &receipt.PaidAmountMicro, &receipt.CountsAsSellerRecharge, &receipt.BalanceAfter, + &metadataJSON, &receipt.CreatedAtMS, ); err != nil { return ledger.CoinSellerStockCreditReceipt{}, err } + if metadataJSON != "" { + var metadata coinSellerStockMetadata + if err := json.Unmarshal([]byte(metadataJSON), &metadata); err == nil { + receipt.SellerCountryID = metadata.SellerCountryID + receipt.SellerRegionID = metadata.SellerRegionID + } + } receipt.TransactionID = transactionID return receipt, nil } @@ -2916,6 +2931,8 @@ func receiptFromCoinSellerStockMetadata(transactionID string, metadata coinSelle return ledger.CoinSellerStockCreditReceipt{ TransactionID: transactionID, SellerUserID: metadata.SellerUserID, + SellerCountryID: metadata.SellerCountryID, + SellerRegionID: metadata.SellerRegionID, StockType: metadata.StockType, CoinAmount: metadata.CoinAmount, PaidCurrencyCode: metadata.PaidCurrencyCode, @@ -3070,6 +3087,34 @@ func coinSellerTransferredEvent(transactionID string, commandID string, sellerUs } func rechargeRecordedEvent(transactionID string, commandID string, targetUserID int64, availableDelta int64, payload any, nowMs int64) walletOutboxEvent { + if metadata, ok := payload.(coinSellerTransferMetadata); ok { + // WalletRechargeRecorded 是统计服务的充值入口;币商转账没有 USDT 金额,但必须带目标用户真实国家/区域,避免统计继续把 region 当 country。 + payload = map[string]any{ + "app_code": metadata.AppCode, + "seller_user_id": metadata.SellerUserID, + "target_user_id": metadata.TargetUserID, + "target_country_id": metadata.TargetCountryID, + "country_id": metadata.TargetCountryID, + "seller_region_id": metadata.SellerRegionID, + "target_region_id": metadata.TargetRegionID, + "region_id": metadata.TargetRegionID, + "amount": metadata.Amount, + "reason": metadata.Reason, + "seller_asset_type": metadata.SellerAssetType, + "target_asset_type": metadata.TargetAssetType, + "seller_balance_after": metadata.SellerBalanceAfter, + "target_balance_after": metadata.TargetBalanceAfter, + "recharge_sequence": metadata.RechargeSequence, + "recharge_usd_minor": metadata.RechargeUSDMinor, + "recharge_currency_code": metadata.RechargeCurrencyCode, + "recharge_policy_id": metadata.RechargePolicyID, + "recharge_policy_version": metadata.RechargePolicyVersion, + "recharge_policy_coin_amount": metadata.RechargePolicyCoinAmount, + "recharge_policy_usd_minor_amount": metadata.RechargePolicyUSDMinorAmount, + "recharge_type": "coin_seller_transfer", + "created_at_ms": nowMs, + } + } return walletOutboxEvent{ EventID: eventID(transactionID, "WalletRechargeRecorded", targetUserID, ledger.AssetCoin), EventType: "WalletRechargeRecorded", @@ -3184,6 +3229,10 @@ func coinSellerStockCreditedEvent(transactionID string, commandID string, metada "transaction_id": transactionID, "command_id": commandID, "seller_user_id": metadata.SellerUserID, + "seller_country_id": metadata.SellerCountryID, + "seller_region_id": metadata.SellerRegionID, + "country_id": metadata.SellerCountryID, + "region_id": metadata.SellerRegionID, "stock_type": metadata.StockType, "coin_amount": metadata.CoinAmount, "paid_currency_code": metadata.PaidCurrencyCode, @@ -3451,9 +3500,11 @@ func gameBizTypeAndDelta(opType string, coinAmount int64) (string, int64, error) } func coinSellerStockRequestHash(command ledger.CoinSellerStockCreditCommand) string { - return stableHash(fmt.Sprintf("coin_seller_stock|%s|%d|%s|%d|%s|%d|%s|%s|%d|%s", + return stableHash(fmt.Sprintf("coin_seller_stock|%s|%d|%d|%d|%s|%d|%s|%d|%s|%s|%d|%s", appcode.Normalize(command.AppCode), command.SellerUserID, + command.SellerCountryID, + command.SellerRegionID, command.StockType, command.CoinAmount, command.PaidCurrencyCode, diff --git a/services/wallet-service/internal/transport/grpc/server.go b/services/wallet-service/internal/transport/grpc/server.go index 0e7d80d6..a5af7b6d 100644 --- a/services/wallet-service/internal/transport/grpc/server.go +++ b/services/wallet-service/internal/transport/grpc/server.go @@ -842,6 +842,8 @@ func (s *Server) AdminCreditCoinSellerStock(ctx context.Context, req *walletv1.A AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), SellerUserID: req.GetSellerUserId(), + SellerCountryID: req.GetSellerCountryId(), + SellerRegionID: req.GetSellerRegionId(), StockType: req.GetStockType(), CoinAmount: req.GetCoinAmount(), PaidCurrencyCode: req.GetPaidCurrencyCode(), @@ -872,14 +874,15 @@ func (s *Server) AdminCreditCoinSellerStock(ctx context.Context, req *walletv1.A func (s *Server) TransferCoinFromSeller(ctx context.Context, req *walletv1.TransferCoinFromSellerRequest) (*walletv1.TransferCoinFromSellerResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.TransferCoinFromSeller(ctx, ledger.CoinSellerTransferCommand{ - AppCode: req.GetAppCode(), - CommandID: req.GetCommandId(), - SellerUserID: req.GetSellerUserId(), - TargetUserID: req.GetTargetUserId(), - SellerRegionID: req.GetSellerRegionId(), - TargetRegionID: req.GetTargetRegionId(), - Amount: req.GetAmount(), - Reason: req.GetReason(), + AppCode: req.GetAppCode(), + CommandID: req.GetCommandId(), + SellerUserID: req.GetSellerUserId(), + TargetUserID: req.GetTargetUserId(), + TargetCountryID: req.GetTargetCountryId(), + SellerRegionID: req.GetSellerRegionId(), + TargetRegionID: req.GetTargetRegionId(), + Amount: req.GetAmount(), + Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) From 40fa44eaa5112b96c41fccb1d06ebba437b47eb9 Mon Sep 17 00:00:00 2001 From: zhx Date: Mon, 8 Jun 2026 12:29:17 +0800 Subject: [PATCH 28/28] Fix databi backfill active day formatting --- services/statistics-service/cmd/backfill-last7/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/statistics-service/cmd/backfill-last7/main.go b/services/statistics-service/cmd/backfill-last7/main.go index 784a9c6c..69d11e69 100644 --- a/services/statistics-service/cmd/backfill-last7/main.go +++ b/services/statistics-service/cmd/backfill-last7/main.go @@ -356,7 +356,7 @@ func rebuildRegistrations(ctx context.Context, db *sql.DB, state *rebuildState, func rebuildActive(ctx context.Context, db *sql.DB, state *rebuildState, app, startDay, endDay string) error { // 活跃的原始房间事件已经被实时消费进 stat_user_day_activity;离线回填只重刷该表的国家/区域快照,避免在大窗口内扫描房间流水。 rows, err := db.QueryContext(ctx, ` - SELECT stat_day, user_id, MIN(first_active_at_ms) + SELECT DATE_FORMAT(stat_day, '%Y-%m-%d'), user_id, MIN(first_active_at_ms) FROM stat_user_day_activity WHERE app_code = ? AND stat_day BETWEEN ? AND ? GROUP BY stat_day, user_id`,